mirror of
https://git.wownero.com/wownero/wownero.git
synced 2025-01-08 21:28:52 +00:00
Merge pull request 'upstream' (#351) from wowario/wownero:up into master
Reviewed-on: https://git.wownero.com/wownero/wownero/pulls/351
This commit is contained in:
commit
90fbc9b181
1
.gitignore
vendored
1
.gitignore
vendored
@ -23,6 +23,7 @@ cscope.po.out
|
||||
external/miniupnpc/Makefile
|
||||
miniupnpcstrings.h
|
||||
version/
|
||||
ClangBuildAnalyzerSession.txt
|
||||
# Created by https://www.gitignore.io
|
||||
|
||||
### C++ ###
|
||||
|
@ -54,6 +54,13 @@ if (USE_CCACHE)
|
||||
else()
|
||||
message(STATUS "ccache deselected")
|
||||
endif()
|
||||
option (USE_COMPILATION_TIME_PROFILER "Use compilation time profiler (for CLang >= 9 only)" OFF)
|
||||
if (USE_COMPILATION_TIME_PROFILER)
|
||||
if (NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
message(FATAL_ERROR "The flag USE_COMPILATION_TIME_PROFILER is meant to be set only for CLang compiler!")
|
||||
endif()
|
||||
add_compile_options("-ftime-trace")
|
||||
endif()
|
||||
|
||||
# Job pool feature requires Ninja.
|
||||
if (${CMAKE_VERSION} VERSION_GREATER "3.0.0")
|
||||
@ -68,6 +75,20 @@ if (${CMAKE_VERSION} VERSION_GREATER "3.0.0")
|
||||
set_property(GLOBAL APPEND PROPERTY JOB_POOLS link_job_pool=${WOWNERO_PARALLEL_LINK_JOBS})
|
||||
set(CMAKE_JOB_POOL_LINK link_job_pool)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
option (USE_CLANG_TIDY_C "Lint the code with clang-tidy - variant C" OFF)
|
||||
option (USE_CLANG_TIDY_CXX "Lint the code with clang-tidy - variant C++" OFF)
|
||||
if (USE_CLANG_TIDY_C AND USE_CLANG_TIDY_CXX)
|
||||
message(FATAL_ERROR "Enabling both USE_CLANG_TIDY_C and USE_CLANG_TIDY_CXX simultaneously crashes clang-tidy.")
|
||||
endif()
|
||||
if (USE_CLANG_TIDY_C OR USE_CLANG_TIDY_CXX)
|
||||
include(SetClangTidy)
|
||||
endif()
|
||||
if (USE_CLANG_TIDY_C)
|
||||
monero_clang_tidy("C")
|
||||
elseif (USE_CLANG_TIDY_CXX)
|
||||
monero_clang_tidy("CXX")
|
||||
endif()
|
||||
|
||||
enable_language(C ASM)
|
||||
@ -126,6 +147,24 @@ function (add_definition_if_library_exists library function header var)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
option(RELINK_TARGETS "Relink targets, when just a dependant .so changed, but not its header?" OFF)
|
||||
function (monero_set_target_no_relink target)
|
||||
if (RELINK_TARGETS MATCHES OFF)
|
||||
# Will not relink the target, when just its dependant .so has changed, but not it's interface
|
||||
set_target_properties("${target}" PROPERTIES LINK_DEPENDS_NO_SHARED true)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function (monero_add_minimal_executable name)
|
||||
source_group("${name}"
|
||||
FILES
|
||||
${ARGN})
|
||||
|
||||
add_executable("${name}"
|
||||
${ARGN})
|
||||
monero_set_target_no_relink( ${name} )
|
||||
endfunction()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
|
||||
message(STATUS "Setting default build type: ${CMAKE_BUILD_TYPE}")
|
||||
|
@ -48,29 +48,21 @@ function (get_version_tag_from_git GIT)
|
||||
message(STATUS "You are currently on commit ${COMMIT}")
|
||||
|
||||
# Get all the tags
|
||||
execute_process(COMMAND "${GIT}" rev-list --tags --max-count=1 --abbrev-commit
|
||||
execute_process(COMMAND "${GIT}" tag -l --points-at HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
RESULT_VARIABLE RET
|
||||
OUTPUT_VARIABLE TAGGEDCOMMIT
|
||||
OUTPUT_VARIABLE TAG
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
if(NOT TAGGEDCOMMIT)
|
||||
message(WARNING "Cannot determine most recent tag. Make sure that you are building either from a Git working tree or from a source archive.")
|
||||
# Check if we're building that tagged commit or a different one
|
||||
if(TAG)
|
||||
message(STATUS "You are building a tagged release")
|
||||
set(VERSIONTAG "release")
|
||||
set(VERSION_IS_RELEASE "true")
|
||||
else()
|
||||
message(STATUS "You are ahead of or behind a tagged release")
|
||||
set(VERSIONTAG "${COMMIT}")
|
||||
set(VERSION_IS_RELEASE "false")
|
||||
else()
|
||||
message(STATUS "The most recent tag was at ${TAGGEDCOMMIT}")
|
||||
|
||||
# Check if we're building that tagged commit or a different one
|
||||
if(COMMIT STREQUAL TAGGEDCOMMIT)
|
||||
message(STATUS "You are building a tagged release")
|
||||
set(VERSIONTAG "release")
|
||||
set(VERSION_IS_RELEASE "true")
|
||||
else()
|
||||
message(STATUS "You are ahead of or behind a tagged release")
|
||||
set(VERSIONTAG "${COMMIT}")
|
||||
set(VERSION_IS_RELEASE "false")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
72
cmake/SetClangTidy.cmake
Normal file
72
cmake/SetClangTidy.cmake
Normal file
@ -0,0 +1,72 @@
|
||||
# Copyright (c) 2014-2020, 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.
|
||||
|
||||
# https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_CLANG_TIDY.html
|
||||
# This module sets the following variables:
|
||||
# CMAKE_C_CLANG_TIDY
|
||||
# CMAKE_CXX_CLANG_TIDY
|
||||
# when clang-tidy is found in PATH. Afterwards, the code is being linted by the tool.
|
||||
# The checks to be enabled can be manipulated with the variable MONERO_CLANG_TIDY_CHECKS
|
||||
|
||||
macro (monero_clang_tidy LANGUAGE)
|
||||
set(TOOL_NAME "clang-tidy")
|
||||
set(MONERO_CLANG_TIDY_MIN_VERSION "3.6")
|
||||
if(${CMAKE_VERSION} VERSION_LESS "${MONERO_CLANG_TIDY_MIN_VERSION}")
|
||||
message(FATAL_ERROR "Sorry, ${TOOL_NAME} is available for CMake from version ${MONERO_CLANG_TIDY_MIN_VERSION}")
|
||||
else()
|
||||
message(STATUS "Trying to enable ${TOOL_NAME}")
|
||||
find_program(MONERO_CLANG_BIN ${TOOL_NAME})
|
||||
if(NOT MONERO_CLANG_BIN)
|
||||
message(FATAL_ERROR "${TOOL_NAME} not found! Try running: sudo apt install ${TOOL_NAME}")
|
||||
else()
|
||||
message(STATUS "Found ${MONERO_CLANG_BIN}")
|
||||
set(MONERO_CLANG_TIDY_CHECKS
|
||||
-header-filter=.; # By default the headers are excluded. This line enables them.
|
||||
-checks=*; # Currently enabling all checks
|
||||
# An example of selectively enabling checks:
|
||||
#-checks=bugprone-*,cppcoreguidelines-avoid-goto # Have to be in one line :(
|
||||
)
|
||||
# Current list of checks is avaibale under:
|
||||
# https://clang.llvm.org/extra/clang-tidy/
|
||||
if (${LANGUAGE} STREQUAL "C")
|
||||
set(CMAKE_C_CLANG_TIDY
|
||||
${MONERO_CLANG_BIN}; # Mind the semicolon
|
||||
${MONERO_CLANG_TIDY_CHECKS}
|
||||
)
|
||||
elseif (${LANGUAGE} STREQUAL "CXX")
|
||||
set(CMAKE_CXX_CLANG_TIDY
|
||||
${MONERO_CLANG_BIN}; # Mind the semicolon
|
||||
${MONERO_CLANG_TIDY_CHECKS}
|
||||
)
|
||||
else()
|
||||
message(FATAL_ERROR "${TOOL_NAME}: Unsupported language: ${LANGUAGE}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
@ -1,36 +1,31 @@
|
||||
package=openssl
|
||||
$(package)_version=1.0.2r
|
||||
$(package)_download_path=https://ftp.openssl.org/source/old/1.0.2
|
||||
$(package)_version=1.1.1i
|
||||
$(package)_download_path=https://www.openssl.org/source
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=ae51d08bba8a83958e894946f15303ff894d75c2b8bbd44a852b64e3fe11d0d6
|
||||
$(package)_patches=fix_arflags.patch
|
||||
$(package)_sha256_hash=e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_env=AR="$($(package)_ar)" ARFLAGS=$($(package)_arflags) RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)"
|
||||
$(package)_config_env_arm_android=ANDROID_NDK_HOME="$(host_prefix)/native" PATH="$(host_prefix)/native/bin" CC=clang AR=ar RANLIB=ranlib
|
||||
$(package)_config_env_aarch64_android=ANDROID_NDK_HOME="$(host_prefix)/native" PATH="$(host_prefix)/native/bin" CC=clang AR=ar RANLIB=ranlib
|
||||
$(package)_build_env_arm_android=ANDROID_NDK_HOME="$(host_prefix)/native"
|
||||
$(package)_build_env_aarch64_android=ANDROID_NDK_HOME="$(host_prefix)/native"
|
||||
$(package)_config_opts=--prefix=$(host_prefix) --openssldir=$(host_prefix)/etc/openssl
|
||||
$(package)_config_opts+=no-capieng
|
||||
$(package)_config_opts+=no-dso
|
||||
$(package)_config_opts+=no-dtls1
|
||||
$(package)_config_opts+=no-ec_nistp_64_gcc_128
|
||||
$(package)_config_opts+=no-gost
|
||||
$(package)_config_opts+=no-gmp
|
||||
$(package)_config_opts+=no-heartbeats
|
||||
$(package)_config_opts+=no-jpake
|
||||
$(package)_config_opts+=no-krb5
|
||||
$(package)_config_opts+=no-libunbound
|
||||
$(package)_config_opts+=no-md2
|
||||
$(package)_config_opts+=no-rc5
|
||||
$(package)_config_opts+=no-rdrand
|
||||
$(package)_config_opts+=no-rfc3779
|
||||
$(package)_config_opts+=no-rsax
|
||||
$(package)_config_opts+=no-sctp
|
||||
$(package)_config_opts+=no-sha0
|
||||
$(package)_config_opts+=no-shared
|
||||
$(package)_config_opts+=no-ssl-trace
|
||||
$(package)_config_opts+=no-ssl2
|
||||
$(package)_config_opts+=no-ssl3
|
||||
$(package)_config_opts+=no-static_engine
|
||||
$(package)_config_opts+=no-store
|
||||
$(package)_config_opts+=no-unit-test
|
||||
$(package)_config_opts+=no-weak-ssl-ciphers
|
||||
$(package)_config_opts+=no-zlib
|
||||
@ -42,8 +37,8 @@ $(package)_config_opts_x86_64_linux=linux-x86_64
|
||||
$(package)_config_opts_i686_linux=linux-generic32
|
||||
$(package)_config_opts_arm_linux=linux-generic32
|
||||
$(package)_config_opts_aarch64_linux=linux-generic64
|
||||
$(package)_config_opts_arm_android=--static android-armv7 no-asm
|
||||
$(package)_config_opts_aarch64_android=--static android no-asm
|
||||
$(package)_config_opts_arm_android=--static android-arm
|
||||
$(package)_config_opts_aarch64_android=--static android-arm64
|
||||
$(package)_config_opts_riscv64_linux=linux-generic64
|
||||
$(package)_config_opts_mipsel_linux=linux-generic32
|
||||
$(package)_config_opts_mips_linux=linux-generic32
|
||||
@ -55,10 +50,8 @@ $(package)_config_opts_x86_64_freebsd=BSD-x86_64
|
||||
endef
|
||||
|
||||
define $(package)_preprocess_cmds
|
||||
sed -i.old "/define DATE/d" util/mkbuildinf.pl && \
|
||||
sed -i.old "s|engines apps test|engines|" Makefile.org && \
|
||||
sed -i -e "s/-mandroid //" Configure && \
|
||||
patch < $($(package)_patch_dir)/fix_arflags.patch
|
||||
sed -i.old 's|"engines", "apps", "test", "util", "tools", "fuzz"|"engines", "tools"|' Configure && \
|
||||
sed -i -e 's|cflags --sysroot.*",|cflags",|' Configurations/15-android.conf
|
||||
endef
|
||||
|
||||
define $(package)_config_cmds
|
||||
@ -70,7 +63,7 @@ define $(package)_build_cmds
|
||||
endef
|
||||
|
||||
define $(package)_stage_cmds
|
||||
$(MAKE) INSTALL_PREFIX=$($(package)_staging_dir) -j1 install_sw
|
||||
$(MAKE) DESTDIR=$($(package)_staging_dir) -j1 install_sw
|
||||
endef
|
||||
|
||||
define $(package)_postprocess_cmds
|
||||
|
@ -1,24 +0,0 @@
|
||||
--- Makefile.org.O 2019-02-26 14:20:20.000000000 +0000
|
||||
+++ Makefile.org 2019-11-15 13:05:54.370086856 +0000
|
||||
@@ -63,8 +63,8 @@
|
||||
PEX_LIBS=
|
||||
EX_LIBS=
|
||||
EXE_EXT=
|
||||
-ARFLAGS=
|
||||
-AR=ar $(ARFLAGS) r
|
||||
+ARFLAGS= r
|
||||
+AR=ar $(ARFLAGS)
|
||||
RANLIB= ranlib
|
||||
RC= windres
|
||||
NM= nm
|
||||
--- Configure.O 2019-02-26 14:20:20.000000000 +0000
|
||||
+++ Configure 2019-11-16 07:43:14.933990774 +0000
|
||||
@@ -1251,7 +1251,7 @@
|
||||
my $shared_extension = $fields[$idx_shared_extension];
|
||||
my $ranlib = $ENV{'RANLIB'} || $fields[$idx_ranlib];
|
||||
my $ar = $ENV{'AR'} || "ar";
|
||||
-my $arflags = $fields[$idx_arflags];
|
||||
+my $arflags = $ENV{'ARFLAGS'} || $fields[$idx_arflags];
|
||||
my $windres = $ENV{'RC'} || $ENV{'WINDRES'} || "windres";
|
||||
my $multilib = $fields[$idx_multilib];
|
||||
|
@ -58,7 +58,6 @@ namespace epee
|
||||
byte_buffer buffer_; //! Beginning of buffer
|
||||
std::uint8_t* next_write_; //! Current write position
|
||||
const std::uint8_t* end_; //! End of buffer
|
||||
std::size_t increase_size_; //! Minimum buffer size increase
|
||||
|
||||
//! \post `requested <= available()`
|
||||
void overflow(const std::size_t requested);
|
||||
@ -75,29 +74,17 @@ namespace epee
|
||||
using char_type = std::uint8_t;
|
||||
using Ch = char_type;
|
||||
|
||||
//! \return Default minimum size increase on buffer overflow
|
||||
static constexpr std::size_t default_increase() noexcept { return 4096; }
|
||||
|
||||
//! Increase internal buffer by at least `byte_stream_increase` bytes.
|
||||
byte_stream() noexcept
|
||||
: byte_stream(default_increase())
|
||||
{}
|
||||
|
||||
//! Increase internal buffer by at least `increase` bytes.
|
||||
explicit byte_stream(const std::size_t increase) noexcept
|
||||
: buffer_(nullptr),
|
||||
next_write_(nullptr),
|
||||
end_(nullptr),
|
||||
increase_size_(increase)
|
||||
end_(nullptr)
|
||||
{}
|
||||
|
||||
byte_stream(byte_stream&& rhs) noexcept;
|
||||
~byte_stream() noexcept = default;
|
||||
byte_stream& operator=(byte_stream&& rhs) noexcept;
|
||||
|
||||
//! \return The minimum increase size on buffer overflow
|
||||
std::size_t increase_size() const noexcept { return increase_size_; }
|
||||
|
||||
const std::uint8_t* data() const noexcept { return buffer_.get(); }
|
||||
std::uint8_t* tellp() const noexcept { return next_write_; }
|
||||
std::size_t available() const noexcept { return end_ - next_write_; }
|
||||
|
@ -70,7 +70,7 @@ namespace http
|
||||
virtual bool connect(std::chrono::milliseconds timeout) = 0;
|
||||
virtual bool disconnect() = 0;
|
||||
virtual bool is_connected(bool *ssl = NULL) = 0;
|
||||
virtual bool invoke(const boost::string_ref uri, const boost::string_ref method, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) = 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;
|
||||
|
@ -233,7 +233,7 @@ namespace net_utils
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
inline bool invoke(const boost::string_ref uri, const boost::string_ref method, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) override
|
||||
inline 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()) override
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_lock);
|
||||
if(!is_connected())
|
||||
|
@ -118,8 +118,10 @@
|
||||
return true; \
|
||||
} \
|
||||
uint64_t ticks2 = misc_utils::get_tick_count(); \
|
||||
epee::serialization::store_t_to_binary(static_cast<command_type::response&>(resp), response_info.m_body); \
|
||||
epee::byte_slice buffer; \
|
||||
epee::serialization::store_t_to_binary(static_cast<command_type::response&>(resp), buffer, 64 * 1024); \
|
||||
uint64_t ticks3 = epee::misc_utils::get_tick_count(); \
|
||||
response_info.m_body.assign(reinterpret_cast<const char*>(buffer.data()), buffer.size()); \
|
||||
response_info.m_mime_tipe = " application/octet-stream"; \
|
||||
response_info.m_header_info.m_content_type = " application/octet-stream"; \
|
||||
MDEBUG( s_pattern << "() processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms"); \
|
||||
|
@ -31,7 +31,6 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "byte_slice.h"
|
||||
#include "net_utils_base.h"
|
||||
#include "span.h"
|
||||
|
||||
@ -39,6 +38,7 @@
|
||||
|
||||
namespace epee
|
||||
{
|
||||
class byte_slice;
|
||||
namespace levin
|
||||
{
|
||||
#pragma pack(push)
|
||||
@ -86,7 +86,7 @@ namespace levin
|
||||
template<class t_connection_context = net_utils::connection_context_base>
|
||||
struct levin_commands_handler
|
||||
{
|
||||
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, t_connection_context& context)=0;
|
||||
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, byte_slice& buff_out, t_connection_context& context)=0;
|
||||
virtual int notify(int command, const epee::span<const uint8_t> in_buff, t_connection_context& context)=0;
|
||||
virtual void callback(t_connection_context& context){};
|
||||
|
||||
|
@ -514,16 +514,15 @@ public:
|
||||
{
|
||||
if(m_current_head.m_have_to_return_data)
|
||||
{
|
||||
std::string return_buff;
|
||||
byte_slice return_buff;
|
||||
const uint32_t return_code = m_config.m_pcommands_handler->invoke(
|
||||
m_current_head.m_command, buff_to_invoke, return_buff, m_connection_context
|
||||
);
|
||||
|
||||
bucket_head2 head = make_header(m_current_head.m_command, return_buff.size(), LEVIN_PACKET_RESPONSE, false);
|
||||
head.m_return_code = SWAP32LE(return_code);
|
||||
return_buff.insert(0, reinterpret_cast<const char*>(&head), sizeof(head));
|
||||
|
||||
if(!m_pservice_endpoint->do_send(byte_slice{std::move(return_buff)}))
|
||||
if(!m_pservice_endpoint->do_send(byte_slice{{epee::as_byte_span(head), epee::to_span(return_buff)}}))
|
||||
return false;
|
||||
|
||||
MDEBUG(m_connection_context << "LEVIN_PACKET_SENT. [len=" << head.m_cb
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include <boost/lambda/lambda.hpp>
|
||||
#include <boost/interprocess/detail/atomic.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <functional>
|
||||
#include "net/net_utils_base.h"
|
||||
#include "net/net_ssl.h"
|
||||
@ -280,7 +281,7 @@ namespace net_utils
|
||||
|
||||
|
||||
inline
|
||||
bool send(const std::string& buff, std::chrono::milliseconds timeout)
|
||||
bool send(const boost::string_ref buff, std::chrono::milliseconds timeout)
|
||||
{
|
||||
|
||||
try
|
||||
@ -298,7 +299,7 @@ namespace net_utils
|
||||
// object is used as a callback and will update the ec variable when the
|
||||
// operation completes. The blocking_udp_client.cpp example shows how you
|
||||
// can use boost::bind rather than boost::lambda.
|
||||
async_write(buff.c_str(), buff.size(), ec);
|
||||
async_write(buff.data(), buff.size(), ec);
|
||||
|
||||
// Block until the asynchronous operation has completed.
|
||||
while (ec == boost::asio::error::would_block)
|
||||
|
@ -131,8 +131,8 @@ namespace net_utils
|
||||
inline
|
||||
bool parse_url_ipv6(const std::string url_str, http::url_content& content)
|
||||
{
|
||||
STATIC_REGEXP_EXPR_1(rexp_match_uri, "^((.*?)://)?(\\[(.*)\\](:(\\d+))?)(.*)?", boost::regex::icase | boost::regex::normal);
|
||||
// 12 3 4 5 6 7
|
||||
STATIC_REGEXP_EXPR_1(rexp_match_uri, "^(([^:]*?)://)?(\\[(.*)\\](:(\\d+))?)(.*)?", boost::regex::icase | boost::regex::normal);
|
||||
// 12 3 4 5 6 7
|
||||
|
||||
content.port = 0;
|
||||
boost::smatch result;
|
||||
@ -175,8 +175,8 @@ namespace net_utils
|
||||
|
||||
///iframe_test.html?api_url=http://api.vk.com/api.php&api_id=3289090&api_settings=1&viewer_id=562964060&viewer_type=0&sid=0aad8d1c5713130f9ca0076f2b7b47e532877424961367d81e7fa92455f069be7e21bc3193cbd0be11895&secret=368ebbc0ef&access_token=668bc03f43981d883f73876ffff4aa8564254b359cc745dfa1b3cde7bdab2e94105d8f6d8250717569c0a7&user_id=0&group_id=0&is_app_user=1&auth_key=d2f7a895ca5ff3fdb2a2a8ae23fe679a&language=0&parent_language=0&ad_info=ElsdCQBaQlxiAQRdFUVUXiN2AVBzBx5pU1BXIgZUJlIEAWcgAUoLQg==&referrer=unknown&lc_name=9834b6a3&hash=
|
||||
//STATIC_REGEXP_EXPR_1(rexp_match_uri, "^([^?#]*)(\\?([^#]*))?(#(.*))?", boost::regex::icase | boost::regex::normal);
|
||||
STATIC_REGEXP_EXPR_1(rexp_match_uri, "^((.*?)://)?(([^/:]*)(:(\\d+))?)(.*)?", boost::regex::icase | boost::regex::normal);
|
||||
// 12 34 5 6 7
|
||||
STATIC_REGEXP_EXPR_1(rexp_match_uri, "^(([^:]*?)://)?(([^/:]*)(:(\\d+))?)(.*)?", boost::regex::icase | boost::regex::normal);
|
||||
// 12 34 5 6 7
|
||||
content.port = 0;
|
||||
boost::smatch result;
|
||||
if(!(boost::regex_search(url_str, result, rexp_match_uri, boost::match_default) && result[0].matched))
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include "byte_slice.h"
|
||||
#include "portable_storage_template_helper.h"
|
||||
#include "net/http_base.h"
|
||||
#include "net/http_server_handlers_map2.h"
|
||||
@ -74,12 +75,12 @@ namespace epee
|
||||
template<class t_request, class t_response, class t_transport>
|
||||
bool invoke_http_bin(const boost::string_ref uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(15), const boost::string_ref method = "POST")
|
||||
{
|
||||
std::string req_param;
|
||||
if(!serialization::store_t_to_binary(out_struct, req_param))
|
||||
byte_slice req_param;
|
||||
if(!serialization::store_t_to_binary(out_struct, req_param, 16 * 1024))
|
||||
return false;
|
||||
|
||||
const http::http_response_info* pri = NULL;
|
||||
if(!transport.invoke(uri, method, req_param, timeout, std::addressof(pri)))
|
||||
if(!transport.invoke(uri, method, boost::string_ref{reinterpret_cast<const char*>(req_param.data()), req_param.size()}, timeout, std::addressof(pri)))
|
||||
{
|
||||
LOG_PRINT_L1("Failed to invoke http request to " << uri);
|
||||
return false;
|
||||
|
@ -27,8 +27,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "portable_storage_template_helper.h"
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <boost/utility/value_init.hpp>
|
||||
#include <functional>
|
||||
#include "byte_slice.h"
|
||||
#include "span.h"
|
||||
#include "net/levin_base.h"
|
||||
|
||||
@ -110,11 +112,12 @@ namespace epee
|
||||
const boost::uuids::uuid &conn_id = context.m_connection_id;
|
||||
typename serialization::portable_storage stg;
|
||||
out_struct.store(stg);
|
||||
std::string buff_to_send, buff_to_recv;
|
||||
stg.store_to_binary(buff_to_send);
|
||||
byte_slice buff_to_send;
|
||||
std::string buff_to_recv;
|
||||
stg.store_to_binary(buff_to_send, 16 * 1024);
|
||||
|
||||
on_levin_traffic(context, true, true, false, buff_to_send.size(), command);
|
||||
int res = transport.invoke(command, buff_to_send, buff_to_recv, conn_id);
|
||||
int res = transport.invoke(command, boost::string_ref{reinterpret_cast<const char*>(buff_to_send.data()), buff_to_send.size()}, buff_to_recv, conn_id);
|
||||
if( res <=0 )
|
||||
{
|
||||
LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res);
|
||||
@ -137,10 +140,10 @@ namespace epee
|
||||
const boost::uuids::uuid &conn_id = context.m_connection_id;
|
||||
typename serialization::portable_storage stg;
|
||||
const_cast<t_arg&>(out_struct).store(stg);//TODO: add true const support to searilzation
|
||||
std::string buff_to_send;
|
||||
stg.store_to_binary(buff_to_send);
|
||||
byte_slice buff_to_send;
|
||||
stg.store_to_binary(buff_to_send, 16 * 1024);
|
||||
on_levin_traffic(context, true, true, false, buff_to_send.size(), command);
|
||||
int res = transport.invoke_async(command, epee::strspan<uint8_t>(buff_to_send), conn_id, [cb, command](int code, const epee::span<const uint8_t> buff, typename t_transport::connection_context& context)->bool
|
||||
int res = transport.invoke_async(command, epee::to_span(buff_to_send), conn_id, [cb, command](int code, const epee::span<const uint8_t> buff, typename t_transport::connection_context& context)->bool
|
||||
{
|
||||
t_result result_struct = AUTO_VAL_INIT(result_struct);
|
||||
if( code <=0 )
|
||||
@ -184,11 +187,11 @@ namespace epee
|
||||
const boost::uuids::uuid &conn_id = context.m_connection_id;
|
||||
serialization::portable_storage stg;
|
||||
out_struct.store(stg);
|
||||
std::string buff_to_send;
|
||||
byte_slice buff_to_send;
|
||||
stg.store_to_binary(buff_to_send);
|
||||
|
||||
on_levin_traffic(context, true, true, false, buff_to_send.size(), command);
|
||||
int res = transport.notify(command, epee::strspan<uint8_t>(buff_to_send), conn_id);
|
||||
int res = transport.notify(command, epee::to_span(buff_to_send), conn_id);
|
||||
if(res <=0 )
|
||||
{
|
||||
MERROR("Failed to notify command " << command << " return code " << res);
|
||||
@ -199,7 +202,7 @@ namespace epee
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
template<class t_owner, class t_in_type, class t_out_type, class t_context, class callback_t>
|
||||
int buff_to_t_adapter(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, callback_t cb, t_context& context )
|
||||
int buff_to_t_adapter(int command, const epee::span<const uint8_t> in_buff, byte_slice& buff_out, callback_t cb, t_context& context )
|
||||
{
|
||||
serialization::portable_storage strg;
|
||||
if(!strg.load_from_binary(in_buff))
|
||||
@ -222,7 +225,7 @@ namespace epee
|
||||
serialization::portable_storage strg_out;
|
||||
static_cast<t_out_type&>(out_struct).store(strg_out);
|
||||
|
||||
if(!strg_out.store_to_binary(buff_out))
|
||||
if(!strg_out.store_to_binary(buff_out, 32 * 1024))
|
||||
{
|
||||
LOG_ERROR("Failed to store_to_binary in command" << command);
|
||||
return -1;
|
||||
@ -254,7 +257,7 @@ namespace epee
|
||||
}
|
||||
|
||||
#define CHAIN_LEVIN_INVOKE_MAP2(context_type) \
|
||||
int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, context_type& context) \
|
||||
int invoke(int command, const epee::span<const uint8_t> in_buff, epee::byte_slice& buff_out, context_type& context) \
|
||||
{ \
|
||||
bool handled = false; \
|
||||
return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \
|
||||
@ -263,13 +266,13 @@ namespace epee
|
||||
#define CHAIN_LEVIN_NOTIFY_MAP2(context_type) \
|
||||
int notify(int command, const epee::span<const uint8_t> in_buff, context_type& context) \
|
||||
{ \
|
||||
bool handled = false; std::string fake_str;\
|
||||
bool handled = false; epee::byte_slice fake_str; \
|
||||
return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \
|
||||
}
|
||||
|
||||
|
||||
#define CHAIN_LEVIN_INVOKE_MAP() \
|
||||
int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, epee::net_utils::connection_context_base& context) \
|
||||
int invoke(int command, const epee::span<const uint8_t> in_buff, epee::byte_slice& buff_out, epee::net_utils::connection_context_base& context) \
|
||||
{ \
|
||||
bool handled = false; \
|
||||
return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \
|
||||
@ -289,7 +292,7 @@ namespace epee
|
||||
}
|
||||
|
||||
#define BEGIN_INVOKE_MAP2(owner_type) \
|
||||
template <class t_context> int handle_invoke_map(bool is_notify, int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, t_context& context, bool& handled) \
|
||||
template <class t_context> int handle_invoke_map(bool is_notify, int command, const epee::span<const uint8_t> in_buff, epee::byte_slice& buff_out, t_context& context, bool& handled) \
|
||||
{ \
|
||||
try { \
|
||||
typedef owner_type internal_owner_type_name;
|
||||
|
@ -32,7 +32,6 @@
|
||||
|
||||
#include "misc_language.h"
|
||||
#include "portable_storage_base.h"
|
||||
#include "portable_storage_to_bin.h"
|
||||
#include "portable_storage_from_bin.h"
|
||||
#include "portable_storage_to_json.h"
|
||||
#include "portable_storage_from_json.h"
|
||||
@ -42,6 +41,7 @@
|
||||
|
||||
namespace epee
|
||||
{
|
||||
class byte_slice;
|
||||
namespace serialization
|
||||
{
|
||||
/************************************************************************/
|
||||
@ -83,7 +83,7 @@ namespace epee
|
||||
bool delete_entry(const std::string& pentry_name, hsection hparent_section = nullptr);
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
bool store_to_binary(binarybuffer& target);
|
||||
bool store_to_binary(byte_slice& target, std::size_t initial_buffer_size = 8192);
|
||||
bool load_from_binary(const epee::span<const uint8_t> target);
|
||||
bool load_from_binary(const std::string& target) { return load_from_binary(epee::strspan<uint8_t>(target)); }
|
||||
template<class trace_policy>
|
||||
@ -133,22 +133,6 @@ namespace epee
|
||||
{
|
||||
return false;//TODO: don't think i ever again will use xml - ambiguous and "overtagged" format
|
||||
}
|
||||
|
||||
inline
|
||||
bool portable_storage::store_to_binary(binarybuffer& target)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
std::stringstream ss;
|
||||
storage_block_header sbh = AUTO_VAL_INIT(sbh);
|
||||
sbh.m_signature_a = SWAP32LE(PORTABLE_STORAGE_SIGNATUREA);
|
||||
sbh.m_signature_b = SWAP32LE(PORTABLE_STORAGE_SIGNATUREB);
|
||||
sbh.m_ver = PORTABLE_STORAGE_FORMAT_VER;
|
||||
ss.write((const char*)&sbh, sizeof(storage_block_header));
|
||||
pack_entry_to_buff(ss, m_root);
|
||||
target = ss.str();
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::store_to_binary", false)
|
||||
}
|
||||
inline
|
||||
bool portable_storage::load_from_binary(const epee::span<const uint8_t> source)
|
||||
{
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "byte_slice.h"
|
||||
#include "parserse_base_utils.h"
|
||||
#include "portable_storage.h"
|
||||
#include "file_io_utils.h"
|
||||
@ -111,18 +112,18 @@ namespace epee
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
template<class t_struct>
|
||||
bool store_t_to_binary(t_struct& str_in, std::string& binary_buff, size_t indent = 0)
|
||||
bool store_t_to_binary(t_struct& str_in, byte_slice& binary_buff, size_t initial_buffer_size = 8192)
|
||||
{
|
||||
portable_storage ps;
|
||||
str_in.store(ps);
|
||||
return ps.store_to_binary(binary_buff);
|
||||
return ps.store_to_binary(binary_buff, initial_buffer_size);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
template<class t_struct>
|
||||
std::string store_t_to_binary(t_struct& str_in, size_t indent = 0)
|
||||
byte_slice store_t_to_binary(t_struct& str_in, size_t initial_buffer_size = 8192)
|
||||
{
|
||||
std::string binary_buff;
|
||||
store_t_to_binary(str_in, binary_buff, indent);
|
||||
byte_slice binary_buff;
|
||||
store_t_to_binary(str_in, binary_buff, initial_buffer_size);
|
||||
return binary_buff;
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
add_library(epee STATIC byte_slice.cpp byte_stream.cpp hex.cpp abstract_http_client.cpp http_auth.cpp mlog.cpp net_helper.cpp net_utils_base.cpp string_tools.cpp
|
||||
wipeable_string.cpp levin_base.cpp memwipe.c connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp net_ssl.cpp
|
||||
int-util.cpp)
|
||||
int-util.cpp portable_storage.cpp)
|
||||
|
||||
if (USE_READLINE AND (GNU_READLINE_FOUND OR (DEPENDS AND NOT MINGW)))
|
||||
add_library(epee_readline STATIC readline_buffer.cpp)
|
||||
|
@ -34,6 +34,11 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr const std::size_t minimum_increase = 4096;
|
||||
}
|
||||
|
||||
namespace epee
|
||||
{
|
||||
void byte_stream::overflow(const std::size_t requested)
|
||||
@ -46,7 +51,7 @@ namespace epee
|
||||
|
||||
const std::size_t len = size();
|
||||
const std::size_t cap = capacity();
|
||||
const std::size_t increase = std::max(need, increase_size());
|
||||
const std::size_t increase = std::max(std::max(need, cap), minimum_increase);
|
||||
|
||||
next_write_ = nullptr;
|
||||
end_ = nullptr;
|
||||
@ -62,8 +67,7 @@ namespace epee
|
||||
byte_stream::byte_stream(byte_stream&& rhs) noexcept
|
||||
: buffer_(std::move(rhs.buffer_)),
|
||||
next_write_(rhs.next_write_),
|
||||
end_(rhs.end_),
|
||||
increase_size_(rhs.increase_size_)
|
||||
end_(rhs.end_)
|
||||
{
|
||||
rhs.next_write_ = nullptr;
|
||||
rhs.end_ = nullptr;
|
||||
@ -76,7 +80,6 @@ namespace epee
|
||||
buffer_ = std::move(rhs.buffer_);
|
||||
next_write_ = rhs.next_write_;
|
||||
end_ = rhs.end_;
|
||||
increase_size_ = rhs.increase_size_;
|
||||
rhs.next_write_ = nullptr;
|
||||
rhs.end_ = nullptr;
|
||||
}
|
||||
|
@ -6,6 +6,17 @@
|
||||
#include "string_tools.h"
|
||||
#include "net/local_ip.h"
|
||||
|
||||
static inline uint32_t make_address_v4_from_v6(const boost::asio::ip::address_v6& a)
|
||||
{
|
||||
const auto &bytes = a.to_bytes();
|
||||
uint32_t v4 = 0;
|
||||
v4 = (v4 << 8) | bytes[12];
|
||||
v4 = (v4 << 8) | bytes[13];
|
||||
v4 = (v4 << 8) | bytes[14];
|
||||
v4 = (v4 << 8) | bytes[15];
|
||||
return htonl(v4);
|
||||
}
|
||||
|
||||
namespace epee { namespace net_utils
|
||||
{
|
||||
bool ipv4_network_address::equal(const ipv4_network_address& other) const noexcept
|
||||
@ -83,8 +94,28 @@ namespace epee { namespace net_utils
|
||||
network_address::interface const* const other_self = other.self.get();
|
||||
if (self_ == other_self) return true;
|
||||
if (!self_ || !other_self) return false;
|
||||
if (typeid(*self_) != typeid(*other_self)) return false;
|
||||
return self_->is_same_host(*other_self);
|
||||
if (typeid(*self_) == typeid(*other_self))
|
||||
return self_->is_same_host(*other_self);
|
||||
const auto this_id = get_type_id();
|
||||
if (this_id == ipv4_network_address::get_type_id() && other.get_type_id() == ipv6_network_address::get_type_id())
|
||||
{
|
||||
const boost::asio::ip::address_v6 &actual_ip = other.as<const epee::net_utils::ipv6_network_address>().ip();
|
||||
if (actual_ip.is_v4_mapped())
|
||||
{
|
||||
const uint32_t v4ip = make_address_v4_from_v6(actual_ip);
|
||||
return is_same_host(ipv4_network_address(v4ip, 0));
|
||||
}
|
||||
}
|
||||
else if (this_id == ipv6_network_address::get_type_id() && other.get_type_id() == ipv4_network_address::get_type_id())
|
||||
{
|
||||
const boost::asio::ip::address_v6 &actual_ip = this->as<const epee::net_utils::ipv6_network_address>().ip();
|
||||
if (actual_ip.is_v4_mapped())
|
||||
{
|
||||
const uint32_t v4ip = make_address_v4_from_v6(actual_ip);
|
||||
return other.is_same_host(ipv4_network_address(v4ip, 0));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string print_connection_context(const connection_context_base& ctx)
|
||||
|
29
contrib/epee/src/portable_storage.cpp
Normal file
29
contrib/epee/src/portable_storage.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
#include "byte_slice.h"
|
||||
#include "byte_stream.h"
|
||||
#include "misc_log_ex.h"
|
||||
#include "span.h"
|
||||
#include "storages/portable_storage.h"
|
||||
#include "storages/portable_storage_to_bin.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
bool portable_storage::store_to_binary(byte_slice& target, const std::size_t initial_buffer_size)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
byte_stream ss;
|
||||
ss.reserve(initial_buffer_size);
|
||||
storage_block_header sbh{};
|
||||
sbh.m_signature_a = SWAP32LE(PORTABLE_STORAGE_SIGNATUREA);
|
||||
sbh.m_signature_b = SWAP32LE(PORTABLE_STORAGE_SIGNATUREB);
|
||||
sbh.m_ver = PORTABLE_STORAGE_FORMAT_VER;
|
||||
ss.write(epee::as_byte_span(sbh));
|
||||
pack_entry_to_buff(ss, m_root);
|
||||
target = epee::byte_slice{std::move(ss)};
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::store_to_binary", false)
|
||||
}
|
||||
}
|
||||
}
|
@ -75,6 +75,8 @@ function (monero_add_executable name)
|
||||
PROPERTY
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
||||
enable_stack_trace("${name}")
|
||||
|
||||
monero_set_target_no_relink("${name}")
|
||||
endfunction ()
|
||||
|
||||
function (monero_add_library name)
|
||||
@ -92,6 +94,7 @@ function (monero_add_library_with_deps)
|
||||
set(objlib obj_${MONERO_ADD_LIBRARY_NAME})
|
||||
add_library(${objlib} OBJECT ${MONERO_ADD_LIBRARY_SOURCES})
|
||||
add_library("${MONERO_ADD_LIBRARY_NAME}" $<TARGET_OBJECTS:${objlib}>)
|
||||
monero_set_target_no_relink("${MONERO_ADD_LIBRARY_NAME}")
|
||||
if (MONERO_ADD_LIBRARY_DEPENDS)
|
||||
add_dependencies(${objlib} ${MONERO_ADD_LIBRARY_DEPENDS})
|
||||
endif()
|
||||
|
@ -45,4 +45,4 @@ foreach(BLOB_NAME checkpoints)
|
||||
)
|
||||
endforeach()
|
||||
|
||||
add_library(blocks STATIC blocks.cpp ${GENERATED_SOURCES})
|
||||
monero_add_library(blocks blocks.cpp ${GENERATED_SOURCES})
|
||||
|
26
src/common/powerof.h
Normal file
26
src/common/powerof.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace tools
|
||||
{
|
||||
template<uint64_t a, uint64_t b>
|
||||
struct PowerOf
|
||||
{
|
||||
enum Data : uint64_t
|
||||
{
|
||||
// a^b = a * a^(b-1)
|
||||
Value = a * PowerOf<a, b - 1>::Value,
|
||||
};
|
||||
};
|
||||
|
||||
template<uint64_t a>
|
||||
struct PowerOf<a, 0>
|
||||
{
|
||||
enum Data : uint64_t
|
||||
{
|
||||
// a^0 = 1
|
||||
Value = 1,
|
||||
};
|
||||
};
|
||||
}
|
@ -1000,13 +1000,13 @@ std::string get_nix_version_display_string()
|
||||
for (char c: val)
|
||||
{
|
||||
if (c == '*')
|
||||
newval += escape ? "*" : ".*";
|
||||
newval += escape ? "*" : ".*", escape = false;
|
||||
else if (c == '?')
|
||||
newval += escape ? "?" : ".";
|
||||
newval += escape ? "?" : ".", escape = false;
|
||||
else if (c == '\\')
|
||||
newval += '\\', escape = !escape;
|
||||
else
|
||||
newval += c;
|
||||
newval += c, escape = false;
|
||||
}
|
||||
return newval;
|
||||
}
|
||||
|
@ -123,13 +123,17 @@ namespace crypto {
|
||||
void random32_unbiased(unsigned char *bytes)
|
||||
{
|
||||
// l = 2^252 + 27742317777372353535851937790883648493.
|
||||
// it fits 15 in 32 bytes
|
||||
// l fits 15 times in 32 bytes (iow, 15 l is the highest multiple of l that fits in 32 bytes)
|
||||
static const unsigned char limit[32] = { 0xe3, 0x6a, 0x67, 0x72, 0x8b, 0xce, 0x13, 0x29, 0x8f, 0x30, 0x82, 0x8c, 0x0b, 0xa4, 0x10, 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0 };
|
||||
do
|
||||
while(1)
|
||||
{
|
||||
generate_random_bytes_thread_safe(32, bytes);
|
||||
} while (!sc_isnonzero(bytes) && !less32(bytes, limit)); // should be good about 15/16 of the time
|
||||
sc_reduce32(bytes);
|
||||
if (!less32(bytes, limit))
|
||||
continue;
|
||||
sc_reduce32(bytes);
|
||||
if (sc_isnonzero(bytes))
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* generate a random 32-byte (256-bit) integer and copy it to res */
|
||||
static inline void random_scalar(ec_scalar &res) {
|
||||
|
@ -43,7 +43,8 @@ namespace cryptonote
|
||||
{
|
||||
cryptonote_connection_context(): m_state(state_before_handshake), m_remote_blockchain_height(0), m_last_response_height(0),
|
||||
m_last_request_time(boost::date_time::not_a_date_time), m_callback_request_count(0),
|
||||
m_last_known_hash(crypto::null_hash), m_pruning_seed(0), m_rpc_port(0), m_rpc_credits_per_hash(0), m_anchor(false) {}
|
||||
m_last_known_hash(crypto::null_hash), m_pruning_seed(0), m_rpc_port(0), m_rpc_credits_per_hash(0), m_anchor(false), m_score(0),
|
||||
m_expect_response(0) {}
|
||||
|
||||
enum state
|
||||
{
|
||||
@ -66,7 +67,9 @@ namespace cryptonote
|
||||
uint16_t m_rpc_port;
|
||||
uint32_t m_rpc_credits_per_hash;
|
||||
bool m_anchor;
|
||||
//size_t m_score; TODO: add score calculations
|
||||
int32_t m_score;
|
||||
int m_expect_response;
|
||||
uint64_t m_expect_height;
|
||||
};
|
||||
|
||||
inline std::string get_protocol_state_string(cryptonote_connection_context::state s)
|
||||
|
@ -97,6 +97,7 @@
|
||||
|
||||
|
||||
#define BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT 10000 //by default, blocks ids count in synchronizing
|
||||
#define BLOCKS_IDS_SYNCHRONIZING_MAX_COUNT 25000 //max blocks ids count in synchronizing
|
||||
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT_PRE_V4 100 //by default, blocks count in blocks downloading
|
||||
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT 20 //by default, blocks count in blocks downloading
|
||||
#define BLOCKS_SYNCHRONIZING_MAX_COUNT 2048 //must be a power of 2, greater than 128, equal to SEEDHASH_EPOCH_BLOCKS
|
||||
@ -106,11 +107,11 @@
|
||||
|
||||
|
||||
#define CRYPTONOTE_DANDELIONPP_STEMS 2 // number of outgoing stem connections per epoch
|
||||
#define CRYPTONOTE_DANDELIONPP_FLUFF_PROBABILITY 10 // out of 100
|
||||
#define CRYPTONOTE_DANDELIONPP_FLUFF_PROBABILITY 20 // out of 100
|
||||
#define CRYPTONOTE_DANDELIONPP_MIN_EPOCH 10 // minutes
|
||||
#define CRYPTONOTE_DANDELIONPP_EPOCH_RANGE 30 // seconds
|
||||
#define CRYPTONOTE_DANDELIONPP_FLUSH_AVERAGE 5 // seconds average for poisson distributed fluff flush
|
||||
#define CRYPTONOTE_DANDELIONPP_EMBARGO_AVERAGE 173 // seconds (see tx_pool.cpp for more info)
|
||||
#define CRYPTONOTE_DANDELIONPP_EMBARGO_AVERAGE 39 // seconds (see tx_pool.cpp for more info)
|
||||
|
||||
// see src/cryptonote_protocol/levin_notify.cpp
|
||||
#define CRYPTONOTE_NOISE_MIN_EPOCH 5 // minutes
|
||||
@ -136,6 +137,7 @@
|
||||
#define P2P_DEFAULT_HANDSHAKE_INTERVAL 60 //secondes
|
||||
#define P2P_DEFAULT_PACKET_MAX_SIZE 50000000 //50000000 bytes maximum packet size
|
||||
#define P2P_DEFAULT_PEERS_IN_HANDSHAKE 250
|
||||
#define P2P_MAX_PEERS_IN_HANDSHAKE 250
|
||||
#define P2P_DEFAULT_CONNECTION_TIMEOUT 5000 //5 seconds
|
||||
#define P2P_DEFAULT_SOCKS_CONNECT_TIMEOUT 45 // seconds
|
||||
#define P2P_DEFAULT_PING_CONNECTION_TIMEOUT 2000 //2 seconds
|
||||
|
@ -3220,14 +3220,6 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rv.type == rct::RCTTypeCLSAG)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(rv.p.CLSAGs.size() == tx.vin.size(), false, "Bad CLSAGs size");
|
||||
for (size_t n = 0; n < tx.vin.size(); ++n)
|
||||
{
|
||||
rv.p.CLSAGs[n].I = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(false, false, "Unsupported rct tx type: " + boost::lexical_cast<std::string>(rv.type));
|
||||
@ -3710,19 +3702,6 @@ void Blockchain::check_ring_signature(const crypto::hash &tx_prefix_hash, const
|
||||
result = crypto::check_ring_signature(tx_prefix_hash, key_image, p_output_keys, sig.data()) ? 1 : 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
uint64_t Blockchain::get_fee_quantization_mask()
|
||||
{
|
||||
static uint64_t mask = 0;
|
||||
if (mask == 0)
|
||||
{
|
||||
mask = 1;
|
||||
for (size_t n = PER_KB_FEE_QUANTIZATION_DECIMALS; n < CRYPTONOTE_DISPLAY_DECIMAL_POINT; ++n)
|
||||
mask *= 10;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
uint64_t Blockchain::get_dynamic_base_fee(uint64_t block_reward, size_t median_block_weight, uint8_t version)
|
||||
{
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "string_tools.h"
|
||||
#include "rolling_median.h"
|
||||
#include "cryptonote_basic/cryptonote_basic.h"
|
||||
#include "common/powerof.h"
|
||||
#include "common/util.h"
|
||||
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
|
||||
#include "rpc/core_rpc_server_commands_defs.h"
|
||||
@ -591,7 +592,10 @@ namespace cryptonote
|
||||
*
|
||||
* @return the fee quantized mask
|
||||
*/
|
||||
static uint64_t get_fee_quantization_mask();
|
||||
static uint64_t get_fee_quantization_mask()
|
||||
{
|
||||
return tools::PowerOf<10, CRYPTONOTE_DISPLAY_DECIMAL_POINT - PER_KB_FEE_QUANTIZATION_DECIMALS>::Value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get dynamic per kB or byte fee for a given block weight
|
||||
|
@ -1550,6 +1550,11 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::is_synchronized() const
|
||||
{
|
||||
return m_pprotocol != nullptr && m_pprotocol->is_synchronized();
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
void core::on_synchronized()
|
||||
{
|
||||
m_miner.on_synchronized();
|
||||
@ -1799,7 +1804,7 @@ namespace cryptonote
|
||||
m_starter_message_showed = true;
|
||||
}
|
||||
|
||||
m_txpool_auto_relayer.do_call(boost::bind(&core::relay_txpool_transactions, this));
|
||||
relay_txpool_transactions(); // txpool handles periodic DB checking
|
||||
m_check_updates_interval.do_call(boost::bind(&core::check_updates, this));
|
||||
m_check_disk_space_interval.do_call(boost::bind(&core::check_disk_space, this));
|
||||
m_block_rate_interval.do_call(boost::bind(&core::check_block_rate, this));
|
||||
|
@ -329,7 +329,7 @@ namespace cryptonote
|
||||
*
|
||||
* @note see Blockchain::get_current_blockchain_height()
|
||||
*/
|
||||
uint64_t get_current_blockchain_height() const;
|
||||
virtual uint64_t get_current_blockchain_height() const final;
|
||||
|
||||
/**
|
||||
* @brief get the hash and height of the most recent block
|
||||
@ -637,6 +637,13 @@ namespace cryptonote
|
||||
*/
|
||||
std::string print_pool(bool short_format) const;
|
||||
|
||||
/**
|
||||
* @brief gets the core synchronization status
|
||||
*
|
||||
* @return core synchronization status
|
||||
*/
|
||||
virtual bool is_synchronized() const final;
|
||||
|
||||
/**
|
||||
* @copydoc miner::on_synchronized
|
||||
*
|
||||
@ -663,7 +670,7 @@ namespace cryptonote
|
||||
*
|
||||
* @param target_blockchain_height the target height
|
||||
*/
|
||||
virtual uint64_t get_target_blockchain_height() const override;
|
||||
uint64_t get_target_blockchain_height() const;
|
||||
|
||||
/**
|
||||
* @brief returns the newest hardfork version known to the blockchain
|
||||
@ -1065,7 +1072,6 @@ namespace cryptonote
|
||||
|
||||
epee::math_helper::once_a_time_seconds<60*60*12, false> m_store_blockchain_interval; //!< interval for manual storing of Blockchain, if enabled
|
||||
epee::math_helper::once_a_time_seconds<60*60*2, true> m_fork_moaner; //!< interval for checking HardFork status
|
||||
epee::math_helper::once_a_time_seconds<60*2, false> m_txpool_auto_relayer; //!< interval for checking re-relaying txpool transactions
|
||||
epee::math_helper::once_a_time_seconds<60*60*12, true> m_check_updates_interval; //!< interval for checking for new versions
|
||||
epee::math_helper::once_a_time_seconds<60*10, true> m_check_disk_space_interval; //!< interval for checking for disk space
|
||||
epee::math_helper::once_a_time_seconds<90, false> m_block_rate_interval; //!< interval for checking block rate
|
||||
|
@ -39,7 +39,8 @@ namespace cryptonote
|
||||
virtual ~i_core_events() noexcept
|
||||
{}
|
||||
|
||||
virtual uint64_t get_target_blockchain_height() const = 0;
|
||||
virtual uint64_t get_current_blockchain_height() const = 0;
|
||||
virtual bool is_synchronized() const = 0;
|
||||
virtual void on_transactions_relayed(epee::span<const cryptonote::blobdata> tx_blobs, relay_method tx_relay) = 0;
|
||||
};
|
||||
}
|
||||
|
@ -75,11 +75,11 @@ namespace cryptonote
|
||||
not ideal since a blackhole is more likely to reveal earlier nodes in
|
||||
the chain.
|
||||
|
||||
This value was calculated with k=10, ep=0.10, and hop = 175 ms. A
|
||||
This value was calculated with k=5, ep=0.10, and hop = 175 ms. A
|
||||
testrun from a recent Intel laptop took ~80ms to
|
||||
receive+parse+proces+send transaction. At least 50ms will be added to
|
||||
the latency if crossing an ocean. So 175ms is the fudge factor for
|
||||
a single hop with 173s being the embargo timer. */
|
||||
a single hop with 39s being the embargo timer. */
|
||||
constexpr const std::chrono::seconds dandelionpp_embargo_average{CRYPTONOTE_DANDELIONPP_EMBARGO_AVERAGE};
|
||||
|
||||
//TODO: constants such as these should at least be in the header,
|
||||
@ -91,6 +91,9 @@ namespace cryptonote
|
||||
time_t const MAX_RELAY_TIME = (60 * 60 * 4); // at most that many seconds between resends
|
||||
float const ACCEPT_THRESHOLD = 1.0f;
|
||||
|
||||
//! Max DB check interval for relayable txes
|
||||
constexpr const std::chrono::minutes max_relayable_check{2};
|
||||
|
||||
constexpr const std::chrono::seconds forward_delay_average{CRYPTONOTE_FORWARD_DELAY_AVERAGE};
|
||||
|
||||
// a kind of increasing backoff within min/max bounds
|
||||
@ -115,12 +118,21 @@ namespace cryptonote
|
||||
else
|
||||
return get_min_block_weight(version) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
|
||||
}
|
||||
|
||||
// external lock must be held for the comparison+set to work properly
|
||||
void set_if_less(std::atomic<time_t>& next_check, const time_t candidate) noexcept
|
||||
{
|
||||
if (candidate < next_check.load(std::memory_order_relaxed))
|
||||
next_check = candidate;
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------------
|
||||
tx_memory_pool::tx_memory_pool(Blockchain& bchs): m_blockchain(bchs), m_cookie(0), m_txpool_max_weight(DEFAULT_TXPOOL_MAX_WEIGHT), m_txpool_weight(0), m_mine_stem_txes(false)
|
||||
tx_memory_pool::tx_memory_pool(Blockchain& bchs): m_blockchain(bchs), m_cookie(0), m_txpool_max_weight(DEFAULT_TXPOOL_MAX_WEIGHT), m_txpool_weight(0), m_mine_stem_txes(false), m_next_check(std::time(nullptr))
|
||||
{
|
||||
|
||||
// class code expects unsigned values throughout
|
||||
if (m_next_check < time_t(0))
|
||||
throw std::runtime_error{"Unexpected time_t (system clock) value"};
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context& tvc, relay_method tx_relay, bool relayed, uint8_t version)
|
||||
@ -314,7 +326,10 @@ namespace cryptonote
|
||||
using clock = std::chrono::system_clock;
|
||||
auto last_relayed_time = std::numeric_limits<decltype(meta.last_relayed_time)>::max();
|
||||
if (tx_relay == relay_method::forward)
|
||||
{
|
||||
last_relayed_time = clock::to_time_t(clock::now() + crypto::random_poisson_seconds{forward_delay_average}());
|
||||
set_if_less(m_next_check, time_t(last_relayed_time));
|
||||
}
|
||||
// else the `set_relayed` function will adjust the time accordingly later
|
||||
|
||||
//update transactions container
|
||||
@ -728,16 +743,22 @@ namespace cryptonote
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
//TODO: investigate whether boolean return is appropriate
|
||||
bool tx_memory_pool::get_relayable_transactions(std::vector<std::tuple<crypto::hash, cryptonote::blobdata, relay_method>> &txs) const
|
||||
bool tx_memory_pool::get_relayable_transactions(std::vector<std::tuple<crypto::hash, cryptonote::blobdata, relay_method>> &txs)
|
||||
{
|
||||
std::vector<std::pair<crypto::hash, txpool_tx_meta_t>> change_timestamps;
|
||||
using clock = std::chrono::system_clock;
|
||||
|
||||
const uint64_t now = time(NULL);
|
||||
if (uint64_t{std::numeric_limits<time_t>::max()} < now || time_t(now) < m_next_check)
|
||||
return false;
|
||||
|
||||
uint64_t next_check = clock::to_time_t(clock::from_time_t(time_t(now)) + max_relayable_check);
|
||||
std::vector<std::pair<crypto::hash, txpool_tx_meta_t>> change_timestamps;
|
||||
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
LockedTXN lock(m_blockchain.get_db());
|
||||
txs.reserve(m_blockchain.get_txpool_tx_count());
|
||||
m_blockchain.for_all_txpool_txes([this, now, &txs, &change_timestamps](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *){
|
||||
m_blockchain.for_all_txpool_txes([this, now, &txs, &change_timestamps, &next_check](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *){
|
||||
// 0 fee transactions are never relayed
|
||||
if(!meta.pruned && meta.fee > 0 && !meta.do_not_relay)
|
||||
{
|
||||
@ -747,7 +768,10 @@ namespace cryptonote
|
||||
case relay_method::stem:
|
||||
case relay_method::forward:
|
||||
if (meta.last_relayed_time > now)
|
||||
{
|
||||
next_check = std::min(next_check, meta.last_relayed_time);
|
||||
return true; // continue to next tx
|
||||
}
|
||||
change_timestamps.emplace_back(txid, meta);
|
||||
break;
|
||||
default:
|
||||
@ -792,6 +816,8 @@ namespace cryptonote
|
||||
elem.second.last_relayed_time = now + get_relay_delay(now, elem.second.receive_time);
|
||||
m_blockchain.update_txpool_tx(elem.first, elem.second);
|
||||
}
|
||||
|
||||
m_next_check = time_t(next_check);
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
@ -799,6 +825,7 @@ namespace cryptonote
|
||||
{
|
||||
crypto::random_poisson_seconds embargo_duration{dandelionpp_embargo_average};
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
uint64_t next_relay = uint64_t{std::numeric_limits<time_t>::max()};
|
||||
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
@ -815,7 +842,10 @@ namespace cryptonote
|
||||
meta.relayed = true;
|
||||
|
||||
if (meta.dandelionpp_stem)
|
||||
{
|
||||
meta.last_relayed_time = std::chrono::system_clock::to_time_t(now + embargo_duration());
|
||||
next_relay = std::min(next_relay, meta.last_relayed_time);
|
||||
}
|
||||
else
|
||||
meta.last_relayed_time = std::chrono::system_clock::to_time_t(now);
|
||||
|
||||
@ -829,6 +859,7 @@ namespace cryptonote
|
||||
}
|
||||
}
|
||||
lock.commit();
|
||||
set_if_less(m_next_check, time_t(next_relay));
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
size_t tx_memory_pool::get_transactions_count(bool include_sensitive) const
|
||||
|
@ -31,6 +31,7 @@
|
||||
#pragma once
|
||||
#include "include_base_utils.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
@ -329,11 +330,14 @@ namespace cryptonote
|
||||
* isn't old enough that relaying it is considered harmful
|
||||
* Note a transaction can be "relayable" even if do_not_relay is true
|
||||
*
|
||||
* This function will skip all DB checks if an insufficient amount of
|
||||
* time since the last call.
|
||||
*
|
||||
* @param txs return-by-reference the transactions and their hashes
|
||||
*
|
||||
* @return true
|
||||
* @return True if DB was checked, false if DB checks skipped.
|
||||
*/
|
||||
bool get_relayable_transactions(std::vector<std::tuple<crypto::hash, cryptonote::blobdata, relay_method>>& txs) const;
|
||||
bool get_relayable_transactions(std::vector<std::tuple<crypto::hash, cryptonote::blobdata, relay_method>>& txs);
|
||||
|
||||
/**
|
||||
* @brief tell the pool that certain transactions were just relayed
|
||||
@ -609,6 +613,9 @@ private:
|
||||
mutable std::unordered_map<crypto::hash, std::tuple<bool, tx_verification_context, uint64_t, crypto::hash>> m_input_cache;
|
||||
|
||||
std::unordered_map<crypto::hash, transaction> m_parsed_tx_cache;
|
||||
|
||||
//! Next timestamp that a DB check for relayable txes is allowed
|
||||
std::atomic<time_t> m_next_check;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -52,12 +52,12 @@ namespace std {
|
||||
namespace cryptonote
|
||||
{
|
||||
|
||||
void block_queue::add_blocks(uint64_t height, std::vector<cryptonote::block_complete_entry> bcel, const boost::uuids::uuid &connection_id, float rate, size_t size)
|
||||
void block_queue::add_blocks(uint64_t height, std::vector<cryptonote::block_complete_entry> bcel, const boost::uuids::uuid &connection_id, const epee::net_utils::network_address &addr, float rate, size_t size)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> lock(mutex);
|
||||
std::vector<crypto::hash> hashes;
|
||||
bool has_hashes = remove_span(height, &hashes);
|
||||
blocks.insert(span(height, std::move(bcel), connection_id, rate, size));
|
||||
blocks.insert(span(height, std::move(bcel), connection_id, addr, rate, size));
|
||||
if (has_hashes)
|
||||
{
|
||||
for (const crypto::hash &h: hashes)
|
||||
@ -69,11 +69,11 @@ void block_queue::add_blocks(uint64_t height, std::vector<cryptonote::block_comp
|
||||
}
|
||||
}
|
||||
|
||||
void block_queue::add_blocks(uint64_t height, uint64_t nblocks, const boost::uuids::uuid &connection_id, boost::posix_time::ptime time)
|
||||
void block_queue::add_blocks(uint64_t height, uint64_t nblocks, const boost::uuids::uuid &connection_id, const epee::net_utils::network_address &addr, boost::posix_time::ptime time)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(nblocks > 0, "Empty span");
|
||||
boost::unique_lock<boost::recursive_mutex> lock(mutex);
|
||||
blocks.insert(span(height, nblocks, connection_id, time));
|
||||
blocks.insert(span(height, nblocks, connection_id, addr, time));
|
||||
}
|
||||
|
||||
void block_queue::flush_spans(const boost::uuids::uuid &connection_id, bool all)
|
||||
@ -228,7 +228,7 @@ bool block_queue::have(const crypto::hash &hash) const
|
||||
return have_blocks.find(hash) != have_blocks.end();
|
||||
}
|
||||
|
||||
std::pair<uint64_t, uint64_t> block_queue::reserve_span(uint64_t first_block_height, uint64_t last_block_height, uint64_t max_blocks, const boost::uuids::uuid &connection_id, bool sync_pruned_blocks, uint32_t local_pruning_seed, uint32_t pruning_seed, uint64_t blockchain_height, const std::vector<std::pair<crypto::hash, uint64_t>> &block_hashes, boost::posix_time::ptime time)
|
||||
std::pair<uint64_t, uint64_t> block_queue::reserve_span(uint64_t first_block_height, uint64_t last_block_height, uint64_t max_blocks, const boost::uuids::uuid &connection_id, const epee::net_utils::network_address &addr, bool sync_pruned_blocks, uint32_t local_pruning_seed, uint32_t pruning_seed, uint64_t blockchain_height, const std::vector<std::pair<crypto::hash, uint64_t>> &block_hashes, boost::posix_time::ptime time)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> lock(mutex);
|
||||
|
||||
@ -305,7 +305,7 @@ std::pair<uint64_t, uint64_t> block_queue::reserve_span(uint64_t first_block_hei
|
||||
return std::make_pair(0, 0);
|
||||
}
|
||||
MDEBUG("Reserving span " << span_start_height << " - " << (span_start_height + span_length - 1) << " for " << connection_id);
|
||||
add_blocks(span_start_height, span_length, connection_id, time);
|
||||
add_blocks(span_start_height, span_length, connection_id, addr, time);
|
||||
set_span_hashes(span_start_height, connection_id, hashes);
|
||||
return std::make_pair(span_start_height, span_length);
|
||||
}
|
||||
@ -354,7 +354,7 @@ void block_queue::set_span_hashes(uint64_t start_height, const boost::uuids::uui
|
||||
}
|
||||
}
|
||||
|
||||
bool block_queue::get_next_span(uint64_t &height, std::vector<cryptonote::block_complete_entry> &bcel, boost::uuids::uuid &connection_id, bool filled) const
|
||||
bool block_queue::get_next_span(uint64_t &height, std::vector<cryptonote::block_complete_entry> &bcel, boost::uuids::uuid &connection_id, epee::net_utils::network_address &addr, bool filled) const
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> lock(mutex);
|
||||
if (blocks.empty())
|
||||
@ -367,6 +367,7 @@ bool block_queue::get_next_span(uint64_t &height, std::vector<cryptonote::block_
|
||||
height = i->start_block_height;
|
||||
bcel = i->blocks;
|
||||
connection_id = i->connection_id;
|
||||
addr = i->origin;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <unordered_set>
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include "net/net_utils_base.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "cn.block_queue"
|
||||
@ -57,19 +58,20 @@ namespace cryptonote
|
||||
float rate;
|
||||
size_t size;
|
||||
boost::posix_time::ptime time;
|
||||
epee::net_utils::network_address origin{};
|
||||
|
||||
span(uint64_t start_block_height, std::vector<cryptonote::block_complete_entry> blocks, const boost::uuids::uuid &connection_id, float rate, size_t size):
|
||||
start_block_height(start_block_height), blocks(std::move(blocks)), connection_id(connection_id), nblocks(this->blocks.size()), rate(rate), size(size), time() {}
|
||||
span(uint64_t start_block_height, uint64_t nblocks, const boost::uuids::uuid &connection_id, boost::posix_time::ptime time):
|
||||
start_block_height(start_block_height), connection_id(connection_id), nblocks(nblocks), rate(0.0f), size(0), time(time) {}
|
||||
span(uint64_t start_block_height, std::vector<cryptonote::block_complete_entry> blocks, const boost::uuids::uuid &connection_id, const epee::net_utils::network_address &addr, float rate, size_t size):
|
||||
start_block_height(start_block_height), blocks(std::move(blocks)), connection_id(connection_id), nblocks(this->blocks.size()), rate(rate), size(size), time(boost::date_time::min_date_time), origin(addr) {}
|
||||
span(uint64_t start_block_height, uint64_t nblocks, const boost::uuids::uuid &connection_id, const epee::net_utils::network_address &addr, boost::posix_time::ptime time):
|
||||
start_block_height(start_block_height), connection_id(connection_id), nblocks(nblocks), rate(0.0f), size(0), time(time), origin(addr) {}
|
||||
|
||||
bool operator<(const span &s) const { return start_block_height < s.start_block_height; }
|
||||
};
|
||||
typedef std::set<span> block_map;
|
||||
|
||||
public:
|
||||
void add_blocks(uint64_t height, std::vector<cryptonote::block_complete_entry> bcel, const boost::uuids::uuid &connection_id, float rate, size_t size);
|
||||
void add_blocks(uint64_t height, uint64_t nblocks, const boost::uuids::uuid &connection_id, boost::posix_time::ptime time = boost::date_time::min_date_time);
|
||||
void add_blocks(uint64_t height, std::vector<cryptonote::block_complete_entry> bcel, const boost::uuids::uuid &connection_id, const epee::net_utils::network_address &addr, float rate, size_t size);
|
||||
void add_blocks(uint64_t height, uint64_t nblocks, const boost::uuids::uuid &connection_id, const epee::net_utils::network_address &addr, boost::posix_time::ptime time = boost::date_time::min_date_time);
|
||||
void flush_spans(const boost::uuids::uuid &connection_id, bool all = false);
|
||||
void flush_stale_spans(const std::set<boost::uuids::uuid> &live_connections);
|
||||
bool remove_span(uint64_t start_block_height, std::vector<crypto::hash> *hashes = NULL);
|
||||
@ -78,12 +80,12 @@ namespace cryptonote
|
||||
void print() const;
|
||||
std::string get_overview(uint64_t blockchain_height) const;
|
||||
bool has_unpruned_height(uint64_t block_height, uint64_t blockchain_height, uint32_t pruning_seed) const;
|
||||
std::pair<uint64_t, uint64_t> reserve_span(uint64_t first_block_height, uint64_t last_block_height, uint64_t max_blocks, const boost::uuids::uuid &connection_id, bool sync_pruned_blocks, uint32_t local_pruning_seed, uint32_t pruning_seed, uint64_t blockchain_height, const std::vector<std::pair<crypto::hash, uint64_t>> &block_hashes, boost::posix_time::ptime time = boost::posix_time::microsec_clock::universal_time());
|
||||
std::pair<uint64_t, uint64_t> reserve_span(uint64_t first_block_height, uint64_t last_block_height, uint64_t max_blocks, const boost::uuids::uuid &connection_id, const epee::net_utils::network_address &addr, bool sync_pruned_blocks, uint32_t local_pruning_seed, uint32_t pruning_seed, uint64_t blockchain_height, const std::vector<std::pair<crypto::hash, uint64_t>> &block_hashes, boost::posix_time::ptime time = boost::posix_time::microsec_clock::universal_time());
|
||||
uint64_t get_next_needed_height(uint64_t blockchain_height) const;
|
||||
std::pair<uint64_t, uint64_t> get_next_span_if_scheduled(std::vector<crypto::hash> &hashes, boost::uuids::uuid &connection_id, boost::posix_time::ptime &time) const;
|
||||
void reset_next_span_time(boost::posix_time::ptime t = boost::posix_time::microsec_clock::universal_time());
|
||||
void set_span_hashes(uint64_t start_height, const boost::uuids::uuid &connection_id, std::vector<crypto::hash> hashes);
|
||||
bool get_next_span(uint64_t &height, std::vector<cryptonote::block_complete_entry> &bcel, boost::uuids::uuid &connection_id, bool filled = true) const;
|
||||
bool get_next_span(uint64_t &height, std::vector<cryptonote::block_complete_entry> &bcel, boost::uuids::uuid &connection_id, epee::net_utils::network_address &addr, bool filled = true) const;
|
||||
bool has_next_span(const boost::uuids::uuid &connection_id, bool &filled, boost::posix_time::ptime &time) const;
|
||||
bool has_next_span(uint64_t height, bool &filled, boost::posix_time::ptime &time, boost::uuids::uuid &connection_id) const;
|
||||
size_t get_data_size() const;
|
||||
|
@ -298,6 +298,7 @@ namespace cryptonote
|
||||
uint64_t cumulative_difficulty_top64;
|
||||
std::vector<crypto::hash> m_block_ids;
|
||||
std::vector<uint64_t> m_block_weights;
|
||||
cryptonote::blobdata first_block;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(start_height)
|
||||
@ -309,6 +310,7 @@ namespace cryptonote
|
||||
KV_SERIALIZE_OPT(cumulative_difficulty_top64, (uint64_t)0)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(m_block_ids)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(m_block_weights)
|
||||
KV_SERIALIZE(first_block)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<request_t> request;
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
#include <string>
|
||||
|
||||
#include "byte_slice.h"
|
||||
#include "math_helper.h"
|
||||
#include "storages/levin_abstract_invoke2.h"
|
||||
#include "warnings.h"
|
||||
@ -100,11 +101,11 @@ namespace cryptonote
|
||||
void set_p2p_endpoint(nodetool::i_p2p_endpoint<connection_context>* p2p);
|
||||
//bool process_handshake_data(const blobdata& data, cryptonote_connection_context& context);
|
||||
bool process_payload_sync_data(const CORE_SYNC_DATA& hshd, cryptonote_connection_context& context, bool is_inital);
|
||||
bool get_payload_sync_data(blobdata& data);
|
||||
bool get_payload_sync_data(epee::byte_slice& data);
|
||||
bool get_payload_sync_data(CORE_SYNC_DATA& hshd);
|
||||
bool on_callback(cryptonote_connection_context& context);
|
||||
t_core& get_core(){return m_core;}
|
||||
bool is_synchronized(){return m_synchronized;}
|
||||
virtual bool is_synchronized() const final { return !no_sync() && m_synchronized; }
|
||||
void log_connections();
|
||||
std::list<connection_info> get_connections();
|
||||
const block_queue &get_block_queue() const { return m_block_queue; }
|
||||
@ -116,6 +117,8 @@ namespace cryptonote
|
||||
std::string get_peers_overview() const;
|
||||
std::pair<uint32_t, uint32_t> get_next_needed_pruning_stripe() const;
|
||||
bool needs_new_sync_connections() const;
|
||||
bool is_busy_syncing();
|
||||
|
||||
private:
|
||||
//----------------- commands handlers ----------------------------------------------
|
||||
int handle_notify_new_block(int command, NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& context);
|
||||
@ -141,6 +144,7 @@ namespace cryptonote
|
||||
bool should_ask_for_pruned_data(cryptonote_connection_context& context, uint64_t first_block_height, uint64_t nblocks, bool check_block_weights) const;
|
||||
void drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans);
|
||||
void drop_connection_with_score(cryptonote_connection_context &context, unsigned int score, bool flush_all_spans);
|
||||
void drop_connections(const epee::net_utils::network_address address);
|
||||
bool kick_idle_peers();
|
||||
bool check_standby_peers();
|
||||
bool update_sync_search();
|
||||
@ -148,6 +152,7 @@ namespace cryptonote
|
||||
void notify_new_stripe(cryptonote_connection_context &context, uint32_t stripe);
|
||||
void skip_unneeded_hashes(cryptonote_connection_context& context, bool check_block_queue) const;
|
||||
bool request_txpool_complement(cryptonote_connection_context &context);
|
||||
void hit_score(cryptonote_connection_context &context, int32_t score);
|
||||
|
||||
t_core& m_core;
|
||||
|
||||
@ -160,9 +165,10 @@ namespace cryptonote
|
||||
std::atomic<bool> m_ask_for_txpool_complement;
|
||||
boost::mutex m_sync_lock;
|
||||
block_queue m_block_queue;
|
||||
epee::math_helper::once_a_time_seconds<30> m_idle_peer_kicker;
|
||||
epee::math_helper::once_a_time_seconds<8> m_idle_peer_kicker;
|
||||
epee::math_helper::once_a_time_milliseconds<100> m_standby_checker;
|
||||
epee::math_helper::once_a_time_seconds<101> m_sync_search_checker;
|
||||
epee::math_helper::once_a_time_seconds<43> m_bad_peer_checker;
|
||||
std::atomic<unsigned int> m_max_out_peers;
|
||||
tools::PerformanceTimer m_sync_timer, m_add_timer;
|
||||
uint64_t m_last_add_end_time;
|
||||
@ -183,14 +189,16 @@ namespace cryptonote
|
||||
double get_avg_block_size();
|
||||
boost::circular_buffer<size_t> m_avg_buffer = boost::circular_buffer<size_t>(10);
|
||||
|
||||
boost::mutex m_bad_peer_check_lock;
|
||||
|
||||
template<class t_parameter>
|
||||
bool post_notify(typename t_parameter::request& arg, cryptonote_connection_context& context)
|
||||
{
|
||||
LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(context) << "] post " << typeid(t_parameter).name() << " -->");
|
||||
std::string blob;
|
||||
epee::serialization::store_t_to_binary(arg, blob);
|
||||
epee::byte_slice blob;
|
||||
epee::serialization::store_t_to_binary(arg, blob, 256 * 1024); // optimize for block responses
|
||||
//handler_response_blocks_now(blob.size()); // XXX
|
||||
return m_p2p->invoke_notify_to_peer(t_parameter::ID, epee::strspan<uint8_t>(blob), context);
|
||||
return m_p2p->invoke_notify_to_peer(t_parameter::ID, epee::to_span(blob), context);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -68,10 +68,12 @@
|
||||
#define BLOCK_QUEUE_FORCE_DOWNLOAD_NEAR_BLOCKS 1000
|
||||
#define REQUEST_NEXT_SCHEDULED_SPAN_THRESHOLD_STANDBY (5 * 1000000) // microseconds
|
||||
#define REQUEST_NEXT_SCHEDULED_SPAN_THRESHOLD (30 * 1000000) // microseconds
|
||||
#define IDLE_PEER_KICK_TIME (600 * 1000000) // microseconds
|
||||
#define IDLE_PEER_KICK_TIME (240 * 1000000) // microseconds
|
||||
#define NON_RESPONSIVE_PEER_KICK_TIME (20 * 1000000) // microseconds
|
||||
#define PASSIVE_PEER_KICK_TIME (60 * 1000000) // microseconds
|
||||
#define DROP_ON_SYNC_WEDGE_THRESHOLD (30 * 1000000000ull) // nanoseconds
|
||||
#define LAST_ACTIVITY_STALL_THRESHOLD (2.0f) // seconds
|
||||
#define DROP_PEERS_ON_SCORE -2
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
@ -139,9 +141,12 @@ namespace cryptonote
|
||||
{
|
||||
NOTIFY_REQUEST_CHAIN::request r = {};
|
||||
context.m_needed_objects.clear();
|
||||
context.m_expect_height = m_core.get_current_blockchain_height();
|
||||
m_core.get_short_chain_history(r.block_ids);
|
||||
handler_request_blocks_history( r.block_ids ); // change the limit(?), sleep(?)
|
||||
r.prune = m_sync_pruned_blocks;
|
||||
context.m_last_request_time = boost::posix_time::microsec_clock::universal_time();
|
||||
context.m_expect_response = NOTIFY_RESPONSE_CHAIN_ENTRY::ID;
|
||||
MLOG_P2P_MESSAGE("-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size() );
|
||||
post_notify<NOTIFY_REQUEST_CHAIN>(r, context);
|
||||
MLOG_PEER_STATE("requesting chain");
|
||||
@ -326,6 +331,11 @@ namespace cryptonote
|
||||
}
|
||||
}
|
||||
|
||||
if (hshd.current_height < context.m_remote_blockchain_height)
|
||||
{
|
||||
MINFO(context << "Claims " << hshd.current_height << ", claimed " << context.m_remote_blockchain_height << " before");
|
||||
hit_score(context, 1);
|
||||
}
|
||||
context.m_remote_blockchain_height = hshd.current_height;
|
||||
context.m_pruning_seed = hshd.pruning_seed;
|
||||
#ifdef CRYPTONOTE_PRUNING_DEBUG_SPOOF_SEED
|
||||
@ -416,7 +426,7 @@ namespace cryptonote
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
template<class t_core>
|
||||
bool t_cryptonote_protocol_handler<t_core>::get_payload_sync_data(blobdata& data)
|
||||
bool t_cryptonote_protocol_handler<t_core>::get_payload_sync_data(epee::byte_slice& data)
|
||||
{
|
||||
CORE_SYNC_DATA hsd = {};
|
||||
get_payload_sync_data(hsd);
|
||||
@ -427,10 +437,10 @@ namespace cryptonote
|
||||
template<class t_core>
|
||||
int t_cryptonote_protocol_handler<t_core>::handle_notify_new_block(int command, NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& context)
|
||||
{
|
||||
MLOGIF_P2P_MESSAGE(crypto::hash hash; cryptonote::block b; bool ret = cryptonote::parse_and_validate_block_from_blob(arg.b.block, b, &hash);, ret, "Received NOTIFY_NEW_BLOCK " << hash << " (height " << arg.current_blockchain_height << ", " << arg.b.txs.size() << " txes)");
|
||||
MLOGIF_P2P_MESSAGE(crypto::hash hash; cryptonote::block b; bool ret = cryptonote::parse_and_validate_block_from_blob(arg.b.block, b, &hash);, ret, context << "Received NOTIFY_NEW_BLOCK " << hash << " (height " << arg.current_blockchain_height << ", " << arg.b.txs.size() << " txes)");
|
||||
if(context.m_state != cryptonote_connection_context::state_normal)
|
||||
return 1;
|
||||
if(!is_synchronized() || m_no_sync) // can happen if a peer connection goes to normal but another thread still hasn't finished adding queued blocks
|
||||
if(!is_synchronized()) // can happen if a peer connection goes to normal but another thread still hasn't finished adding queued blocks
|
||||
{
|
||||
LOG_DEBUG_CC(context, "Received new block while syncing, ignored");
|
||||
return 1;
|
||||
@ -484,9 +494,12 @@ namespace cryptonote
|
||||
context.m_needed_objects.clear();
|
||||
context.m_state = cryptonote_connection_context::state_synchronizing;
|
||||
NOTIFY_REQUEST_CHAIN::request r = {};
|
||||
context.m_expect_height = m_core.get_current_blockchain_height();
|
||||
m_core.get_short_chain_history(r.block_ids);
|
||||
r.prune = m_sync_pruned_blocks;
|
||||
handler_request_blocks_history( r.block_ids ); // change the limit(?), sleep(?)
|
||||
context.m_last_request_time = boost::posix_time::microsec_clock::universal_time();
|
||||
context.m_expect_response = NOTIFY_RESPONSE_CHAIN_ENTRY::ID;
|
||||
MLOG_P2P_MESSAGE("-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size() );
|
||||
post_notify<NOTIFY_REQUEST_CHAIN>(r, context);
|
||||
MLOG_PEER_STATE("requesting chain");
|
||||
@ -498,10 +511,10 @@ namespace cryptonote
|
||||
template<class t_core>
|
||||
int t_cryptonote_protocol_handler<t_core>::handle_notify_new_fluffy_block(int command, NOTIFY_NEW_FLUFFY_BLOCK::request& arg, cryptonote_connection_context& context)
|
||||
{
|
||||
MLOGIF_P2P_MESSAGE(crypto::hash hash; cryptonote::block b; bool ret = cryptonote::parse_and_validate_block_from_blob(arg.b.block, b, &hash);, ret, "Received NOTIFY_NEW_FLUFFY_BLOCK " << hash << " (height " << arg.current_blockchain_height << ", " << arg.b.txs.size() << " txes)");
|
||||
MLOGIF_P2P_MESSAGE(crypto::hash hash; cryptonote::block b; bool ret = cryptonote::parse_and_validate_block_from_blob(arg.b.block, b, &hash);, ret, context << "Received NOTIFY_NEW_FLUFFY_BLOCK " << hash << " (height " << arg.current_blockchain_height << ", " << arg.b.txs.size() << " txes)");
|
||||
if(context.m_state != cryptonote_connection_context::state_normal)
|
||||
return 1;
|
||||
if(!is_synchronized() || m_no_sync) // can happen if a peer connection goes to normal but another thread still hasn't finished adding queued blocks
|
||||
if(!is_synchronized()) // can happen if a peer connection goes to normal but another thread still hasn't finished adding queued blocks
|
||||
{
|
||||
LOG_DEBUG_CC(context, "Received new block while syncing, ignored");
|
||||
return 1;
|
||||
@ -762,9 +775,12 @@ namespace cryptonote
|
||||
context.m_needed_objects.clear();
|
||||
context.m_state = cryptonote_connection_context::state_synchronizing;
|
||||
NOTIFY_REQUEST_CHAIN::request r = {};
|
||||
context.m_expect_height = m_core.get_current_blockchain_height();
|
||||
m_core.get_short_chain_history(r.block_ids);
|
||||
handler_request_blocks_history( r.block_ids ); // change the limit(?), sleep(?)
|
||||
r.prune = m_sync_pruned_blocks;
|
||||
context.m_last_request_time = boost::posix_time::microsec_clock::universal_time();
|
||||
context.m_expect_response = NOTIFY_RESPONSE_CHAIN_ENTRY::ID;
|
||||
MLOG_P2P_MESSAGE("-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size() );
|
||||
post_notify<NOTIFY_REQUEST_CHAIN>(r, context);
|
||||
MLOG_PEER_STATE("requesting chain");
|
||||
@ -929,7 +945,7 @@ namespace cryptonote
|
||||
// while syncing, core will lock for a long time, so we ignore
|
||||
// those txes as they aren't really needed anyway, and avoid a
|
||||
// long block before replying
|
||||
if(!is_synchronized() || m_no_sync)
|
||||
if(!is_synchronized())
|
||||
{
|
||||
LOG_DEBUG_CC(context, "Received new tx while syncing, ignored");
|
||||
return 1;
|
||||
@ -1029,6 +1045,7 @@ namespace cryptonote
|
||||
drop_connection(context, false, false);
|
||||
return 1;
|
||||
}
|
||||
context.m_last_request_time = boost::posix_time::microsec_clock::universal_time();
|
||||
MLOG_P2P_MESSAGE("-->>NOTIFY_RESPONSE_GET_OBJECTS: blocks.size()="
|
||||
<< rsp.blocks.size() << ", rsp.m_current_blockchain_height=" << rsp.current_blockchain_height
|
||||
<< ", missed_ids.size()=" << rsp.missed_ids.size());
|
||||
@ -1062,6 +1079,14 @@ namespace cryptonote
|
||||
boost::posix_time::ptime request_time = context.m_last_request_time;
|
||||
context.m_last_request_time = boost::date_time::not_a_date_time;
|
||||
|
||||
if (context.m_expect_response != NOTIFY_RESPONSE_GET_OBJECTS::ID)
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("Got NOTIFY_RESPONSE_GET_OBJECTS out of the blue, dropping connection");
|
||||
drop_connection(context, true, false);
|
||||
return 1;
|
||||
}
|
||||
context.m_expect_response = 0;
|
||||
|
||||
// calculate size of request
|
||||
size_t size = 0;
|
||||
size_t blocks_size = 0;
|
||||
@ -1107,6 +1132,11 @@ namespace cryptonote
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (arg.current_blockchain_height < context.m_remote_blockchain_height)
|
||||
{
|
||||
MINFO(context << "Claims " << arg.current_blockchain_height << ", claimed " << context.m_remote_blockchain_height << " before");
|
||||
hit_score(context, 1);
|
||||
}
|
||||
context.m_remote_blockchain_height = arg.current_blockchain_height;
|
||||
if (context.m_remote_blockchain_height > m_core.get_target_blockchain_height())
|
||||
m_core.set_target_blockchain_height(context.m_remote_blockchain_height);
|
||||
@ -1141,7 +1171,16 @@ namespace cryptonote
|
||||
return 1;
|
||||
}
|
||||
if (start_height == std::numeric_limits<uint64_t>::max())
|
||||
{
|
||||
start_height = boost::get<txin_gen>(b.miner_tx.vin[0]).height;
|
||||
if (start_height > context.m_expect_height)
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("sent block ahead of expected height, dropping connection");
|
||||
drop_connection(context, false, false);
|
||||
++m_sync_bad_spans_downloaded;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
auto req_it = context.m_requested_objects.find(block_hash);
|
||||
if(req_it == context.m_requested_objects.end())
|
||||
@ -1230,7 +1269,7 @@ namespace cryptonote
|
||||
const boost::posix_time::time_duration dt = now - request_time;
|
||||
const float rate = size * 1e6 / (dt.total_microseconds() + 1);
|
||||
MDEBUG(context << " adding span: " << arg.blocks.size() << " at height " << start_height << ", " << dt.total_microseconds()/1e6 << " seconds, " << (rate/1024) << " kB/s, size now " << (m_block_queue.get_data_size() + blocks_size) / 1048576.f << " MB");
|
||||
m_block_queue.add_blocks(start_height, arg.blocks, context.m_connection_id, rate, blocks_size);
|
||||
m_block_queue.add_blocks(start_height, arg.blocks, context.m_connection_id, context.m_remote_address, rate, blocks_size);
|
||||
|
||||
const crypto::hash last_block_hash = cryptonote::get_block_hash(b);
|
||||
context.m_last_known_hash = last_block_hash;
|
||||
@ -1331,7 +1370,8 @@ namespace cryptonote
|
||||
uint64_t start_height;
|
||||
std::vector<cryptonote::block_complete_entry> blocks;
|
||||
boost::uuids::uuid span_connection_id;
|
||||
if (!m_block_queue.get_next_span(start_height, blocks, span_connection_id))
|
||||
epee::net_utils::network_address span_origin;
|
||||
if (!m_block_queue.get_next_span(start_height, blocks, span_connection_id, span_origin))
|
||||
{
|
||||
MDEBUG(context << " no next span found, going back to download");
|
||||
break;
|
||||
@ -1429,6 +1469,7 @@ namespace cryptonote
|
||||
if (!m_core.prepare_handle_incoming_blocks(blocks, pblocks))
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("Failure in prepare_handle_incoming_blocks");
|
||||
drop_connections(span_origin);
|
||||
return 1;
|
||||
}
|
||||
if (!pblocks.empty() && pblocks.size() != blocks.size())
|
||||
@ -1468,6 +1509,7 @@ namespace cryptonote
|
||||
{
|
||||
if(tvc[i].m_verifivation_failed)
|
||||
{
|
||||
drop_connections(span_origin);
|
||||
if (!m_p2p->for_connection(span_connection_id, [&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t f)->bool{
|
||||
cryptonote::transaction tx;
|
||||
crypto::hash txid;
|
||||
@ -1509,6 +1551,7 @@ namespace cryptonote
|
||||
|
||||
if(bvc.m_verifivation_failed)
|
||||
{
|
||||
drop_connections(span_origin);
|
||||
if (!m_p2p->for_connection(span_connection_id, [&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t f)->bool{
|
||||
LOG_PRINT_CCONTEXT_L1("Block verification failed, dropping connection");
|
||||
drop_connection_with_score(context, bvc.m_bad_pow ? P2P_IP_FAILS_BEFORE_BLOCK : 1, true);
|
||||
@ -1528,6 +1571,7 @@ namespace cryptonote
|
||||
}
|
||||
if(bvc.m_marked_as_orphaned)
|
||||
{
|
||||
drop_connections(span_origin);
|
||||
if (!m_p2p->for_connection(span_connection_id, [&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t f)->bool{
|
||||
LOG_PRINT_CCONTEXT_L1("Block received at sync phase was marked as orphaned, dropping connection");
|
||||
drop_connection(context, true, true);
|
||||
@ -1666,24 +1710,46 @@ skip:
|
||||
bool t_cryptonote_protocol_handler<t_core>::kick_idle_peers()
|
||||
{
|
||||
MTRACE("Checking for idle peers...");
|
||||
std::vector<std::pair<boost::uuids::uuid, unsigned>> idle_peers;
|
||||
m_p2p->for_each_connection([&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t support_flags)->bool
|
||||
{
|
||||
if (context.m_state == cryptonote_connection_context::state_synchronizing && context.m_last_request_time != boost::date_time::not_a_date_time)
|
||||
{
|
||||
const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
|
||||
const boost::posix_time::time_duration dt = now - context.m_last_request_time;
|
||||
if (dt.total_microseconds() > IDLE_PEER_KICK_TIME)
|
||||
const auto ms = dt.total_microseconds();
|
||||
if (ms > IDLE_PEER_KICK_TIME || (context.m_expect_response && ms > NON_RESPONSIVE_PEER_KICK_TIME))
|
||||
{
|
||||
MINFO(context << " kicking idle peer, last update " << (dt.total_microseconds() / 1.e6) << " seconds ago");
|
||||
LOG_PRINT_CCONTEXT_L2("requesting callback");
|
||||
context.m_last_request_time = boost::date_time::not_a_date_time;
|
||||
context.m_state = cryptonote_connection_context::state_standby; // we'll go back to adding, then (if we can't), download
|
||||
++context.m_callback_request_count;
|
||||
m_p2p->request_callback(context);
|
||||
if (context.m_score-- >= 0)
|
||||
{
|
||||
MINFO(context << " kicking idle peer, last update " << (dt.total_microseconds() / 1.e6) << " seconds ago, expecting " << (int)context.m_expect_response);
|
||||
LOG_PRINT_CCONTEXT_L2("requesting callback");
|
||||
context.m_last_request_time = boost::date_time::not_a_date_time;
|
||||
context.m_expect_response = 0;
|
||||
context.m_expect_height = 0;
|
||||
context.m_state = cryptonote_connection_context::state_standby; // we'll go back to adding, then (if we can't), download
|
||||
++context.m_callback_request_count;
|
||||
m_p2p->request_callback(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
idle_peers.push_back(std::make_pair(context.m_connection_id, context.m_expect_response == 0 ? 1 : 5));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
for (const auto &e: idle_peers)
|
||||
{
|
||||
const auto &uuid = e.first;
|
||||
m_p2p->for_connection(uuid, [&](cryptonote_connection_context& ctx, nodetool::peerid_type peer_id, uint32_t f)->bool{
|
||||
MINFO(ctx << "dropping idle peer with negative score");
|
||||
drop_connection_with_score(ctx, e.second, false);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
@ -1760,6 +1826,16 @@ skip:
|
||||
LOG_ERROR_CCONTEXT("Failed to handle NOTIFY_REQUEST_CHAIN.");
|
||||
return 1;
|
||||
}
|
||||
if (r.m_block_ids.size() >= 2)
|
||||
{
|
||||
cryptonote::block b;
|
||||
if (!m_core.get_block_by_hash(r.m_block_ids[1], b))
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("Failed to handle NOTIFY_REQUEST_CHAIN: first block not found");
|
||||
return 1;
|
||||
}
|
||||
r.first_block = cryptonote::block_to_blob(b);
|
||||
}
|
||||
MLOG_P2P_MESSAGE("-->>NOTIFY_RESPONSE_CHAIN_ENTRY: m_start_height=" << r.start_height << ", m_total_height=" << r.total_height << ", m_block_ids.size()=" << r.m_block_ids.size());
|
||||
post_notify<NOTIFY_RESPONSE_CHAIN_ENTRY>(r, context);
|
||||
return 1;
|
||||
@ -1944,7 +2020,7 @@ skip:
|
||||
if (local_stripe == 0)
|
||||
return false;
|
||||
// don't request pre-bulletprooof pruned blocks, we can't reconstruct their weight (yet)
|
||||
static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(HF_VERSION_SMALLER_BP);
|
||||
static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(HF_VERSION_SMALLER_BP + 1);
|
||||
if (first_block_height < bp_fork_height)
|
||||
return false;
|
||||
// assumes the span size is less or equal to the stripe size
|
||||
@ -2125,7 +2201,7 @@ skip:
|
||||
const uint64_t first_block_height = context.m_last_response_height - context.m_needed_objects.size() + 1;
|
||||
static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(HF_VERSION_SMALLER_BP);
|
||||
bool sync_pruned_blocks = m_sync_pruned_blocks && first_block_height >= bp_fork_height && m_core.get_blockchain_pruning_seed();
|
||||
span = m_block_queue.reserve_span(first_block_height, context.m_last_response_height, count_limit, context.m_connection_id, sync_pruned_blocks, m_core.get_blockchain_pruning_seed(), context.m_pruning_seed, context.m_remote_blockchain_height, context.m_needed_objects);
|
||||
span = m_block_queue.reserve_span(first_block_height, context.m_last_response_height, count_limit, context.m_connection_id, context.m_remote_address, sync_pruned_blocks, m_core.get_blockchain_pruning_seed(), context.m_pruning_seed, context.m_remote_blockchain_height, context.m_needed_objects);
|
||||
MDEBUG(context << " span from " << first_block_height << ": " << span.first << "/" << span.second);
|
||||
if (span.second > 0)
|
||||
{
|
||||
@ -2206,6 +2282,8 @@ skip:
|
||||
}
|
||||
}
|
||||
context.m_last_request_time = boost::posix_time::microsec_clock::universal_time();
|
||||
context.m_expect_height = span.first;
|
||||
context.m_expect_response = NOTIFY_RESPONSE_GET_OBJECTS::ID;
|
||||
MLOG_P2P_MESSAGE("-->>NOTIFY_REQUEST_GET_OBJECTS: blocks.size()=" << req.blocks.size()
|
||||
<< "requested blocks count=" << count << " / " << count_limit << " from " << span.first << ", first hash " << req.blocks.front());
|
||||
//epee::net_utils::network_throttle_manager::get_global_throttle_inreq().logger_handle_net("log/dr-monero/net/req-all.data", sec, get_avg_block_size());
|
||||
@ -2260,8 +2338,8 @@ skip:
|
||||
uint64_t start_height;
|
||||
std::vector<cryptonote::block_complete_entry> blocks;
|
||||
boost::uuids::uuid span_connection_id;
|
||||
bool filled = false;
|
||||
if (m_block_queue.get_next_span(start_height, blocks, span_connection_id, filled) && filled)
|
||||
epee::net_utils::network_address span_origin;
|
||||
if (m_block_queue.get_next_span(start_height, blocks, span_connection_id, span_origin, true))
|
||||
{
|
||||
LOG_DEBUG_CC(context, "No other thread is adding blocks, resuming");
|
||||
MLOG_PEER_STATE("will try to add blocks next");
|
||||
@ -2277,6 +2355,7 @@ skip:
|
||||
{//we have to fetch more objects ids, request blockchain entry
|
||||
|
||||
NOTIFY_REQUEST_CHAIN::request r = {};
|
||||
context.m_expect_height = m_core.get_current_blockchain_height();
|
||||
m_core.get_short_chain_history(r.block_ids);
|
||||
CHECK_AND_ASSERT_MES(!r.block_ids.empty(), false, "Short chain history is empty");
|
||||
|
||||
@ -2284,7 +2363,10 @@ skip:
|
||||
{
|
||||
// we'll want to start off from where we are on that peer, which may not be added yet
|
||||
if (context.m_last_known_hash != crypto::null_hash && r.block_ids.front() != context.m_last_known_hash)
|
||||
{
|
||||
context.m_expect_height = std::numeric_limits<uint64_t>::max();
|
||||
r.block_ids.push_front(context.m_last_known_hash);
|
||||
}
|
||||
}
|
||||
|
||||
handler_request_blocks_history( r.block_ids ); // change the limit(?), sleep(?)
|
||||
@ -2296,6 +2378,7 @@ skip:
|
||||
//LOG_PRINT_CCONTEXT_L1("r = " << 200);
|
||||
|
||||
context.m_last_request_time = boost::posix_time::microsec_clock::universal_time();
|
||||
context.m_expect_response = NOTIFY_RESPONSE_CHAIN_ENTRY::ID;
|
||||
MLOG_P2P_MESSAGE("-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size() << ", start_from_current_chain " << start_from_current_chain);
|
||||
post_notify<NOTIFY_REQUEST_CHAIN>(r, context);
|
||||
MLOG_PEER_STATE("requesting chain");
|
||||
@ -2321,7 +2404,7 @@ skip:
|
||||
}
|
||||
else
|
||||
{
|
||||
MINFO(context << " we've reached this peer's blockchain height");
|
||||
MINFO(context << " we've reached this peer's blockchain height (theirs " << context.m_remote_blockchain_height << ", our target " << m_core.get_target_blockchain_height());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -2418,6 +2501,20 @@ skip:
|
||||
<< ", m_start_height=" << arg.start_height << ", m_total_height=" << arg.total_height);
|
||||
MLOG_PEER_STATE("received chain");
|
||||
|
||||
if (context.m_expect_response != NOTIFY_RESPONSE_CHAIN_ENTRY::ID)
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("Got NOTIFY_RESPONSE_CHAIN_ENTRY out of the blue, dropping connection");
|
||||
drop_connection(context, true, false);
|
||||
return 1;
|
||||
}
|
||||
context.m_expect_response = 0;
|
||||
if (arg.start_height + 1 > context.m_expect_height) // we expect an overlapping block
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("Got NOTIFY_RESPONSE_CHAIN_ENTRY past expected height, dropping connection");
|
||||
drop_connection(context, true, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
context.m_last_request_time = boost::date_time::not_a_date_time;
|
||||
|
||||
m_sync_download_chain_size += arg.m_block_ids.size() * sizeof(crypto::hash);
|
||||
@ -2442,12 +2539,17 @@ skip:
|
||||
}
|
||||
MDEBUG(context << "first block hash " << arg.m_block_ids.front() << ", last " << arg.m_block_ids.back());
|
||||
|
||||
if (arg.total_height >= CRYPTONOTE_MAX_BLOCK_NUMBER || arg.m_block_ids.size() >= CRYPTONOTE_MAX_BLOCK_NUMBER)
|
||||
if (arg.total_height >= CRYPTONOTE_MAX_BLOCK_NUMBER || arg.m_block_ids.size() > BLOCKS_IDS_SYNCHRONIZING_MAX_COUNT)
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_CHAIN_ENTRY, with total_height=" << arg.total_height << " and block_ids=" << arg.m_block_ids.size());
|
||||
drop_connection(context, false, false);
|
||||
return 1;
|
||||
}
|
||||
if (arg.total_height < context.m_remote_blockchain_height)
|
||||
{
|
||||
MINFO(context << "Claims " << arg.total_height << ", claimed " << context.m_remote_blockchain_height << " before");
|
||||
hit_score(context, 1);
|
||||
}
|
||||
context.m_remote_blockchain_height = arg.total_height;
|
||||
context.m_last_response_height = arg.start_height + arg.m_block_ids.size()-1;
|
||||
if(context.m_last_response_height > context.m_remote_blockchain_height)
|
||||
@ -2459,8 +2561,19 @@ skip:
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::unordered_set<crypto::hash> hashes;
|
||||
for (const auto &h: arg.m_block_ids)
|
||||
{
|
||||
if (!hashes.insert(h).second)
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("sent duplicate block, dropping connection");
|
||||
drop_connection(context, true, false);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t n_use_blocks = m_core.prevalidate_block_hashes(arg.start_height, arg.m_block_ids, arg.m_block_weights);
|
||||
if (n_use_blocks + HASH_OF_HASHES_STEP <= arg.m_block_ids.size())
|
||||
if (n_use_blocks == 0 || n_use_blocks + HASH_OF_HASHES_STEP <= arg.m_block_ids.size())
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("Most blocks are invalid, dropping connection");
|
||||
drop_connection(context, true, false);
|
||||
@ -2469,8 +2582,15 @@ skip:
|
||||
|
||||
context.m_needed_objects.clear();
|
||||
uint64_t added = 0;
|
||||
std::unordered_set<crypto::hash> blocks_found;
|
||||
for (size_t i = 0; i < arg.m_block_ids.size(); ++i)
|
||||
{
|
||||
if (!blocks_found.insert(arg.m_block_ids[i]).second)
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("Duplicate blocks in chain entry response, dropping connection");
|
||||
drop_connection(context, true, false);
|
||||
return 1;
|
||||
}
|
||||
const uint64_t block_weight = arg.m_block_weights.empty() ? 0 : arg.m_block_weights[i];
|
||||
context.m_needed_objects.push_back(std::make_pair(arg.m_block_ids[i], block_weight));
|
||||
if (++added == n_use_blocks)
|
||||
@ -2523,15 +2643,15 @@ skip:
|
||||
// send fluffy ones first, we want to encourage people to run that
|
||||
if (!fluffyConnections.empty())
|
||||
{
|
||||
std::string fluffyBlob;
|
||||
epee::serialization::store_t_to_binary(fluffy_arg, fluffyBlob);
|
||||
m_p2p->relay_notify_to_list(NOTIFY_NEW_FLUFFY_BLOCK::ID, epee::strspan<uint8_t>(fluffyBlob), std::move(fluffyConnections));
|
||||
epee::byte_slice fluffyBlob;
|
||||
epee::serialization::store_t_to_binary(fluffy_arg, fluffyBlob, 32 * 1024);
|
||||
m_p2p->relay_notify_to_list(NOTIFY_NEW_FLUFFY_BLOCK::ID, epee::to_span(fluffyBlob), std::move(fluffyConnections));
|
||||
}
|
||||
if (!fullConnections.empty())
|
||||
{
|
||||
std::string fullBlob;
|
||||
epee::serialization::store_t_to_binary(arg, fullBlob);
|
||||
m_p2p->relay_notify_to_list(NOTIFY_NEW_BLOCK::ID, epee::strspan<uint8_t>(fullBlob), std::move(fullConnections));
|
||||
epee::byte_slice fullBlob;
|
||||
epee::serialization::store_t_to_binary(arg, fullBlob, 128 * 1024);
|
||||
m_p2p->relay_notify_to_list(NOTIFY_NEW_BLOCK::ID, epee::to_span(fullBlob), std::move(fullConnections));
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -2564,6 +2684,19 @@ skip:
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
template<class t_core>
|
||||
void t_cryptonote_protocol_handler<t_core>::hit_score(cryptonote_connection_context &context, int32_t score)
|
||||
{
|
||||
if (score <= 0)
|
||||
{
|
||||
MERROR("Negative score hit");
|
||||
return;
|
||||
}
|
||||
context.m_score -= score;
|
||||
if (context.m_score <= DROP_PEERS_ON_SCORE)
|
||||
drop_connection_with_score(context, 5, false);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
template<class t_core>
|
||||
std::string t_cryptonote_protocol_handler<t_core>::get_peers_overview() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
@ -2638,6 +2771,13 @@ skip:
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
template<class t_core>
|
||||
bool t_cryptonote_protocol_handler<t_core>::is_busy_syncing()
|
||||
{
|
||||
const boost::unique_lock<boost::mutex> sync{m_sync_lock, boost::try_to_lock};
|
||||
return !sync.owns_lock();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
template<class t_core>
|
||||
void t_cryptonote_protocol_handler<t_core>::drop_connection_with_score(cryptonote_connection_context &context, unsigned score, bool flush_all_spans)
|
||||
{
|
||||
LOG_DEBUG_CC(context, "dropping connection id " << context.m_connection_id << " (pruning seed " <<
|
||||
@ -2659,6 +2799,29 @@ skip:
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
template<class t_core>
|
||||
void t_cryptonote_protocol_handler<t_core>::drop_connections(const epee::net_utils::network_address address)
|
||||
{
|
||||
MWARNING("dropping connections to " << address.str());
|
||||
|
||||
m_p2p->add_host_fail(address, 5);
|
||||
|
||||
std::vector<boost::uuids::uuid> drop;
|
||||
m_p2p->for_each_connection([&](const connection_context& cntxt, nodetool::peerid_type peer_id, uint32_t support_flags) {
|
||||
if (address.is_same_host(cntxt.m_remote_address))
|
||||
drop.push_back(cntxt.m_connection_id);
|
||||
return true;
|
||||
});
|
||||
for (const boost::uuids::uuid &id: drop)
|
||||
{
|
||||
m_block_queue.flush_spans(id, true);
|
||||
m_p2p->for_connection(id, [&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t f)->bool{
|
||||
drop_connection(context, true, false);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
template<class t_core>
|
||||
void t_cryptonote_protocol_handler<t_core>::on_connection_close(cryptonote_connection_context &context)
|
||||
{
|
||||
uint64_t target = 0;
|
||||
|
@ -40,6 +40,7 @@ namespace cryptonote
|
||||
/************************************************************************/
|
||||
struct i_cryptonote_protocol
|
||||
{
|
||||
virtual bool is_synchronized() const = 0;
|
||||
virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& exclude_context)=0;
|
||||
virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, const boost::uuids::uuid& source, epee::net_utils::zone zone, relay_method tx_relay)=0;
|
||||
//virtual bool request_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, cryptonote_connection_context& context)=0;
|
||||
@ -50,6 +51,10 @@ namespace cryptonote
|
||||
/************************************************************************/
|
||||
struct cryptonote_protocol_stub: public i_cryptonote_protocol
|
||||
{
|
||||
virtual bool is_synchronized() const final
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& exclude_context)
|
||||
{
|
||||
return false;
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
#include "byte_slice.h"
|
||||
#include "common/expect.h"
|
||||
#include "common/varint.h"
|
||||
#include "cryptonote_config.h"
|
||||
@ -52,7 +53,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
int get_command_from_message(const cryptonote::blobdata &msg)
|
||||
int get_command_from_message(const epee::byte_slice &msg)
|
||||
{
|
||||
return msg.size() >= sizeof(epee::levin::bucket_head2) ? SWAP32LE(((epee::levin::bucket_head2*)msg.data())->m_command) : 0;
|
||||
}
|
||||
@ -105,8 +106,44 @@ namespace levin
|
||||
return std::chrono::steady_clock::duration{crypto::rand_range(rep(0), range.count())};
|
||||
}
|
||||
|
||||
//! \return Outgoing connections supporting fragments in `connections` filtered by remote blockchain height.
|
||||
std::vector<boost::uuids::uuid> get_out_connections(connections& p2p, uint64_t min_blockchain_height)
|
||||
uint64_t get_median_remote_height(connections& p2p)
|
||||
{
|
||||
std::vector<uint64_t> remote_heights;
|
||||
remote_heights.reserve(connection_id_reserve_size);
|
||||
p2p.foreach_connection([&remote_heights] (detail::p2p_context& context) {
|
||||
if (!context.m_is_income)
|
||||
{
|
||||
remote_heights.emplace_back(context.m_remote_blockchain_height);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (remote_heights.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const size_t n = remote_heights.size() / 2;
|
||||
std::sort(remote_heights.begin(), remote_heights.end());
|
||||
if (remote_heights.size() % 2 != 0)
|
||||
{
|
||||
return remote_heights[n];
|
||||
}
|
||||
return remote_heights[n-1];
|
||||
}
|
||||
|
||||
uint64_t get_blockchain_height(connections& p2p, const i_core_events* core)
|
||||
{
|
||||
const uint64_t local_blockchain_height = core->get_current_blockchain_height();
|
||||
if (core->is_synchronized())
|
||||
{
|
||||
return local_blockchain_height;
|
||||
}
|
||||
return std::max(local_blockchain_height, get_median_remote_height(p2p));
|
||||
}
|
||||
|
||||
//! \return Outgoing connections supporting fragments in `connections` filtered by blockchain height.
|
||||
std::vector<boost::uuids::uuid> get_out_connections(connections& p2p, uint64_t blockchain_height)
|
||||
{
|
||||
std::vector<boost::uuids::uuid> outs;
|
||||
outs.reserve(connection_id_reserve_size);
|
||||
@ -115,16 +152,22 @@ namespace levin
|
||||
the reserve call so a strand is not used. Investigate if there is lots
|
||||
of waiting in here. */
|
||||
|
||||
p2p.foreach_connection([&outs, min_blockchain_height] (detail::p2p_context& context) {
|
||||
if (!context.m_is_income && context.m_remote_blockchain_height >= min_blockchain_height)
|
||||
p2p.foreach_connection([&outs, blockchain_height] (detail::p2p_context& context) {
|
||||
if (!context.m_is_income && context.m_remote_blockchain_height >= blockchain_height)
|
||||
outs.emplace_back(context.m_connection_id);
|
||||
return true;
|
||||
});
|
||||
|
||||
MDEBUG("Found " << outs.size() << " out connections having height >= " << blockchain_height);
|
||||
return outs;
|
||||
}
|
||||
|
||||
std::string make_tx_payload(std::vector<blobdata>&& txs, const bool pad, const bool fluff)
|
||||
std::vector<boost::uuids::uuid> get_out_connections(connections& p2p, const i_core_events* core)
|
||||
{
|
||||
return get_out_connections(p2p, get_blockchain_height(p2p, core));
|
||||
}
|
||||
|
||||
epee::byte_slice make_tx_payload(std::vector<blobdata>&& txs, const bool pad, const bool fluff)
|
||||
{
|
||||
NOTIFY_NEW_TRANSACTIONS::request request{};
|
||||
request.txs = std::move(txs);
|
||||
@ -146,7 +189,7 @@ namespace levin
|
||||
padding -= overhead;
|
||||
request._ = std::string(padding, ' ');
|
||||
|
||||
std::string arg_buff;
|
||||
epee::byte_slice arg_buff;
|
||||
epee::serialization::store_t_to_binary(request, arg_buff);
|
||||
|
||||
// we probably lowballed the payload size a bit, so added a but too much. Fix this now.
|
||||
@ -158,7 +201,7 @@ namespace levin
|
||||
// if the size of _ moved enough, we might lose byte in size encoding, we don't care
|
||||
}
|
||||
|
||||
std::string fullBlob;
|
||||
epee::byte_slice fullBlob;
|
||||
if (!epee::serialization::store_t_to_binary(request, fullBlob))
|
||||
throw std::runtime_error{"Failed to serialize to epee binary format"};
|
||||
|
||||
@ -167,12 +210,12 @@ namespace levin
|
||||
|
||||
bool make_payload_send_txs(connections& p2p, std::vector<blobdata>&& txs, const boost::uuids::uuid& destination, const bool pad, const bool fluff)
|
||||
{
|
||||
const cryptonote::blobdata blob = make_tx_payload(std::move(txs), pad, fluff);
|
||||
const epee::byte_slice blob = make_tx_payload(std::move(txs), pad, fluff);
|
||||
p2p.for_connection(destination, [&blob](detail::p2p_context& context) {
|
||||
on_levin_traffic(context, true, true, false, blob.size(), get_command_from_message(blob));
|
||||
return true;
|
||||
});
|
||||
return p2p.notify(NOTIFY_NEW_TRANSACTIONS::ID, epee::strspan<std::uint8_t>(blob), destination);
|
||||
return p2p.notify(NOTIFY_NEW_TRANSACTIONS::ID, epee::to_span(blob), destination);
|
||||
}
|
||||
|
||||
/* The current design uses `asio::strand`s. The documentation isn't as clear
|
||||
@ -233,7 +276,7 @@ namespace levin
|
||||
{
|
||||
struct zone
|
||||
{
|
||||
explicit zone(boost::asio::io_service& io_service, std::shared_ptr<connections> p2p, epee::byte_slice noise_in, bool is_public, bool pad_txs)
|
||||
explicit zone(boost::asio::io_service& io_service, std::shared_ptr<connections> p2p, epee::byte_slice noise_in, epee::net_utils::zone zone, bool pad_txs)
|
||||
: p2p(std::move(p2p)),
|
||||
noise(std::move(noise_in)),
|
||||
next_epoch(io_service),
|
||||
@ -243,6 +286,7 @@ namespace levin
|
||||
channels(),
|
||||
connection_count(0),
|
||||
flush_callbacks(0),
|
||||
nzone(zone),
|
||||
is_public(is_public),
|
||||
pad_txs(pad_txs),
|
||||
fluffing(false)
|
||||
@ -260,6 +304,7 @@ namespace levin
|
||||
std::deque<noise_channel> channels; //!< Never touch after init; only update elements on `noise_channel.strand`
|
||||
std::atomic<std::size_t> connection_count; //!< Only update in strand, can be read at any time
|
||||
std::uint32_t flush_callbacks; //!< Number of active fluff flush callbacks queued
|
||||
const epee::net_utils::zone nzone; //!< Zone is public ipv4/ipv6 connections, or i2p or tor
|
||||
const bool is_public; //!< Zone is public ipv4/ipv6 connections
|
||||
const bool pad_txs; //!< Pad txs to the next boundary for privacy
|
||||
bool fluffing; //!< Zone is in Dandelion++ fluff epoch
|
||||
@ -297,7 +342,8 @@ namespace levin
|
||||
if (!channel.connection.is_nil())
|
||||
channel.queue.push_back(std::move(message_));
|
||||
else if (destination_ == 0 && zone_->connection_count == 0)
|
||||
MWARNING("Unable to send transaction(s) over anonymity network - no available outbound connections");
|
||||
MWARNING("Unable to send transaction(s) to " << epee::net_utils::zone_to_string(zone_->nzone) <<
|
||||
" - no available outbound connections");
|
||||
}
|
||||
};
|
||||
|
||||
@ -399,7 +445,7 @@ namespace levin
|
||||
zone->p2p->foreach_connection([txs, now, &zone, &source, &in_duration, &out_duration, &next_flush] (detail::p2p_context& context)
|
||||
{
|
||||
// When i2p/tor, only fluff to outbound connections
|
||||
if (source != context.m_connection_id && (zone->is_public || !context.m_is_income))
|
||||
if (source != context.m_connection_id && (zone->nzone == epee::net_utils::zone::public_ || !context.m_is_income))
|
||||
{
|
||||
if (context.fluff_txs.empty())
|
||||
context.flush_time = now + (context.m_is_income ? in_duration() : out_duration());
|
||||
@ -526,7 +572,7 @@ namespace levin
|
||||
}
|
||||
|
||||
// connection list may be outdated, try again
|
||||
update_channels::run(zone_, get_out_connections(*zone_->p2p, core_->get_target_blockchain_height()));
|
||||
update_channels::run(zone_, get_out_connections(*zone_->p2p, core_));
|
||||
}
|
||||
|
||||
MERROR("Unable to send transaction(s) via Dandelion++ stem");
|
||||
@ -562,7 +608,7 @@ namespace levin
|
||||
|
||||
assert(zone_->strand.running_in_this_thread());
|
||||
|
||||
if (zone_->is_public)
|
||||
if (zone_->nzone == epee::net_utils::zone::public_)
|
||||
MDEBUG("Starting new Dandelion++ epoch: " << (fluffing_ ? "fluff" : "stem"));
|
||||
|
||||
zone_->map = std::move(map_);
|
||||
@ -630,10 +676,12 @@ namespace levin
|
||||
{
|
||||
channel.active = nullptr;
|
||||
channel.connection = boost::uuids::nil_uuid();
|
||||
auto height = get_blockchain_height(*zone_->p2p, core_);
|
||||
|
||||
auto connections = get_out_connections(*zone_->p2p, core_->get_target_blockchain_height());
|
||||
auto connections = get_out_connections(*zone_->p2p, height);
|
||||
if (connections.empty())
|
||||
MWARNING("Lost all outbound connections to anonymity network - currently unable to send transaction(s)");
|
||||
MWARNING("Unable to send transaction(s) to " << epee::net_utils::zone_to_string(zone_->nzone) <<
|
||||
" - no suitable outbound connections at height " << height);
|
||||
|
||||
zone_->strand.post(update_channels{zone_, std::move(connections)});
|
||||
}
|
||||
@ -664,7 +712,7 @@ namespace levin
|
||||
|
||||
const bool fluffing = crypto::rand_idx(unsigned(100)) < CRYPTONOTE_DANDELIONPP_FLUFF_PROBABILITY;
|
||||
const auto start = std::chrono::steady_clock::now();
|
||||
auto connections = get_out_connections(*(zone_->p2p), core_->get_target_blockchain_height());
|
||||
auto connections = get_out_connections(*(zone_->p2p), core_);
|
||||
zone_->strand.dispatch(
|
||||
change_channels{zone_, net::dandelionpp::connection_map{std::move(connections), count_}, fluffing}
|
||||
);
|
||||
@ -676,15 +724,15 @@ namespace levin
|
||||
};
|
||||
} // anonymous
|
||||
|
||||
notify::notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, const bool is_public, const bool pad_txs, i_core_events& core)
|
||||
: zone_(std::make_shared<detail::zone>(service, std::move(p2p), std::move(noise), is_public, pad_txs))
|
||||
notify::notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, const bool pad_txs, i_core_events& core)
|
||||
: zone_(std::make_shared<detail::zone>(service, std::move(p2p), std::move(noise), zone, pad_txs))
|
||||
, core_(std::addressof(core))
|
||||
{
|
||||
if (!zone_->p2p)
|
||||
throw std::logic_error{"cryptonote::levin::notify cannot have nullptr p2p argument"};
|
||||
|
||||
const bool noise_enabled = !zone_->noise.empty();
|
||||
if (noise_enabled || is_public)
|
||||
if (noise_enabled || zone == epee::net_utils::zone::public_)
|
||||
{
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
const auto min_epoch = noise_enabled ? noise_min_epoch : dandelionpp_min_epoch;
|
||||
@ -715,7 +763,7 @@ namespace levin
|
||||
return;
|
||||
|
||||
zone_->strand.dispatch(
|
||||
update_channels{zone_, get_out_connections(*(zone_->p2p), core_->get_target_blockchain_height())}
|
||||
update_channels{zone_, get_out_connections(*(zone_->p2p), core_)}
|
||||
);
|
||||
}
|
||||
|
||||
@ -778,9 +826,9 @@ namespace levin
|
||||
|
||||
// Padding is not useful when using noise mode. Send as stem so receiver
|
||||
// forwards in Dandelion++ mode.
|
||||
const std::string payload = make_tx_payload(std::move(txs), false, false);
|
||||
const epee::byte_slice payload = make_tx_payload(std::move(txs), false, false);
|
||||
epee::byte_slice message = epee::levin::make_fragmented_notify(
|
||||
zone_->noise, NOTIFY_NEW_TRANSACTIONS::ID, epee::strspan<std::uint8_t>(payload)
|
||||
zone_->noise, NOTIFY_NEW_TRANSACTIONS::ID, epee::to_span(payload)
|
||||
);
|
||||
if (CRYPTONOTE_MAX_FRAGMENTS * zone_->noise.size() < message.size())
|
||||
{
|
||||
@ -806,7 +854,7 @@ namespace levin
|
||||
case relay_method::stem:
|
||||
case relay_method::forward:
|
||||
case relay_method::local:
|
||||
if (zone_->is_public)
|
||||
if (zone_->nzone == epee::net_utils::zone::public_)
|
||||
{
|
||||
// this will change a local/forward tx to stem or fluff ...
|
||||
zone_->strand.dispatch(
|
||||
|
@ -85,7 +85,7 @@ namespace levin
|
||||
{}
|
||||
|
||||
//! Construct an instance with available notification `zones`.
|
||||
explicit notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, bool is_public, bool pad_txs, i_core_events& core);
|
||||
explicit notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, bool pad_txs, i_core_events& core);
|
||||
|
||||
notify(const notify&) = delete;
|
||||
notify(notify&&) = default;
|
||||
|
@ -50,7 +50,7 @@ bool t_command_parser_executor::print_peer_list(const std::vector<std::string>&
|
||||
{
|
||||
if (args.size() > 3)
|
||||
{
|
||||
std::cout << "use: print_pl [white] [gray] [<limit>] [pruned] [publicrpc]" << std::endl;
|
||||
std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ bool t_command_parser_executor::print_peer_list(const std::vector<std::string>&
|
||||
}
|
||||
else if (!epee::string_tools::get_xtype_from_string(limit, args[i]))
|
||||
{
|
||||
std::cout << "unexpected argument: " << args[i] << std::endl;
|
||||
std::cout << "Invalid syntax: Unexpected parameter: " << args[i] << ". For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -90,56 +90,79 @@ bool t_command_parser_executor::print_peer_list(const std::vector<std::string>&
|
||||
|
||||
bool t_command_parser_executor::print_peer_list_stats(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.print_peer_list_stats();
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::save_blockchain(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
return m_executor.save_blockchain();
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::show_hash_rate(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.show_hash_rate();
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::hide_hash_rate(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.hide_hash_rate();
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::show_difficulty(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.show_difficulty();
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::show_status(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.show_status();
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::print_connections(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.print_connections();
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::print_net_stats(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.print_net_stats();
|
||||
}
|
||||
@ -148,8 +171,8 @@ bool t_command_parser_executor::print_blockchain_info(const std::vector<std::str
|
||||
{
|
||||
if(!args.size())
|
||||
{
|
||||
std::cout << "need block index parameter" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
uint64_t start_index = 0;
|
||||
uint64_t end_index = 0;
|
||||
@ -158,20 +181,20 @@ bool t_command_parser_executor::print_blockchain_info(const std::vector<std::str
|
||||
int64_t nblocks;
|
||||
if(!epee::string_tools::get_xtype_from_string(nblocks, args[0]))
|
||||
{
|
||||
std::cout << "wrong number of blocks" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Wrong number of blocks. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
return m_executor.print_blockchain_info(nblocks, (uint64_t)-nblocks);
|
||||
}
|
||||
if(!epee::string_tools::get_xtype_from_string(start_index, args[0]))
|
||||
{
|
||||
std::cout << "wrong starter block index parameter" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Wrong starter block index parameter. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
if(args.size() >1 && !epee::string_tools::get_xtype_from_string(end_index, args[1]))
|
||||
{
|
||||
std::cout << "wrong end block index parameter" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Wrong end block index parameter. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.print_blockchain_info(start_index, end_index);
|
||||
@ -181,7 +204,7 @@ bool t_command_parser_executor::set_log_level(const std::vector<std::string>& ar
|
||||
{
|
||||
if(args.size() > 1)
|
||||
{
|
||||
std::cout << "use: set_log [<log_level_number_0-4> | <categories>]" << std::endl;
|
||||
std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -195,7 +218,7 @@ bool t_command_parser_executor::set_log_level(const std::vector<std::string>& ar
|
||||
{
|
||||
if(4 < l)
|
||||
{
|
||||
std::cout << "wrong number range, use: set_log <log_level_number_0-4>" << std::endl;
|
||||
std::cout << "Invalid syntax: Wrong number range, use: set_log <log_level_number_0-4>. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
return m_executor.set_log_level(l);
|
||||
@ -208,7 +231,10 @@ bool t_command_parser_executor::set_log_level(const std::vector<std::string>& ar
|
||||
|
||||
bool t_command_parser_executor::print_height(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.print_height();
|
||||
}
|
||||
@ -223,14 +249,14 @@ bool t_command_parser_executor::print_block(const std::vector<std::string>& args
|
||||
include_hex = true;
|
||||
else
|
||||
{
|
||||
std::cout << "unexpected argument: " << args[i] << std::endl;
|
||||
std::cout << "Invalid syntax: Unexpected parameter: " << args[i] << ". For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (args.empty())
|
||||
{
|
||||
std::cout << "expected: print_block (<block_hash> | <block_height>) [+hex]" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string& arg = args.front();
|
||||
@ -248,7 +274,7 @@ bool t_command_parser_executor::print_block(const std::vector<std::string>& args
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::print_transaction(const std::vector<std::string>& args)
|
||||
@ -267,13 +293,13 @@ bool t_command_parser_executor::print_transaction(const std::vector<std::string>
|
||||
include_json = true;
|
||||
else
|
||||
{
|
||||
std::cout << "unexpected argument: " << args[i] << std::endl;
|
||||
std::cout << "Invalid syntax: Unexpected parameter: " << args[i] << ". For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (args.empty())
|
||||
{
|
||||
std::cout << "expected: print_tx <transaction_hash> [+meta] [+hex] [+json]" << std::endl;
|
||||
std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -291,7 +317,7 @@ bool t_command_parser_executor::is_key_image_spent(const std::vector<std::string
|
||||
{
|
||||
if (args.empty())
|
||||
{
|
||||
std::cout << "expected: is_key_image_spent <key_image>" << std::endl;
|
||||
std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -309,21 +335,30 @@ bool t_command_parser_executor::is_key_image_spent(const std::vector<std::string
|
||||
|
||||
bool t_command_parser_executor::print_transaction_pool_long(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.print_transaction_pool_long();
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::print_transaction_pool_short(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.print_transaction_pool_short();
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::print_transaction_pool_stats(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.print_transaction_pool_stats();
|
||||
}
|
||||
@ -332,7 +367,7 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
|
||||
{
|
||||
if(!args.size())
|
||||
{
|
||||
std::cout << "Please specify a wallet address to mine for: start_mining <addr> [<threads>|auto]" << std::endl;
|
||||
std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -353,7 +388,7 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
|
||||
{
|
||||
if(!cryptonote::get_account_address_from_str(info, cryptonote::STAGENET, address_str))
|
||||
{
|
||||
std::cout << "target account address has wrong format" << std::endl;
|
||||
std::cout << "Invalid syntax: Target account address has wrong format. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@ -389,9 +424,10 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
|
||||
bool ignore_battery = false;
|
||||
if(args.size() > 4)
|
||||
{
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if(args.size() == 4)
|
||||
{
|
||||
if(args[3] == "true" || command_line::is_yes(args[3]) || args[3] == "1")
|
||||
@ -400,10 +436,11 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
|
||||
}
|
||||
else if(args[3] != "false" && !command_line::is_no(args[3]) && args[3] != "0")
|
||||
{
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Invalid combination of parameters. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(args.size() >= 3)
|
||||
{
|
||||
if(args[2] == "true" || command_line::is_yes(args[2]) || args[2] == "1")
|
||||
@ -412,10 +449,11 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
|
||||
}
|
||||
else if(args[2] != "false" && !command_line::is_no(args[2]) && args[2] != "0")
|
||||
{
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Invalid combination of parameters. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(args.size() >= 2)
|
||||
{
|
||||
if (args[1] == "auto" || args[1] == "autodetect")
|
||||
@ -436,7 +474,10 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
|
||||
|
||||
bool t_command_parser_executor::stop_mining(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.stop_mining();
|
||||
}
|
||||
@ -448,21 +489,31 @@ bool t_command_parser_executor::mining_status(const std::vector<std::string>& ar
|
||||
|
||||
bool t_command_parser_executor::stop_daemon(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.stop_daemon();
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::print_status(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.print_status();
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::set_limit(const std::vector<std::string>& args)
|
||||
{
|
||||
if(args.size()>1) return false;
|
||||
if(args.size()>1) {
|
||||
std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(args.size()==0) {
|
||||
return m_executor.get_limit();
|
||||
}
|
||||
@ -471,8 +522,8 @@ bool t_command_parser_executor::set_limit(const std::vector<std::string>& args)
|
||||
limit = std::stoll(args[0]);
|
||||
}
|
||||
catch(const std::exception& ex) {
|
||||
std::cout << "failed to parse argument" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Failed to parse limit. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.set_limit(limit, limit);
|
||||
@ -480,7 +531,11 @@ bool t_command_parser_executor::set_limit(const std::vector<std::string>& args)
|
||||
|
||||
bool t_command_parser_executor::set_limit_up(const std::vector<std::string>& args)
|
||||
{
|
||||
if(args.size()>1) return false;
|
||||
if(args.size()>1) {
|
||||
std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(args.size()==0) {
|
||||
return m_executor.get_limit_up();
|
||||
}
|
||||
@ -489,8 +544,8 @@ bool t_command_parser_executor::set_limit_up(const std::vector<std::string>& arg
|
||||
limit = std::stoll(args[0]);
|
||||
}
|
||||
catch(const std::exception& ex) {
|
||||
std::cout << "failed to parse argument" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Failed to parse limit. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.set_limit(0, limit);
|
||||
@ -498,7 +553,11 @@ bool t_command_parser_executor::set_limit_up(const std::vector<std::string>& arg
|
||||
|
||||
bool t_command_parser_executor::set_limit_down(const std::vector<std::string>& args)
|
||||
{
|
||||
if(args.size()>1) return false;
|
||||
if(args.size()>1) {
|
||||
std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(args.size()==0) {
|
||||
return m_executor.get_limit_down();
|
||||
}
|
||||
@ -507,8 +566,8 @@ bool t_command_parser_executor::set_limit_down(const std::vector<std::string>& a
|
||||
limit = std::stoll(args[0]);
|
||||
}
|
||||
catch(const std::exception& ex) {
|
||||
std::cout << "failed to parse argument" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Failed to parse limit. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.set_limit(limit, 0);
|
||||
@ -525,12 +584,13 @@ bool t_command_parser_executor::out_peers(const std::vector<std::string>& args)
|
||||
set = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
catch(const std::exception& ex) {
|
||||
_erro("stoi exception");
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Failed to parse number. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return m_executor.out_peers(set, limit);
|
||||
}
|
||||
|
||||
@ -548,7 +608,8 @@ bool t_command_parser_executor::in_peers(const std::vector<std::string>& args)
|
||||
|
||||
catch(const std::exception& ex) {
|
||||
_erro("stoi exception");
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Failed to parse number." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.in_peers(set, limit);
|
||||
@ -565,26 +626,37 @@ bool t_command_parser_executor::hard_fork_info(const std::vector<std::string>& a
|
||||
version = std::stoi(args[0]);
|
||||
}
|
||||
catch(const std::exception& ex) {
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Failed to parse version number. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
if (version <= 0 || version > 255) {
|
||||
std::cout << "Invalid syntax: Unknown version number. Must be between 0 and 255. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
if (version <= 0 || version > 255)
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
return m_executor.hard_fork_info(version);
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::show_bans(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!args.empty()) return false;
|
||||
if (!args.empty()) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.print_bans();
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::ban(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.size() != 1 && args.size() != 2) return false;
|
||||
if (args.size() != 1 && args.size() != 2) {
|
||||
std::cout << "Invalid syntax: Expects one or two parameters. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
std::string ip = args[0];
|
||||
time_t seconds = P2P_IP_BLOCKTIME;
|
||||
if (args.size() > 1)
|
||||
@ -595,11 +667,13 @@ bool t_command_parser_executor::ban(const std::vector<std::string>& args)
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Failed to parse seconds. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
if (seconds == 0)
|
||||
{
|
||||
return false;
|
||||
std::cout << "Seconds must be greater than 0." << std::endl;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return m_executor.ban(ip, seconds);
|
||||
@ -607,21 +681,31 @@ bool t_command_parser_executor::ban(const std::vector<std::string>& args)
|
||||
|
||||
bool t_command_parser_executor::unban(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.size() != 1) return false;
|
||||
if (args.size() != 1) {
|
||||
std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string ip = args[0];
|
||||
return m_executor.unban(ip);
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::banned(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.size() != 1) return false;
|
||||
if (args.size() != 1) {
|
||||
std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
std::string address = args[0];
|
||||
return m_executor.banned(address);
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::flush_txpool(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.size() > 1) return false;
|
||||
if (args.size() > 1) {
|
||||
std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string txid;
|
||||
if (args.size() == 1)
|
||||
@ -629,7 +713,7 @@ bool t_command_parser_executor::flush_txpool(const std::vector<std::string>& arg
|
||||
crypto::hash hash;
|
||||
if (!parse_hash256(args[0], hash))
|
||||
{
|
||||
std::cout << "failed to parse tx id" << std::endl;
|
||||
std::cout << "Invalid syntax: Failed to parse tx id. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
txid = args[0];
|
||||
@ -662,7 +746,7 @@ bool t_command_parser_executor::output_histogram(const std::vector<std::string>&
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Invalid syntax: more than two non-amount parameters" << std::endl;
|
||||
std::cout << "Invalid syntax: More than two non-amount parameters. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -673,20 +757,21 @@ bool t_command_parser_executor::print_coinbase_tx_sum(const std::vector<std::str
|
||||
{
|
||||
if(!args.size())
|
||||
{
|
||||
std::cout << "need block height parameter" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t height = 0;
|
||||
uint64_t count = 0;
|
||||
if(!epee::string_tools::get_xtype_from_string(height, args[0]))
|
||||
{
|
||||
std::cout << "wrong starter block height parameter" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Wrong starter block height parameter. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
if(args.size() >1 && !epee::string_tools::get_xtype_from_string(count, args[1]))
|
||||
{
|
||||
std::cout << "wrong count parameter" << std::endl;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.print_coinbase_tx_sum(height, count);
|
||||
@ -696,8 +781,8 @@ bool t_command_parser_executor::alt_chain_info(const std::vector<std::string>& a
|
||||
{
|
||||
if(args.size() > 1)
|
||||
{
|
||||
std::cout << "usage: alt_chain_info [block_hash|>N|-N]" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string tip;
|
||||
@ -709,16 +794,16 @@ bool t_command_parser_executor::alt_chain_info(const std::vector<std::string>& a
|
||||
{
|
||||
if (!epee::string_tools::get_xtype_from_string(above, args[0].c_str() + 1))
|
||||
{
|
||||
std::cout << "invalid above parameter" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Invalid above parameter. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (args[0].size() > 0 && args[0][0] == '-')
|
||||
{
|
||||
if (!epee::string_tools::get_xtype_from_string(last_blocks, args[0].c_str() + 1))
|
||||
{
|
||||
std::cout << "invalid last_blocks parameter" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Invalid last_blocks parameter. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -734,15 +819,15 @@ bool t_command_parser_executor::print_blockchain_dynamic_stats(const std::vector
|
||||
{
|
||||
if(args.size() != 1)
|
||||
{
|
||||
std::cout << "Exactly one parameter is needed" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t nblocks = 0;
|
||||
if(!epee::string_tools::get_xtype_from_string(nblocks, args[0]) || nblocks == 0)
|
||||
{
|
||||
std::cout << "wrong number of blocks" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Wrong number of blocks. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.print_blockchain_dynamic_stats(nblocks);
|
||||
@ -750,10 +835,10 @@ bool t_command_parser_executor::print_blockchain_dynamic_stats(const std::vector
|
||||
|
||||
bool t_command_parser_executor::update(const std::vector<std::string>& args)
|
||||
{
|
||||
if(args.size() != 1)
|
||||
if (args.size() != 1)
|
||||
{
|
||||
std::cout << "Exactly one parameter is needed: check, download, or update" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.update(args.front());
|
||||
@ -761,13 +846,17 @@ bool t_command_parser_executor::update(const std::vector<std::string>& args)
|
||||
|
||||
bool t_command_parser_executor::relay_tx(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.size() != 1) return false;
|
||||
if (args.size() != 1)
|
||||
{
|
||||
std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string txid;
|
||||
crypto::hash hash;
|
||||
if (!parse_hash256(args[0], hash))
|
||||
{
|
||||
std::cout << "failed to parse tx id" << std::endl;
|
||||
std::cout << "Invalid syntax: Failed to parse tx id. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
txid = args[0];
|
||||
@ -776,7 +865,10 @@ bool t_command_parser_executor::relay_tx(const std::vector<std::string>& args)
|
||||
|
||||
bool t_command_parser_executor::sync_info(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.size() != 0) return false;
|
||||
if (args.size() != 0) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.sync_info();
|
||||
}
|
||||
@ -785,8 +877,8 @@ bool t_command_parser_executor::pop_blocks(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.size() != 1)
|
||||
{
|
||||
std::cout << "Exactly one parameter is needed" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
@ -794,21 +886,24 @@ bool t_command_parser_executor::pop_blocks(const std::vector<std::string>& args)
|
||||
uint64_t nblocks = boost::lexical_cast<uint64_t>(args[0]);
|
||||
if (nblocks < 1)
|
||||
{
|
||||
std::cout << "number of blocks must be greater than 0" << std::endl;
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Number of blocks must be greater than 0. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
return m_executor.pop_blocks(nblocks);
|
||||
}
|
||||
catch (const boost::bad_lexical_cast&)
|
||||
{
|
||||
std::cout << "number of blocks must be a number greater than 0" << std::endl;
|
||||
std::cout << "Invalid syntax: Number of blocks must be a number greater than 0. For more details, use the help command." << std::endl;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::rpc_payments(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.size() != 0) return false;
|
||||
if (args.size() != 0) {
|
||||
std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.rpc_payments();
|
||||
}
|
||||
@ -820,7 +915,11 @@ bool t_command_parser_executor::version(const std::vector<std::string>& args)
|
||||
|
||||
bool t_command_parser_executor::prune_blockchain(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.size() > 1) return false;
|
||||
if (args.size() > 1)
|
||||
{
|
||||
std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.empty() || args[0] != "confirm")
|
||||
{
|
||||
@ -846,7 +945,8 @@ bool t_command_parser_executor::set_bootstrap_daemon(const std::vector<std::stri
|
||||
const size_t args_count = args.size();
|
||||
if (args_count < 1 || args_count > 3)
|
||||
{
|
||||
return false;
|
||||
std::cout << "Invalid syntax: Wrong number of parameters. For more details, use the help command." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_executor.set_bootstrap_daemon(
|
||||
|
@ -223,7 +223,8 @@ t_command_server::t_command_server(
|
||||
m_command_lookup.set_handler(
|
||||
"hard_fork_info"
|
||||
, std::bind(&t_command_parser_executor::hard_fork_info, &m_parser, p::_1)
|
||||
, "Print the hard fork voting information."
|
||||
, "hard_fork_info <version>"
|
||||
, "Print the hard fork voting information. If given a version, prints whether is this version enabled."
|
||||
);
|
||||
m_command_lookup.set_handler(
|
||||
"bans"
|
||||
@ -314,6 +315,7 @@ t_command_server::t_command_server(
|
||||
m_command_lookup.set_handler(
|
||||
"prune_blockchain"
|
||||
, std::bind(&t_command_parser_executor::prune_blockchain, &m_parser, p::_1)
|
||||
, "prune_blockchain [confirm]"
|
||||
, "Prune the blockchain."
|
||||
);
|
||||
m_command_lookup.set_handler(
|
||||
|
@ -66,10 +66,12 @@ uint16_t parse_public_rpc_port(const po::variables_map &vm)
|
||||
}
|
||||
|
||||
std::string rpc_port_str;
|
||||
std::string rpc_bind_address = command_line::get_arg(vm, cryptonote::rpc_args::descriptors().rpc_bind_ip);
|
||||
const auto &restricted_rpc_port = cryptonote::core_rpc_server::arg_rpc_restricted_bind_port;
|
||||
if (!command_line::is_arg_defaulted(vm, restricted_rpc_port))
|
||||
{
|
||||
rpc_port_str = command_line::get_arg(vm, restricted_rpc_port);
|
||||
rpc_bind_address = command_line::get_arg(vm, cryptonote::rpc_args::descriptors().rpc_restricted_bind_ip);
|
||||
}
|
||||
else if (command_line::get_arg(vm, cryptonote::core_rpc_server::arg_restricted_rpc))
|
||||
{
|
||||
@ -86,7 +88,6 @@ uint16_t parse_public_rpc_port(const po::variables_map &vm)
|
||||
throw std::runtime_error("invalid RPC port " + rpc_port_str);
|
||||
}
|
||||
|
||||
const auto rpc_bind_address = command_line::get_arg(vm, cryptonote::rpc_args::descriptors().rpc_bind_ip);
|
||||
const auto address = net::get_network_address(rpc_bind_address, rpc_port);
|
||||
if (!address) {
|
||||
throw std::runtime_error("failed to parse RPC bind address");
|
||||
|
@ -149,7 +149,7 @@ namespace nodetool
|
||||
{
|
||||
config_t()
|
||||
: m_net_config(),
|
||||
m_peer_id(crypto::rand<uint64_t>()),
|
||||
m_peer_id(1),
|
||||
m_support_flags(0)
|
||||
{}
|
||||
|
||||
@ -278,7 +278,7 @@ namespace nodetool
|
||||
uint32_t get_max_out_public_peers() const;
|
||||
void change_max_in_public_peers(size_t count);
|
||||
uint32_t get_max_in_public_peers() const;
|
||||
virtual bool block_host(const epee::net_utils::network_address &adress, time_t seconds = P2P_IP_BLOCKTIME);
|
||||
virtual bool block_host(epee::net_utils::network_address address, time_t seconds = P2P_IP_BLOCKTIME);
|
||||
virtual bool unblock_host(const epee::net_utils::network_address &address);
|
||||
virtual bool block_subnet(const epee::net_utils::ipv4_network_subnet &subnet, time_t seconds = P2P_IP_BLOCKTIME);
|
||||
virtual bool unblock_subnet(const epee::net_utils::ipv4_network_subnet &subnet);
|
||||
|
@ -139,7 +139,9 @@ namespace nodetool
|
||||
if (storage)
|
||||
m_peerlist_storage = std::move(*storage);
|
||||
|
||||
m_network_zones[epee::net_utils::zone::public_].m_config.m_support_flags = P2P_SUPPORT_FLAGS;
|
||||
network_zone& public_zone = m_network_zones[epee::net_utils::zone::public_];
|
||||
public_zone.m_config.m_support_flags = P2P_SUPPORT_FLAGS;
|
||||
public_zone.m_config.m_peer_id = crypto::rand<uint64_t>();
|
||||
m_first_connection_maker_call = true;
|
||||
|
||||
CATCH_ENTRY_L0("node_server::init_config", false);
|
||||
@ -224,7 +226,7 @@ namespace nodetool
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
bool node_server<t_payload_net_handler>::block_host(const epee::net_utils::network_address &addr, time_t seconds)
|
||||
bool node_server<t_payload_net_handler>::block_host(epee::net_utils::network_address addr, time_t seconds)
|
||||
{
|
||||
if(!addr.is_blockable())
|
||||
return false;
|
||||
@ -237,7 +239,8 @@ namespace nodetool
|
||||
limit = std::numeric_limits<time_t>::max();
|
||||
else
|
||||
limit = now + seconds;
|
||||
m_blocked_hosts[addr.host_str()] = limit;
|
||||
const std::string host_str = addr.host_str();
|
||||
m_blocked_hosts[host_str] = limit;
|
||||
|
||||
// drop any connection to that address. This should only have to look into
|
||||
// the zone related to the connection, but really make sure everything is
|
||||
@ -253,17 +256,18 @@ namespace nodetool
|
||||
}
|
||||
return true;
|
||||
});
|
||||
for (const auto &c: conns)
|
||||
zone.second.m_net_server.get_config_object().close(c);
|
||||
|
||||
conns.clear();
|
||||
|
||||
peerlist_entry pe{};
|
||||
pe.adr = addr;
|
||||
zone.second.m_peerlist.remove_from_peer_white(pe);
|
||||
|
||||
for (const auto &c: conns)
|
||||
zone.second.m_net_server.get_config_object().close(c);
|
||||
|
||||
conns.clear();
|
||||
}
|
||||
|
||||
MCLOG_CYAN(el::Level::Info, "global", "Host " << addr.host_str() << " blocked.");
|
||||
MCLOG_CYAN(el::Level::Info, "global", "Host " << host_str << " blocked.");
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
@ -402,7 +406,7 @@ namespace nodetool
|
||||
m_use_ipv6 = command_line::get_arg(vm, arg_p2p_use_ipv6);
|
||||
m_require_ipv4 = !command_line::get_arg(vm, arg_p2p_ignore_ipv4);
|
||||
public_zone.m_notifier = cryptonote::levin::notify{
|
||||
public_zone.m_net_server.get_io_service(), public_zone.m_net_server.get_config_shared(), nullptr, true, pad_txs, m_payload_handler.get_core()
|
||||
public_zone.m_net_server.get_io_service(), public_zone.m_net_server.get_config_shared(), nullptr, epee::net_utils::zone::public_, pad_txs, m_payload_handler.get_core()
|
||||
};
|
||||
|
||||
if (command_line::has_arg(vm, arg_p2p_add_peer))
|
||||
@ -545,7 +549,7 @@ namespace nodetool
|
||||
}
|
||||
|
||||
zone.m_notifier = cryptonote::levin::notify{
|
||||
zone.m_net_server.get_io_service(), zone.m_net_server.get_config_shared(), std::move(this_noise), false, pad_txs, m_payload_handler.get_core()
|
||||
zone.m_net_server.get_io_service(), zone.m_net_server.get_config_shared(), std::move(this_noise), proxy.zone, pad_txs, m_payload_handler.get_core()
|
||||
};
|
||||
}
|
||||
|
||||
@ -1099,11 +1103,12 @@ namespace nodetool
|
||||
pi = context.peer_id = rsp.node_data.peer_id;
|
||||
context.m_rpc_port = rsp.node_data.rpc_port;
|
||||
context.m_rpc_credits_per_hash = rsp.node_data.rpc_credits_per_hash;
|
||||
network_zone& zone = m_network_zones.at(context.m_remote_address.get_zone());
|
||||
const auto azone = context.m_remote_address.get_zone();
|
||||
network_zone& zone = m_network_zones.at(azone);
|
||||
zone.m_peerlist.set_peer_just_seen(rsp.node_data.peer_id, context.m_remote_address, context.m_pruning_seed, context.m_rpc_port, context.m_rpc_credits_per_hash);
|
||||
|
||||
// move
|
||||
if(rsp.node_data.peer_id == zone.m_config.m_peer_id)
|
||||
if(azone == epee::net_utils::zone::public_ && rsp.node_data.peer_id == zone.m_config.m_peer_id)
|
||||
{
|
||||
LOG_DEBUG_CC(context, "Connection to self detected, dropping connection");
|
||||
hsh_result = false;
|
||||
@ -1195,50 +1200,51 @@ namespace nodetool
|
||||
template<class t_payload_net_handler>
|
||||
bool node_server<t_payload_net_handler>::is_peer_used(const peerlist_entry& peer)
|
||||
{
|
||||
for(const auto& zone : m_network_zones)
|
||||
if(zone.second.m_config.m_peer_id == peer.id)
|
||||
return true;//dont make connections to ourself
|
||||
const auto zone = peer.adr.get_zone();
|
||||
const auto server = m_network_zones.find(zone);
|
||||
if (server == m_network_zones.end())
|
||||
return false;
|
||||
|
||||
const bool is_public = (zone == epee::net_utils::zone::public_);
|
||||
if(is_public && server->second.m_config.m_peer_id == peer.id)
|
||||
return true;//dont make connections to ourself
|
||||
|
||||
bool used = false;
|
||||
for(auto& zone : m_network_zones)
|
||||
server->second.m_net_server.get_config_object().foreach_connection([&, is_public](const p2p_connection_context& cntxt)
|
||||
{
|
||||
zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
|
||||
if((is_public && cntxt.peer_id == peer.id) || (!cntxt.m_is_income && peer.adr == cntxt.m_remote_address))
|
||||
{
|
||||
if(cntxt.peer_id == peer.id || (!cntxt.m_is_income && peer.adr == cntxt.m_remote_address))
|
||||
{
|
||||
used = true;
|
||||
return false;//stop enumerating
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if(used)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
used = true;
|
||||
return false;//stop enumerating
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return used;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
bool node_server<t_payload_net_handler>::is_peer_used(const anchor_peerlist_entry& peer)
|
||||
{
|
||||
for(auto& zone : m_network_zones) {
|
||||
if(zone.second.m_config.m_peer_id == peer.id) {
|
||||
return true;//dont make connections to ourself
|
||||
}
|
||||
bool used = false;
|
||||
zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
|
||||
const auto zone = peer.adr.get_zone();
|
||||
const auto server = m_network_zones.find(zone);
|
||||
if (server == m_network_zones.end())
|
||||
return false;
|
||||
|
||||
const bool is_public = (zone == epee::net_utils::zone::public_);
|
||||
if(is_public && server->second.m_config.m_peer_id == peer.id)
|
||||
return true;//dont make connections to ourself
|
||||
|
||||
bool used = false;
|
||||
server->second.m_net_server.get_config_object().foreach_connection([&, is_public](const p2p_connection_context& cntxt)
|
||||
{
|
||||
if((is_public && cntxt.peer_id == peer.id) || (!cntxt.m_is_income && peer.adr == cntxt.m_remote_address))
|
||||
{
|
||||
if(cntxt.peer_id == peer.id || (!cntxt.m_is_income && peer.adr == cntxt.m_remote_address))
|
||||
{
|
||||
used = true;
|
||||
return false;//stop enumerating
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (used)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
used = true;
|
||||
return false;//stop enumerating
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return used;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
@ -1281,6 +1287,9 @@ namespace nodetool
|
||||
if (zone.m_connect == nullptr) // outgoing connections in zone not possible
|
||||
return false;
|
||||
|
||||
if (zone.m_our_address == na)
|
||||
return false;
|
||||
|
||||
if (zone.m_current_number_of_out_peers == zone.m_config.m_net_config.max_out_connection_count) // out peers limit
|
||||
{
|
||||
return false;
|
||||
@ -1608,6 +1617,9 @@ namespace nodetool
|
||||
peerid_to_string(pe.id) << " " << pe.adr.str() << ", pruning seed " << epee::string_tools::to_string_hex(pe.pruning_seed) <<
|
||||
" (stripe " << next_needed_pruning_stripe << " needed)");
|
||||
|
||||
if(zone.m_our_address == pe.adr)
|
||||
continue;
|
||||
|
||||
if(is_peer_used(pe)) {
|
||||
_note("Peer is used");
|
||||
continue;
|
||||
@ -2016,6 +2028,11 @@ namespace nodetool
|
||||
template<class t_payload_net_handler>
|
||||
bool node_server<t_payload_net_handler>::handle_remote_peerlist(const std::vector<peerlist_entry>& peerlist, const epee::net_utils::connection_context_base& context)
|
||||
{
|
||||
if (peerlist.size() > P2P_MAX_PEERS_IN_HANDSHAKE)
|
||||
{
|
||||
MWARNING(context << "peer sent " << peerlist.size() << " peers, considered spamming");
|
||||
return false;
|
||||
}
|
||||
std::vector<peerlist_entry> peerlist_ = peerlist;
|
||||
if(!sanitize_peerlist(peerlist_))
|
||||
return false;
|
||||
@ -2189,7 +2206,7 @@ namespace nodetool
|
||||
|
||||
const epee::net_utils::network_address na = context.m_remote_address;
|
||||
std::string ip;
|
||||
uint32_t ipv4_addr;
|
||||
uint32_t ipv4_addr = 0;
|
||||
boost::asio::ip::address_v6 ipv6_addr;
|
||||
bool is_ipv4;
|
||||
if (na.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id())
|
||||
@ -2376,11 +2393,12 @@ namespace nodetool
|
||||
return 1;
|
||||
}
|
||||
|
||||
network_zone& zone = m_network_zones.at(context.m_remote_address.get_zone());
|
||||
const auto azone = context.m_remote_address.get_zone();
|
||||
network_zone& zone = m_network_zones.at(azone);
|
||||
|
||||
// test only the remote end's zone, otherwise an attacker could connect to you on clearnet
|
||||
// and pass in a tor connection's peer id, and deduce the two are the same if you reject it
|
||||
if(arg.node_data.peer_id == zone.m_config.m_peer_id)
|
||||
if(azone == epee::net_utils::zone::public_ && arg.node_data.peer_id == zone.m_config.m_peer_id)
|
||||
{
|
||||
LOG_DEBUG_CC(context, "Connection to self detected, dropping connection");
|
||||
drop_connection(context);
|
||||
|
@ -58,7 +58,7 @@ namespace nodetool
|
||||
virtual uint64_t get_public_connections_count()=0;
|
||||
virtual void for_each_connection(std::function<bool(t_connection_context&, peerid_type, uint32_t)> f)=0;
|
||||
virtual bool for_connection(const boost::uuids::uuid&, std::function<bool(t_connection_context&, peerid_type, uint32_t)> f)=0;
|
||||
virtual bool block_host(const epee::net_utils::network_address &address, time_t seconds = 0)=0;
|
||||
virtual bool block_host(epee::net_utils::network_address address, time_t seconds = 0)=0;
|
||||
virtual bool unblock_host(const epee::net_utils::network_address &address)=0;
|
||||
virtual std::map<std::string, time_t> get_blocked_hosts()=0;
|
||||
virtual std::map<epee::net_utils::ipv4_network_subnet, time_t> get_blocked_subnets()=0;
|
||||
@ -108,7 +108,7 @@ namespace nodetool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual bool block_host(const epee::net_utils::network_address &address, time_t seconds)
|
||||
virtual bool block_host(epee::net_utils::network_address address, time_t seconds)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -288,6 +288,19 @@ namespace nodetool
|
||||
copy_peers(peers.gray, m_peers_gray.get<by_addr>());
|
||||
copy_peers(peers.anchor, m_peers_anchor.get<by_addr>());
|
||||
}
|
||||
|
||||
void peerlist_manager::evict_host_from_white_peerlist(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_CLASS_VERSION(nodetool::peerlist_types, nodetool::CURRENT_PEERLIST_STORAGE_ARCHIVE_VER);
|
||||
|
@ -109,6 +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);
|
||||
bool append_with_peer_white(const peerlist_entry& pr);
|
||||
bool append_with_peer_gray(const peerlist_entry& pr);
|
||||
bool append_with_peer_anchor(const anchor_peerlist_entry& ple);
|
||||
@ -345,6 +346,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);
|
||||
m_peers_white.insert(ple);
|
||||
trim_white_peerlist();
|
||||
}else
|
||||
|
@ -66,7 +66,7 @@ set(rpc_pub_headers zmq_pub.h)
|
||||
|
||||
set(daemon_rpc_server_headers)
|
||||
|
||||
set(rpc_daemon_private_headers
|
||||
set(rpc_private_headers
|
||||
bootstrap_daemon.h
|
||||
core_rpc_server.h
|
||||
rpc_payment.h
|
||||
|
@ -45,12 +45,12 @@ namespace cryptonote
|
||||
return host + ":" + m_http_client.get_port();
|
||||
}
|
||||
|
||||
boost::optional<uint64_t> bootstrap_daemon::get_height()
|
||||
boost::optional<std::pair<uint64_t, uint64_t>> bootstrap_daemon::get_height()
|
||||
{
|
||||
cryptonote::COMMAND_RPC_GET_HEIGHT::request req;
|
||||
cryptonote::COMMAND_RPC_GET_HEIGHT::response res;
|
||||
cryptonote::COMMAND_RPC_GET_INFO::request req;
|
||||
cryptonote::COMMAND_RPC_GET_INFO::response res;
|
||||
|
||||
if (!invoke_http_json("/getheight", req, res))
|
||||
if (!invoke_http_json("/getinfo", req, res))
|
||||
{
|
||||
return boost::none;
|
||||
}
|
||||
@ -60,7 +60,7 @@ namespace cryptonote
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
return res.height;
|
||||
return {{res.height, res.target_height}};
|
||||
}
|
||||
|
||||
bool bootstrap_daemon::handle_result(bool success, const std::string &status)
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
@ -27,7 +28,7 @@ namespace cryptonote
|
||||
bool rpc_payment_enabled);
|
||||
|
||||
std::string address() const noexcept;
|
||||
boost::optional<uint64_t> get_height();
|
||||
boost::optional<std::pair<uint64_t, uint64_t>> get_height();
|
||||
bool handle_result(bool success, const std::string &status);
|
||||
|
||||
template <class t_request, class t_response>
|
||||
|
@ -264,6 +264,18 @@ namespace cryptonote
|
||||
if (!rpc_config)
|
||||
return false;
|
||||
|
||||
std::string bind_ip_str = rpc_config->bind_ip;
|
||||
std::string bind_ipv6_str = rpc_config->bind_ipv6_address;
|
||||
if (restricted)
|
||||
{
|
||||
const auto restricted_rpc_port_arg = cryptonote::core_rpc_server::arg_rpc_restricted_bind_port;
|
||||
const bool has_restricted_rpc_port_arg = !command_line::is_arg_defaulted(vm, restricted_rpc_port_arg);
|
||||
if (has_restricted_rpc_port_arg && port == command_line::get_arg(vm, restricted_rpc_port_arg))
|
||||
{
|
||||
bind_ip_str = rpc_config->restricted_bind_ip;
|
||||
bind_ipv6_str = rpc_config->restricted_bind_ipv6_address;
|
||||
}
|
||||
}
|
||||
disable_rpc_ban = rpc_config->disable_rpc_ban;
|
||||
std::string address = command_line::get_arg(vm, arg_rpc_payment_address);
|
||||
if (!address.empty() && allow_rpc_payment)
|
||||
@ -300,7 +312,7 @@ namespace cryptonote
|
||||
if (!m_rpc_payment)
|
||||
{
|
||||
uint32_t bind_ip;
|
||||
bool ok = epee::string_tools::get_ip_int32_from_string(bind_ip, rpc_config->bind_ip);
|
||||
bool ok = epee::string_tools::get_ip_int32_from_string(bind_ip, bind_ip_str);
|
||||
if (ok & !epee::net_utils::is_ip_loopback(bind_ip))
|
||||
MWARNING("The RPC server is accessible from the outside, but no RPC payment was setup. RPC access will be free for all.");
|
||||
}
|
||||
@ -322,8 +334,8 @@ namespace cryptonote
|
||||
|
||||
auto rng = [](size_t len, uint8_t *ptr){ return crypto::rand(len, ptr); };
|
||||
return epee::http_server_impl_base<core_rpc_server, connection_context>::init(
|
||||
rng, std::move(port), std::move(rpc_config->bind_ip),
|
||||
std::move(rpc_config->bind_ipv6_address), std::move(rpc_config->use_ipv6), std::move(rpc_config->require_ipv4),
|
||||
rng, std::move(port), std::move(bind_ip_str),
|
||||
std::move(bind_ipv6_str), std::move(rpc_config->use_ipv6), std::move(rpc_config->require_ipv4),
|
||||
std::move(rpc_config->access_control_origins), std::move(http_login), std::move(rpc_config->ssl_options)
|
||||
);
|
||||
}
|
||||
@ -486,6 +498,8 @@ namespace cryptonote
|
||||
res.database_size = round_up(res.database_size, 5ull* 1024 * 1024 * 1024);
|
||||
res.update_available = restricted ? false : m_core.is_update_available();
|
||||
res.version = restricted ? "" : MONERO_VERSION_FULL;
|
||||
res.synchronized = check_core_ready();
|
||||
res.busy_syncing = m_p2p.get_payload_object().is_busy_syncing();
|
||||
|
||||
res.status = CORE_RPC_STATUS_OK;
|
||||
return true;
|
||||
@ -1142,7 +1156,7 @@ namespace cryptonote
|
||||
if (!restricted)
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
|
||||
if (m_bootstrap_daemon.get() != nullptr)
|
||||
if (m_should_use_bootstrap_daemon)
|
||||
{
|
||||
skip_validation = !check_core_ready();
|
||||
}
|
||||
@ -1151,6 +1165,10 @@ namespace cryptonote
|
||||
CHECK_CORE_READY();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_CORE_READY();
|
||||
}
|
||||
|
||||
CHECK_PAYMENT_MIN1(req, res, COST_PER_TX_RELAY, false);
|
||||
|
||||
@ -1988,34 +2006,37 @@ namespace cryptonote
|
||||
}
|
||||
|
||||
auto current_time = std::chrono::system_clock::now();
|
||||
if (!m_p2p.get_payload_object().no_sync() &&
|
||||
current_time - m_bootstrap_height_check_time > std::chrono::seconds(30)) // update every 30s
|
||||
if (current_time - m_bootstrap_height_check_time > std::chrono::seconds(30)) // update every 30s
|
||||
{
|
||||
{
|
||||
boost::upgrade_to_unique_lock<boost::shared_mutex> lock(upgrade_lock);
|
||||
m_bootstrap_height_check_time = current_time;
|
||||
}
|
||||
|
||||
boost::optional<uint64_t> bootstrap_daemon_height = m_bootstrap_daemon->get_height();
|
||||
if (!bootstrap_daemon_height)
|
||||
boost::optional<std::pair<uint64_t, uint64_t>> bootstrap_daemon_height_info = m_bootstrap_daemon->get_height();
|
||||
if (!bootstrap_daemon_height_info)
|
||||
{
|
||||
MERROR("Failed to fetch bootstrap daemon height");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t target_height = m_core.get_target_blockchain_height();
|
||||
if (*bootstrap_daemon_height < target_height)
|
||||
const uint64_t bootstrap_daemon_height = bootstrap_daemon_height_info->first;
|
||||
const uint64_t bootstrap_daemon_target_height = bootstrap_daemon_height_info->second;
|
||||
if (bootstrap_daemon_height < bootstrap_daemon_target_height)
|
||||
{
|
||||
MINFO("Bootstrap daemon is out of sync");
|
||||
return m_bootstrap_daemon->handle_result(false, {});
|
||||
}
|
||||
|
||||
uint64_t top_height = m_core.get_current_blockchain_height();
|
||||
m_should_use_bootstrap_daemon = top_height + 10 < *bootstrap_daemon_height;
|
||||
MINFO((m_should_use_bootstrap_daemon ? "Using" : "Not using") << " the bootstrap daemon (our height: " << top_height << ", bootstrap daemon's height: " << *bootstrap_daemon_height << ")");
|
||||
if (!m_p2p.get_payload_object().no_sync())
|
||||
{
|
||||
uint64_t top_height = m_core.get_current_blockchain_height();
|
||||
m_should_use_bootstrap_daemon = top_height + 10 < bootstrap_daemon_height;
|
||||
MINFO((m_should_use_bootstrap_daemon ? "Using" : "Not using") << " the bootstrap daemon (our height: " << top_height << ", bootstrap daemon's height: " << bootstrap_daemon_height << ")");
|
||||
|
||||
if (!m_should_use_bootstrap_daemon)
|
||||
return false;
|
||||
if (!m_should_use_bootstrap_daemon)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == invoke_http_mode::JON)
|
||||
@ -2895,11 +2916,7 @@ namespace cryptonote
|
||||
block_queue.foreach([&](const cryptonote::block_queue::span &span) {
|
||||
const std::string span_connection_id = epee::string_tools::pod_to_hex(span.connection_id);
|
||||
uint32_t speed = (uint32_t)(100.0f * block_queue.get_speed(span.connection_id) + 0.5f);
|
||||
std::string address = "";
|
||||
for (const auto &c: m_p2p.get_payload_object().get_connections())
|
||||
if (c.connection_id == span_connection_id)
|
||||
address = c.address;
|
||||
res.spans.push_back({span.start_block_height, span.nblocks, span_connection_id, (uint32_t)(span.rate + 0.5f), speed, span.size, address});
|
||||
res.spans.push_back({span.start_block_height, span.nblocks, span_connection_id, (uint32_t)(span.rate + 0.5f), speed, span.size, span.origin.str()});
|
||||
return true;
|
||||
});
|
||||
res.overview = block_queue.get_overview(res.height);
|
||||
|
@ -88,7 +88,7 @@ namespace cryptonote
|
||||
// advance which version they will stop working with
|
||||
// Don't go over 32767 for any of these
|
||||
#define CORE_RPC_VERSION_MAJOR 3
|
||||
#define CORE_RPC_VERSION_MINOR 2
|
||||
#define CORE_RPC_VERSION_MINOR 4
|
||||
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
|
||||
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
|
||||
|
||||
@ -684,7 +684,9 @@ namespace cryptonote
|
||||
bool was_bootstrap_ever_used;
|
||||
uint64_t database_size;
|
||||
bool update_available;
|
||||
bool busy_syncing;
|
||||
std::string version;
|
||||
bool synchronized;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_PARENT(rpc_access_response_base)
|
||||
@ -723,7 +725,9 @@ namespace cryptonote
|
||||
KV_SERIALIZE(was_bootstrap_ever_used)
|
||||
KV_SERIALIZE(database_size)
|
||||
KV_SERIALIZE(update_available)
|
||||
KV_SERIALIZE(busy_syncing)
|
||||
KV_SERIALIZE(version)
|
||||
KV_SERIALIZE(synchronized)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
|
@ -91,6 +91,8 @@ namespace cryptonote
|
||||
rpc_args::descriptors::descriptors()
|
||||
: rpc_bind_ip({"rpc-bind-ip", rpc_args::tr("Specify IP to bind RPC server"), "127.0.0.1"})
|
||||
, rpc_bind_ipv6_address({"rpc-bind-ipv6-address", rpc_args::tr("Specify IPv6 address to bind RPC server"), "::1"})
|
||||
, rpc_restricted_bind_ip({"rpc-restricted-bind-ip", rpc_args::tr("Specify IP to bind restricted RPC server"), "127.0.0.1"})
|
||||
, rpc_restricted_bind_ipv6_address({"rpc-restricted-bind-ipv6-address", rpc_args::tr("Specify IPv6 address to bind restricted RPC server"), "::1"})
|
||||
, rpc_use_ipv6({"rpc-use-ipv6", rpc_args::tr("Allow IPv6 for RPC"), false})
|
||||
, rpc_ignore_ipv4({"rpc-ignore-ipv4", rpc_args::tr("Ignore unsuccessful IPv4 bind for RPC"), false})
|
||||
, rpc_login({"rpc-login", rpc_args::tr("Specify username[:password] required for RPC server"), "", true})
|
||||
@ -113,6 +115,8 @@ namespace cryptonote
|
||||
const descriptors arg{};
|
||||
command_line::add_arg(desc, arg.rpc_bind_ip);
|
||||
command_line::add_arg(desc, arg.rpc_bind_ipv6_address);
|
||||
command_line::add_arg(desc, arg.rpc_restricted_bind_ip);
|
||||
command_line::add_arg(desc, arg.rpc_restricted_bind_ipv6_address);
|
||||
command_line::add_arg(desc, arg.rpc_use_ipv6);
|
||||
command_line::add_arg(desc, arg.rpc_ignore_ipv4);
|
||||
command_line::add_arg(desc, arg.rpc_login);
|
||||
@ -136,6 +140,8 @@ namespace cryptonote
|
||||
|
||||
config.bind_ip = command_line::get_arg(vm, arg.rpc_bind_ip);
|
||||
config.bind_ipv6_address = command_line::get_arg(vm, arg.rpc_bind_ipv6_address);
|
||||
config.restricted_bind_ip = command_line::get_arg(vm, arg.rpc_restricted_bind_ip);
|
||||
config.restricted_bind_ipv6_address = command_line::get_arg(vm, arg.rpc_restricted_bind_ipv6_address);
|
||||
config.use_ipv6 = command_line::get_arg(vm, arg.rpc_use_ipv6);
|
||||
config.require_ipv4 = !command_line::get_arg(vm, arg.rpc_ignore_ipv4);
|
||||
config.disable_rpc_ban = command_line::get_arg(vm, arg.disable_rpc_ban);
|
||||
@ -188,6 +194,34 @@ namespace cryptonote
|
||||
return boost::none;
|
||||
}
|
||||
}
|
||||
if (!config.restricted_bind_ip.empty())
|
||||
{
|
||||
// always parse IP here for error consistency
|
||||
boost::system::error_code ec{};
|
||||
boost::asio::ip::address::from_string(config.restricted_bind_ip, ec);
|
||||
if (ec)
|
||||
{
|
||||
LOG_ERROR(tr("Invalid IP address given for --") << arg.rpc_restricted_bind_ip.name);
|
||||
return boost::none;
|
||||
}
|
||||
}
|
||||
if (!config.restricted_bind_ipv6_address.empty())
|
||||
{
|
||||
// allow square braces, but remove them here if present
|
||||
if (config.restricted_bind_ipv6_address.find('[') != std::string::npos)
|
||||
{
|
||||
config.restricted_bind_ipv6_address = config.restricted_bind_ipv6_address.substr(1, config.restricted_bind_ipv6_address.size() - 2);
|
||||
}
|
||||
|
||||
// always parse IP here for error consistency
|
||||
boost::system::error_code ec{};
|
||||
boost::asio::ip::address::from_string(config.restricted_bind_ipv6_address, ec);
|
||||
if (ec)
|
||||
{
|
||||
LOG_ERROR(tr("Invalid IP address given for --") << arg.rpc_restricted_bind_ipv6_address.name);
|
||||
return boost::none;
|
||||
}
|
||||
}
|
||||
|
||||
const char *env_rpc_login = nullptr;
|
||||
const bool has_rpc_arg = command_line::has_arg(vm, arg.rpc_login);
|
||||
|
@ -53,6 +53,8 @@ namespace cryptonote
|
||||
|
||||
const command_line::arg_descriptor<std::string> rpc_bind_ip;
|
||||
const command_line::arg_descriptor<std::string> rpc_bind_ipv6_address;
|
||||
const command_line::arg_descriptor<std::string> rpc_restricted_bind_ip;
|
||||
const command_line::arg_descriptor<std::string> rpc_restricted_bind_ipv6_address;
|
||||
const command_line::arg_descriptor<bool> rpc_use_ipv6;
|
||||
const command_line::arg_descriptor<bool> rpc_ignore_ipv4;
|
||||
const command_line::arg_descriptor<std::string> rpc_login;
|
||||
@ -81,6 +83,8 @@ namespace cryptonote
|
||||
|
||||
std::string bind_ip;
|
||||
std::string bind_ipv6_address;
|
||||
std::string restricted_bind_ip;
|
||||
std::string restricted_bind_ipv6_address;
|
||||
bool use_ipv6;
|
||||
bool require_ipv4;
|
||||
std::vector<std::string> access_control_origins;
|
||||
|
@ -221,7 +221,7 @@ namespace
|
||||
void add_subscriptions(std::array<std::size_t, N>& subs, const epee::span<const context<T>> range, context<T> const* const first)
|
||||
{
|
||||
assert(range.size() <= N);
|
||||
assert(range.begin() - first <= N - range.size());
|
||||
assert((unsigned long)(range.begin() - first) <= N - range.size());
|
||||
|
||||
for (const auto& ctx : range)
|
||||
{
|
||||
@ -234,7 +234,7 @@ namespace
|
||||
void remove_subscriptions(std::array<std::size_t, N>& subs, const epee::span<const context<T>> range, context<T> const* const first)
|
||||
{
|
||||
assert(range.size() <= N);
|
||||
assert(range.begin() - first <= N - range.size());
|
||||
assert((unsigned long)(range.begin() - first) <= N - range.size());
|
||||
|
||||
for (const auto& ctx : range)
|
||||
{
|
||||
|
@ -212,6 +212,10 @@ void TransactionHistoryImpl::refresh()
|
||||
ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "";
|
||||
ti->m_timestamp = pd.m_timestamp;
|
||||
ti->m_confirmations = 0;
|
||||
for (const auto &d : pd.m_dests)
|
||||
{
|
||||
ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id)});
|
||||
}
|
||||
m_history.push_back(ti);
|
||||
}
|
||||
|
||||
|
@ -2963,7 +2963,8 @@ void wallet2::update_pool_state(std::vector<std::tuple<cryptonote::transaction,
|
||||
MTRACE("update_pool_state got pool");
|
||||
|
||||
// remove any pending tx that's not in the pool
|
||||
constexpr const std::chrono::seconds tx_propagation_timeout{CRYPTONOTE_DANDELIONPP_EMBARGO_AVERAGE * 3 / 2};
|
||||
// TODO: set tx_propagation_timeout to CRYPTONOTE_DANDELIONPP_EMBARGO_AVERAGE * 3 / 2 after v15 hardfork
|
||||
constexpr const std::chrono::seconds tx_propagation_timeout{500};
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
std::unordered_map<crypto::hash, wallet2::unconfirmed_transfer_details>::iterator it = m_unconfirmed_txs.begin();
|
||||
while (it != m_unconfirmed_txs.end())
|
||||
@ -3772,7 +3773,7 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee::wipeable_string& password, bool watch_only)
|
||||
{
|
||||
std::string account_data;
|
||||
epee::byte_slice account_data;
|
||||
std::string multisig_signers;
|
||||
std::string multisig_derivations;
|
||||
cryptonote::account_base account = m_account;
|
||||
@ -3799,7 +3800,7 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee:
|
||||
rapidjson::Document json;
|
||||
json.SetObject();
|
||||
rapidjson::Value value(rapidjson::kStringType);
|
||||
value.SetString(account_data.c_str(), account_data.length());
|
||||
value.SetString(reinterpret_cast<const char*>(account_data.data()), account_data.size());
|
||||
json.AddMember("key_data", value, json.GetAllocator());
|
||||
if (!seed_language.empty())
|
||||
{
|
||||
@ -3970,13 +3971,12 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee:
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
json.Accept(writer);
|
||||
account_data = buffer.GetString();
|
||||
|
||||
// Encrypt the entire JSON object.
|
||||
std::string cipher;
|
||||
cipher.resize(account_data.size());
|
||||
cipher.resize(buffer.GetSize());
|
||||
keys_file_data.get().iv = crypto::rand<crypto::chacha_iv>();
|
||||
crypto::chacha20(account_data.data(), account_data.size(), key, keys_file_data.get().iv, &cipher[0]);
|
||||
crypto::chacha20(buffer.GetString(), buffer.GetSize(), key, keys_file_data.get().iv, &cipher[0]);
|
||||
keys_file_data.get().account_data = cipher;
|
||||
return keys_file_data;
|
||||
}
|
||||
@ -13376,6 +13376,20 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
|
||||
loaded = true;
|
||||
}
|
||||
CHECK_AND_ASSERT_THROW_MES(loaded, "Failed to load output data");
|
||||
|
||||
for (const auto &e: i)
|
||||
{
|
||||
for (const auto &lr: e.m_LR)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(rct::isInMainSubgroup(lr.m_L), "Multisig value is not in the main subgroup");
|
||||
CHECK_AND_ASSERT_THROW_MES(rct::isInMainSubgroup(lr.m_R), "Multisig value is not in the main subgroup");
|
||||
}
|
||||
for (const auto &ki: e.m_partial_key_images)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(rct::isInMainSubgroup(rct::ki2rct(ki)), "Multisig partial key image is not in the main subgroup");
|
||||
}
|
||||
}
|
||||
|
||||
MINFO(boost::format("%u outputs found") % boost::lexical_cast<std::string>(i.size()));
|
||||
info.push_back(std::move(i));
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ set(hash_targets_sources
|
||||
|
||||
set(hash_targets_headers)
|
||||
|
||||
add_executable(hash-target-tests
|
||||
monero_add_minimal_executable(hash-target-tests
|
||||
${hash_targets_sources}
|
||||
${hash_targets_headers})
|
||||
target_link_libraries(hash-target-tests
|
||||
@ -149,7 +149,7 @@ foreach(BENCH IN LISTS MONERO_WALLET_CRYPTO_BENCH)
|
||||
endforeach ()
|
||||
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/benchmark.h.in" "${MONERO_GENERATED_HEADERS_DIR}/tests/benchmark.h")
|
||||
add_executable(monero-wallet-crypto-bench benchmark.cpp ${BENCH_OBJECTS})
|
||||
monero_add_minimal_executable(monero-wallet-crypto-bench benchmark.cpp ${BENCH_OBJECTS})
|
||||
target_link_libraries(monero-wallet-crypto-bench cncrypto)
|
||||
|
||||
add_test(NAME wallet-crypto-bench COMMAND monero-wallet-crypto-bench)
|
||||
|
@ -31,7 +31,7 @@ set(block_weight_sources
|
||||
|
||||
set(block_weight_headers)
|
||||
|
||||
add_executable(block_weight
|
||||
monero_add_minimal_executable(block_weight
|
||||
${block_weight_sources}
|
||||
${block_weight_headers})
|
||||
target_link_libraries(block_weight
|
||||
|
@ -32,7 +32,7 @@ set(core_proxy_sources
|
||||
set(core_proxy_headers
|
||||
core_proxy.h)
|
||||
|
||||
add_executable(core_proxy
|
||||
monero_add_minimal_executable(core_proxy
|
||||
${core_proxy_sources}
|
||||
${core_proxy_headers})
|
||||
target_link_libraries(core_proxy
|
||||
|
@ -66,9 +66,10 @@ namespace tests
|
||||
|
||||
|
||||
public:
|
||||
virtual bool is_synchronized() const final { return true; }
|
||||
void on_synchronized(){}
|
||||
void safesyncmode(const bool){}
|
||||
uint64_t get_current_blockchain_height(){return 1;}
|
||||
virtual uint64_t get_current_blockchain_height() const final {return 1;}
|
||||
void set_target_blockchain_height(uint64_t) {}
|
||||
bool init(const boost::program_options::variables_map& vm);
|
||||
bool deinit(){return true;}
|
||||
|
@ -68,7 +68,7 @@ set(core_tests_headers
|
||||
rct2.h
|
||||
wallet_tools.h)
|
||||
|
||||
add_executable(core_tests
|
||||
monero_add_minimal_executable(core_tests
|
||||
${core_tests_sources}
|
||||
${core_tests_headers})
|
||||
target_link_libraries(core_tests
|
||||
|
@ -37,7 +37,7 @@ set(crypto_sources
|
||||
set(crypto_headers
|
||||
crypto-tests.h)
|
||||
|
||||
add_executable(cncrypto-tests
|
||||
monero_add_minimal_executable(cncrypto-tests
|
||||
${crypto_sources}
|
||||
${crypto_headers})
|
||||
target_link_libraries(cncrypto-tests
|
||||
@ -53,7 +53,7 @@ add_test(
|
||||
NAME cncrypto
|
||||
COMMAND cncrypto-tests "${CMAKE_CURRENT_SOURCE_DIR}/tests.txt")
|
||||
|
||||
add_executable(cnv4-jit-tests cnv4-jit.c)
|
||||
monero_add_minimal_executable(cnv4-jit-tests cnv4-jit.c)
|
||||
target_link_libraries(cnv4-jit-tests
|
||||
PRIVATE
|
||||
common
|
||||
|
File diff suppressed because one or more lines are too long
@ -31,7 +31,7 @@ set(transfers_sources
|
||||
|
||||
set(transfers_headers)
|
||||
|
||||
add_executable(transfers
|
||||
monero_add_minimal_executable(transfers
|
||||
${transfers_sources}
|
||||
${transfers_headers})
|
||||
target_link_libraries(transfers
|
||||
|
@ -31,7 +31,7 @@ set(difficulty_sources
|
||||
|
||||
set(difficulty_headers)
|
||||
|
||||
add_executable(difficulty-tests
|
||||
monero_add_minimal_executable(difficulty-tests
|
||||
${difficulty_sources}
|
||||
${difficulty_headers})
|
||||
target_link_libraries(difficulty-tests
|
||||
|
@ -35,7 +35,7 @@ set(functional_tests_headers
|
||||
transactions_flow_test.h
|
||||
transactions_generation_from_blockchain.h)
|
||||
|
||||
add_executable(functional_tests
|
||||
monero_add_minimal_executable(functional_tests
|
||||
${functional_tests_sources}
|
||||
${functional_tests_headers})
|
||||
target_link_libraries(functional_tests
|
||||
@ -53,7 +53,7 @@ target_link_libraries(functional_tests
|
||||
set(make_test_signature_sources
|
||||
make_test_signature.cc)
|
||||
|
||||
add_executable(make_test_signature
|
||||
monero_add_minimal_executable(make_test_signature
|
||||
${make_test_signature_sources})
|
||||
|
||||
target_link_libraries(make_test_signature
|
||||
|
@ -26,7 +26,7 @@
|
||||
# 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.
|
||||
|
||||
add_executable(block_fuzz_tests block.cpp fuzzer.cpp)
|
||||
monero_add_minimal_executable(block_fuzz_tests block.cpp fuzzer.cpp)
|
||||
target_link_libraries(block_fuzz_tests
|
||||
PRIVATE
|
||||
cryptonote_core
|
||||
@ -40,7 +40,7 @@ set_property(TARGET block_fuzz_tests
|
||||
PROPERTY
|
||||
FOLDER "tests")
|
||||
|
||||
add_executable(transaction_fuzz_tests transaction.cpp fuzzer.cpp)
|
||||
monero_add_minimal_executable(transaction_fuzz_tests transaction.cpp fuzzer.cpp)
|
||||
target_link_libraries(transaction_fuzz_tests
|
||||
PRIVATE
|
||||
cryptonote_core
|
||||
@ -54,7 +54,7 @@ set_property(TARGET transaction_fuzz_tests
|
||||
PROPERTY
|
||||
FOLDER "tests")
|
||||
|
||||
add_executable(signature_fuzz_tests signature.cpp fuzzer.cpp)
|
||||
monero_add_minimal_executable(signature_fuzz_tests signature.cpp fuzzer.cpp)
|
||||
target_link_libraries(signature_fuzz_tests
|
||||
PRIVATE
|
||||
wallet
|
||||
@ -69,7 +69,7 @@ set_property(TARGET signature_fuzz_tests
|
||||
PROPERTY
|
||||
FOLDER "tests")
|
||||
|
||||
add_executable(cold-outputs_fuzz_tests cold-outputs.cpp fuzzer.cpp)
|
||||
monero_add_minimal_executable(cold-outputs_fuzz_tests cold-outputs.cpp fuzzer.cpp)
|
||||
target_link_libraries(cold-outputs_fuzz_tests
|
||||
PRIVATE
|
||||
wallet
|
||||
@ -84,7 +84,7 @@ set_property(TARGET cold-outputs_fuzz_tests
|
||||
PROPERTY
|
||||
FOLDER "tests")
|
||||
|
||||
add_executable(cold-transaction_fuzz_tests cold-transaction.cpp fuzzer.cpp)
|
||||
monero_add_minimal_executable(cold-transaction_fuzz_tests cold-transaction.cpp fuzzer.cpp)
|
||||
target_link_libraries(cold-transaction_fuzz_tests
|
||||
PRIVATE
|
||||
wallet
|
||||
@ -99,7 +99,7 @@ set_property(TARGET cold-transaction_fuzz_tests
|
||||
PROPERTY
|
||||
FOLDER "tests")
|
||||
|
||||
add_executable(load-from-binary_fuzz_tests load_from_binary.cpp fuzzer.cpp)
|
||||
monero_add_minimal_executable(load-from-binary_fuzz_tests load_from_binary.cpp fuzzer.cpp)
|
||||
target_link_libraries(load-from-binary_fuzz_tests
|
||||
PRIVATE
|
||||
common
|
||||
@ -112,7 +112,7 @@ set_property(TARGET load-from-binary_fuzz_tests
|
||||
PROPERTY
|
||||
FOLDER "tests")
|
||||
|
||||
add_executable(load-from-json_fuzz_tests load_from_json.cpp fuzzer.cpp)
|
||||
monero_add_minimal_executable(load-from-json_fuzz_tests load_from_json.cpp fuzzer.cpp)
|
||||
target_link_libraries(load-from-json_fuzz_tests
|
||||
PRIVATE
|
||||
common
|
||||
@ -125,7 +125,7 @@ set_property(TARGET load-from-json_fuzz_tests
|
||||
PROPERTY
|
||||
FOLDER "tests")
|
||||
|
||||
add_executable(base58_fuzz_tests base58.cpp fuzzer.cpp)
|
||||
monero_add_minimal_executable(base58_fuzz_tests base58.cpp fuzzer.cpp)
|
||||
target_link_libraries(base58_fuzz_tests
|
||||
PRIVATE
|
||||
common
|
||||
@ -138,7 +138,7 @@ set_property(TARGET base58_fuzz_tests
|
||||
PROPERTY
|
||||
FOLDER "tests")
|
||||
|
||||
add_executable(parse-url_fuzz_tests parse_url.cpp fuzzer.cpp)
|
||||
monero_add_minimal_executable(parse-url_fuzz_tests parse_url.cpp fuzzer.cpp)
|
||||
target_link_libraries(parse-url_fuzz_tests
|
||||
PRIVATE
|
||||
epee
|
||||
@ -152,7 +152,7 @@ set_property(TARGET parse-url_fuzz_tests
|
||||
PROPERTY
|
||||
FOLDER "tests")
|
||||
|
||||
add_executable(http-client_fuzz_tests http-client.cpp fuzzer.cpp)
|
||||
monero_add_minimal_executable(http-client_fuzz_tests http-client.cpp fuzzer.cpp)
|
||||
target_link_libraries(http-client_fuzz_tests
|
||||
PRIVATE
|
||||
epee
|
||||
@ -168,7 +168,7 @@ set_property(TARGET http-client_fuzz_tests
|
||||
PROPERTY
|
||||
FOLDER "tests")
|
||||
|
||||
add_executable(levin_fuzz_tests levin.cpp fuzzer.cpp)
|
||||
monero_add_minimal_executable(levin_fuzz_tests levin.cpp fuzzer.cpp)
|
||||
target_link_libraries(levin_fuzz_tests
|
||||
PRIVATE
|
||||
common
|
||||
@ -184,7 +184,7 @@ set_property(TARGET levin_fuzz_tests
|
||||
PROPERTY
|
||||
FOLDER "tests")
|
||||
|
||||
add_executable(bulletproof_fuzz_tests bulletproof.cpp fuzzer.cpp)
|
||||
monero_add_minimal_executable(bulletproof_fuzz_tests bulletproof.cpp fuzzer.cpp)
|
||||
target_link_libraries(bulletproof_fuzz_tests
|
||||
PRIVATE
|
||||
common
|
||||
@ -200,7 +200,7 @@ set_property(TARGET bulletproof_fuzz_tests
|
||||
PROPERTY
|
||||
FOLDER "tests")
|
||||
|
||||
add_executable(tx-extra_fuzz_tests tx-extra.cpp fuzzer.cpp)
|
||||
monero_add_minimal_executable(tx-extra_fuzz_tests tx-extra.cpp fuzzer.cpp)
|
||||
target_link_libraries(tx-extra_fuzz_tests
|
||||
PRIVATE
|
||||
cryptonote_basic
|
||||
|
@ -26,6 +26,7 @@
|
||||
// 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 <boost/utility/string_ref.hpp>
|
||||
#include "include_base_utils.h"
|
||||
#include "file_io_utils.h"
|
||||
#include "net/http_client.h"
|
||||
@ -38,7 +39,7 @@ public:
|
||||
bool connect(const std::string& addr, int port, std::chrono::milliseconds timeout, bool ssl = false, const std::string& bind_ip = "0.0.0.0") { return true; }
|
||||
bool connect(const std::string& addr, const std::string& port, std::chrono::milliseconds timeout, bool ssl = false, const std::string& bind_ip = "0.0.0.0") { return true; }
|
||||
bool disconnect() { return true; }
|
||||
bool send(const std::string& buff, std::chrono::milliseconds timeout) { return true; }
|
||||
bool send(const boost::string_ref buff, std::chrono::milliseconds timeout) { return true; }
|
||||
bool send(const void* data, size_t sz) { return true; }
|
||||
bool is_connected() { return true; }
|
||||
bool recv(std::string& buff, std::chrono::milliseconds timeout)
|
||||
|
@ -65,13 +65,13 @@ namespace
|
||||
{
|
||||
}
|
||||
|
||||
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, test_levin_connection_context& context)
|
||||
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, epee::byte_slice& buff_out, test_levin_connection_context& context)
|
||||
{
|
||||
m_invoke_counter.inc();
|
||||
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||
m_last_command = command;
|
||||
m_last_in_buf = std::string((const char*)in_buff.data(), in_buff.size());
|
||||
buff_out = m_invoke_out_buf;
|
||||
buff_out = m_invoke_out_buf.clone();
|
||||
return m_return_code;
|
||||
}
|
||||
|
||||
@ -111,8 +111,7 @@ namespace
|
||||
int return_code() const { return m_return_code; }
|
||||
void return_code(int v) { m_return_code = v; }
|
||||
|
||||
const std::string& invoke_out_buf() const { return m_invoke_out_buf; }
|
||||
void invoke_out_buf(const std::string& v) { m_invoke_out_buf = v; }
|
||||
void invoke_out_buf(std::string v) { m_invoke_out_buf = epee::byte_slice{std::move(v)}; }
|
||||
|
||||
int last_command() const { return m_last_command; }
|
||||
const std::string& last_in_buf() const { return m_last_in_buf; }
|
||||
@ -127,7 +126,7 @@ namespace
|
||||
boost::mutex m_mutex;
|
||||
|
||||
int m_return_code;
|
||||
std::string m_invoke_out_buf;
|
||||
epee::byte_slice m_invoke_out_buf;
|
||||
|
||||
int m_last_command;
|
||||
std::string m_last_in_buf;
|
||||
|
@ -31,7 +31,7 @@ set(hash_sources
|
||||
|
||||
set(hash_headers)
|
||||
|
||||
add_executable(hash-tests
|
||||
monero_add_minimal_executable(hash-tests
|
||||
${hash_sources}
|
||||
${hash_headers})
|
||||
target_link_libraries(hash-tests
|
||||
|
@ -33,7 +33,7 @@ set(libwallet_api_tests_sources
|
||||
set(libwallet_api_tests_headers
|
||||
)
|
||||
|
||||
add_executable(libwallet_api_tests
|
||||
monero_add_minimal_executable(libwallet_api_tests
|
||||
${libwallet_api_tests_sources}
|
||||
${libwallet_api_tests_headers})
|
||||
|
||||
|
@ -32,7 +32,7 @@ set(clt_sources
|
||||
set(clt_headers
|
||||
net_load_tests.h)
|
||||
|
||||
add_executable(net_load_tests_clt
|
||||
monero_add_minimal_executable(net_load_tests_clt
|
||||
${clt_sources}
|
||||
${clt_headers})
|
||||
target_link_libraries(net_load_tests_clt
|
||||
@ -54,7 +54,7 @@ set(srv_sources
|
||||
set(srv_headers
|
||||
net_load_tests.h)
|
||||
|
||||
add_executable(net_load_tests_srv
|
||||
monero_add_minimal_executable(net_load_tests_srv
|
||||
${srv_sources}
|
||||
${srv_headers})
|
||||
target_link_libraries(net_load_tests_srv
|
||||
|
@ -64,7 +64,7 @@ namespace net_load_tests
|
||||
{
|
||||
}
|
||||
|
||||
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, test_connection_context& context)
|
||||
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, epee::byte_slice& buff_out, test_connection_context& context)
|
||||
{
|
||||
//m_invoke_counter.inc();
|
||||
//std::unique_lock<std::mutex> lock(m_mutex);
|
||||
|
@ -55,7 +55,7 @@ set(performance_tests_headers
|
||||
performance_utils.h
|
||||
single_tx_test_base.h)
|
||||
|
||||
add_executable(performance_tests
|
||||
monero_add_minimal_executable(performance_tests
|
||||
${performance_tests_sources}
|
||||
${performance_tests_headers})
|
||||
target_link_libraries(performance_tests
|
||||
|
@ -40,7 +40,7 @@ set(trezor_tests_headers
|
||||
../core_tests/chaingen.h
|
||||
../core_tests/wallet_tools.h)
|
||||
|
||||
add_executable(trezor_tests
|
||||
monero_add_minimal_executable(trezor_tests
|
||||
${trezor_tests_sources}
|
||||
${trezor_tests_headers})
|
||||
|
||||
|
@ -101,7 +101,7 @@ set(unit_tests_sources
|
||||
set(unit_tests_headers
|
||||
unit_tests_utils.h)
|
||||
|
||||
add_executable(unit_tests
|
||||
monero_add_minimal_executable(unit_tests
|
||||
${unit_tests_sources}
|
||||
${unit_tests_headers})
|
||||
target_link_libraries(unit_tests
|
||||
@ -144,6 +144,6 @@ add_test(
|
||||
NAME unit_tests
|
||||
COMMAND unit_tests --data-dir "${TEST_DATA_DIR}")
|
||||
|
||||
add_executable(test_notifier test_notifier.cpp)
|
||||
monero_add_minimal_executable(test_notifier test_notifier.cpp)
|
||||
target_link_libraries(test_notifier ${EXTRA_LIBRARIES})
|
||||
set_property(TARGET test_notifier PROPERTY FOLDER "tests")
|
||||
|
@ -52,36 +52,38 @@ TEST(block_queue, empty)
|
||||
|
||||
TEST(block_queue, add_stepwise)
|
||||
{
|
||||
epee::net_utils::network_address na;
|
||||
cryptonote::block_queue bq;
|
||||
bq.add_blocks(0, 200, uuid1());
|
||||
bq.add_blocks(0, 200, uuid1(), na);
|
||||
ASSERT_EQ(bq.get_max_block_height(), 199);
|
||||
bq.add_blocks(200, 200, uuid1());
|
||||
bq.add_blocks(200, 200, uuid1(), na);
|
||||
ASSERT_EQ(bq.get_max_block_height(), 399);
|
||||
bq.add_blocks(401, 200, uuid1());
|
||||
bq.add_blocks(401, 200, uuid1(), na);
|
||||
ASSERT_EQ(bq.get_max_block_height(), 600);
|
||||
bq.add_blocks(400, 10, uuid1());
|
||||
bq.add_blocks(400, 10, uuid1(), na);
|
||||
ASSERT_EQ(bq.get_max_block_height(), 600);
|
||||
}
|
||||
|
||||
TEST(block_queue, flush_uuid)
|
||||
{
|
||||
cryptonote::block_queue bq;
|
||||
epee::net_utils::network_address na;
|
||||
|
||||
bq.add_blocks(0, 200, uuid1());
|
||||
bq.add_blocks(0, 200, uuid1(), na);
|
||||
ASSERT_EQ(bq.get_max_block_height(), 199);
|
||||
bq.add_blocks(200, 200, uuid2());
|
||||
bq.add_blocks(200, 200, uuid2(), na);
|
||||
ASSERT_EQ(bq.get_max_block_height(), 399);
|
||||
bq.flush_spans(uuid2());
|
||||
ASSERT_EQ(bq.get_max_block_height(), 199);
|
||||
bq.flush_spans(uuid1());
|
||||
ASSERT_EQ(bq.get_max_block_height(), 0);
|
||||
|
||||
bq.add_blocks(0, 200, uuid1());
|
||||
bq.add_blocks(0, 200, uuid1(), na);
|
||||
ASSERT_EQ(bq.get_max_block_height(), 199);
|
||||
bq.add_blocks(200, 200, uuid2());
|
||||
bq.add_blocks(200, 200, uuid2(), na);
|
||||
ASSERT_EQ(bq.get_max_block_height(), 399);
|
||||
bq.flush_spans(uuid1());
|
||||
ASSERT_EQ(bq.get_max_block_height(), 399);
|
||||
bq.add_blocks(0, 200, uuid1());
|
||||
bq.add_blocks(0, 200, uuid1(), na);
|
||||
ASSERT_EQ(bq.get_max_block_height(), 399);
|
||||
}
|
||||
|
@ -138,24 +138,6 @@ namespace
|
||||
ASSERT_FALSE(m_block_not_too_big);
|
||||
}
|
||||
|
||||
#ifdef __x86_64__ // For 64-bit systems only, because block size is limited to size_t.
|
||||
TEST_F(block_reward_and_current_block_weight, fails_on_huge_median_size)
|
||||
{
|
||||
#if !defined(NDEBUG)
|
||||
size_t huge_size = std::numeric_limits<uint32_t>::max() + UINT64_C(2);
|
||||
ASSERT_DEATH(do_test(huge_size, huge_size + 1), "");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_F(block_reward_and_current_block_weight, fails_on_huge_block_weight)
|
||||
{
|
||||
#if !defined(NDEBUG)
|
||||
size_t huge_size = std::numeric_limits<uint32_t>::max() + UINT64_C(2);
|
||||
ASSERT_DEATH(do_test(huge_size - 2, huge_size), "");
|
||||
#endif
|
||||
}
|
||||
#endif // __x86_64__
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
class block_reward_and_last_block_weights : public ::testing::Test
|
||||
{
|
||||
|
@ -56,13 +56,13 @@ namespace
|
||||
{
|
||||
}
|
||||
|
||||
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, test_levin_connection_context& context)
|
||||
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, epee::byte_slice& buff_out, test_levin_connection_context& context)
|
||||
{
|
||||
m_invoke_counter.inc();
|
||||
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||
m_last_command = command;
|
||||
m_last_in_buf = std::string((const char*)in_buff.data(), in_buff.size());
|
||||
buff_out = m_invoke_out_buf;
|
||||
buff_out = m_invoke_out_buf.clone();
|
||||
return m_return_code;
|
||||
}
|
||||
|
||||
@ -102,8 +102,7 @@ namespace
|
||||
int return_code() const { return m_return_code; }
|
||||
void return_code(int v) { m_return_code = v; }
|
||||
|
||||
const std::string& invoke_out_buf() const { return m_invoke_out_buf; }
|
||||
void invoke_out_buf(const std::string& v) { m_invoke_out_buf = v; }
|
||||
void invoke_out_buf(std::string v) { m_invoke_out_buf = epee::byte_slice{std::move(v)}; }
|
||||
|
||||
int last_command() const { return m_last_command; }
|
||||
const std::string& last_in_buf() const { return m_last_in_buf; }
|
||||
@ -118,7 +117,7 @@ namespace
|
||||
boost::mutex m_mutex;
|
||||
|
||||
int m_return_code;
|
||||
std::string m_invoke_out_buf;
|
||||
epee::byte_slice m_invoke_out_buf;
|
||||
|
||||
int m_last_command;
|
||||
std::string m_last_in_buf;
|
||||
|
@ -886,8 +886,6 @@ TEST(ByteStream, Empty)
|
||||
{
|
||||
epee::byte_stream stream;
|
||||
|
||||
EXPECT_EQ(epee::byte_stream::default_increase(), stream.increase_size());
|
||||
|
||||
EXPECT_EQ(nullptr, stream.data());
|
||||
EXPECT_EQ(nullptr, stream.tellp());
|
||||
EXPECT_EQ(0u, stream.available());
|
||||
@ -912,43 +910,55 @@ TEST(ByteStream, Write)
|
||||
{0xde, 0xad, 0xbe, 0xef, 0xef};
|
||||
|
||||
std::vector<std::uint8_t> bytes;
|
||||
epee::byte_stream stream{4};
|
||||
|
||||
EXPECT_EQ(4u, stream.increase_size());
|
||||
epee::byte_stream stream{};
|
||||
|
||||
stream.write({source, 3});
|
||||
bytes.insert(bytes.end(), source, source + 3);
|
||||
EXPECT_EQ(3u, stream.size());
|
||||
EXPECT_EQ(1u, stream.available());
|
||||
EXPECT_EQ(4u, stream.capacity());
|
||||
EXPECT_LE(3u, stream.capacity());
|
||||
EXPECT_EQ(stream.available(), stream.capacity() - stream.size());
|
||||
EXPECT_TRUE(equal(bytes, byte_span{stream.data(), stream.size()}));
|
||||
|
||||
const std::size_t capacity = stream.capacity();
|
||||
|
||||
stream.write({source, 2});
|
||||
bytes.insert(bytes.end(), source, source + 2);
|
||||
EXPECT_EQ(5u, stream.size());
|
||||
EXPECT_EQ(3u, stream.available());
|
||||
EXPECT_EQ(8u, stream.capacity());
|
||||
EXPECT_LE(5u, stream.capacity());
|
||||
EXPECT_EQ(stream.available(), stream.capacity() - stream.size());
|
||||
EXPECT_TRUE(equal(bytes, byte_span{stream.data(), stream.size()}));
|
||||
|
||||
stream.write({source, 5});
|
||||
bytes.insert(bytes.end(), source, source + 5);
|
||||
EXPECT_EQ(10u, stream.size());
|
||||
EXPECT_EQ(2u, stream.available());
|
||||
EXPECT_EQ(12u, stream.capacity());
|
||||
EXPECT_LE(10u, stream.capacity());
|
||||
EXPECT_EQ(stream.available(), stream.capacity() - stream.size());
|
||||
EXPECT_TRUE(equal(bytes, byte_span{stream.data(), stream.size()}));
|
||||
|
||||
stream.write({source, 2});
|
||||
bytes.insert(bytes.end(), source, source + 2);
|
||||
EXPECT_EQ(12u, stream.size());
|
||||
EXPECT_EQ(0u, stream.available());
|
||||
EXPECT_EQ(12u, stream.capacity());
|
||||
EXPECT_LE(12u, stream.capacity());
|
||||
EXPECT_EQ(stream.available(), stream.capacity() - stream.size());
|
||||
EXPECT_TRUE(equal(bytes, byte_span{stream.data(), stream.size()}));
|
||||
|
||||
stream.write({source, 5});
|
||||
bytes.insert(bytes.end(), source, source + 5);
|
||||
EXPECT_EQ(17u, stream.size());
|
||||
EXPECT_EQ(0u, stream.available());
|
||||
EXPECT_EQ(17u, stream.capacity());
|
||||
EXPECT_LE(17u, stream.capacity());
|
||||
EXPECT_EQ(stream.available(), stream.capacity() - stream.size());
|
||||
EXPECT_TRUE(equal(bytes, byte_span{stream.data(), stream.size()}));
|
||||
|
||||
// ensure it can overflow properly
|
||||
while (capacity == stream.capacity())
|
||||
{
|
||||
stream.write({source, 5});
|
||||
bytes.insert(bytes.end(), source, source + 5);
|
||||
}
|
||||
|
||||
EXPECT_EQ(bytes.size(), stream.size());
|
||||
EXPECT_LE(bytes.size(), stream.capacity());
|
||||
EXPECT_EQ(stream.available(), stream.capacity() - stream.size());
|
||||
EXPECT_TRUE(equal(bytes, byte_span{stream.data(), stream.size()}));
|
||||
}
|
||||
|
||||
@ -967,8 +977,8 @@ TEST(ByteStream, Put)
|
||||
}
|
||||
|
||||
EXPECT_EQ(200u, stream.size());
|
||||
EXPECT_EQ(epee::byte_stream::default_increase() - 200, stream.available());
|
||||
EXPECT_EQ(epee::byte_stream::default_increase(), stream.capacity());
|
||||
EXPECT_LE(200u, stream.capacity());
|
||||
EXPECT_EQ(stream.available(), stream.capacity() - stream.size());
|
||||
EXPECT_TRUE(equal(bytes, byte_span{stream.data(), stream.size()}));
|
||||
}
|
||||
|
||||
@ -981,14 +991,12 @@ TEST(ByteStream, Reserve)
|
||||
{0xde, 0xad, 0xbe, 0xef, 0xef};
|
||||
|
||||
std::vector<std::uint8_t> bytes;
|
||||
epee::byte_stream stream{4};
|
||||
|
||||
EXPECT_EQ(4u, stream.increase_size());
|
||||
epee::byte_stream stream{};
|
||||
|
||||
stream.reserve(100);
|
||||
EXPECT_EQ(100u, stream.capacity());
|
||||
EXPECT_LE(100u, stream.capacity());
|
||||
EXPECT_EQ(0u, stream.size());
|
||||
EXPECT_EQ(100u, stream.available());
|
||||
EXPECT_EQ(stream.available(), stream.capacity());
|
||||
|
||||
for (std::size_t i = 0; i < 100 / sizeof(source); ++i)
|
||||
{
|
||||
@ -997,8 +1005,8 @@ TEST(ByteStream, Reserve)
|
||||
}
|
||||
|
||||
EXPECT_EQ(100u, stream.size());
|
||||
EXPECT_EQ(0u, stream.available());
|
||||
EXPECT_EQ(100u, stream.capacity());
|
||||
EXPECT_LE(100u, stream.capacity());
|
||||
EXPECT_EQ(stream.available(), stream.capacity() - stream.size());
|
||||
EXPECT_TRUE(equal(bytes, byte_span{stream.data(), stream.size()}));
|
||||
}
|
||||
|
||||
@ -1033,29 +1041,31 @@ TEST(ByteStream, Move)
|
||||
static constexpr const std::uint8_t source[] =
|
||||
{0xde, 0xad, 0xbe, 0xef, 0xef};
|
||||
|
||||
epee::byte_stream stream{10};
|
||||
epee::byte_stream stream{};
|
||||
stream.write(source);
|
||||
|
||||
const std::size_t capacity = stream.capacity();
|
||||
std::uint8_t const* const data = stream.data();
|
||||
EXPECT_LE(5u, capacity);
|
||||
EXPECT_NE(nullptr, data);
|
||||
|
||||
epee::byte_stream stream2{std::move(stream)};
|
||||
|
||||
EXPECT_EQ(10u, stream.increase_size());
|
||||
EXPECT_EQ(0u, stream.size());
|
||||
EXPECT_EQ(0u, stream.available());
|
||||
EXPECT_EQ(0u, stream.capacity());
|
||||
EXPECT_EQ(nullptr, stream.data());
|
||||
EXPECT_EQ(nullptr, stream.tellp());
|
||||
|
||||
EXPECT_EQ(10u, stream2.increase_size());
|
||||
EXPECT_EQ(5u, stream2.size());
|
||||
EXPECT_EQ(5u, stream2.available());
|
||||
EXPECT_EQ(10u, stream2.capacity());
|
||||
EXPECT_NE(nullptr, stream2.data());
|
||||
EXPECT_NE(nullptr, stream2.tellp());
|
||||
EXPECT_EQ(capacity, stream2.capacity());
|
||||
EXPECT_EQ(capacity - 5, stream2.available());
|
||||
EXPECT_EQ(data, stream2.data());
|
||||
EXPECT_EQ(data + 5u, stream2.tellp());
|
||||
EXPECT_TRUE(equal(source, byte_span{stream2.data(), stream2.size()}));
|
||||
|
||||
stream = epee::byte_stream{};
|
||||
|
||||
EXPECT_EQ(epee::byte_stream::default_increase(), stream.increase_size());
|
||||
EXPECT_EQ(0u, stream.size());
|
||||
EXPECT_EQ(0u, stream.available());
|
||||
EXPECT_EQ(0u, stream.capacity());
|
||||
@ -1064,15 +1074,13 @@ TEST(ByteStream, Move)
|
||||
|
||||
stream = std::move(stream2);
|
||||
|
||||
EXPECT_EQ(10u, stream.increase_size());
|
||||
EXPECT_EQ(5u, stream.size());
|
||||
EXPECT_EQ(5u, stream.available());
|
||||
EXPECT_EQ(10u, stream.capacity());
|
||||
EXPECT_EQ(capacity, stream.capacity());
|
||||
EXPECT_EQ(capacity - 5, stream.available());
|
||||
EXPECT_NE(nullptr, stream.data());
|
||||
EXPECT_NE(nullptr, stream.tellp());
|
||||
EXPECT_TRUE(equal(source, byte_span{stream.data(), stream.size()}));
|
||||
|
||||
EXPECT_EQ(10u, stream2.increase_size());
|
||||
EXPECT_EQ(0u, stream2.size());
|
||||
EXPECT_EQ(0u, stream2.available());
|
||||
EXPECT_EQ(0u, stream2.capacity());
|
||||
@ -1122,9 +1130,7 @@ TEST(ByteStream, Clear)
|
||||
static constexpr const std::uint8_t source[] =
|
||||
{0xde, 0xad, 0xbe, 0xef, 0xef};
|
||||
|
||||
epee::byte_stream stream{4};
|
||||
|
||||
EXPECT_EQ(4u, stream.increase_size());
|
||||
epee::byte_stream stream{};
|
||||
|
||||
EXPECT_EQ(nullptr, stream.data());
|
||||
EXPECT_EQ(nullptr, stream.tellp());
|
||||
@ -1146,16 +1152,17 @@ TEST(ByteStream, Clear)
|
||||
EXPECT_EQ(loc, stream.data());
|
||||
EXPECT_EQ(loc + 3, stream.tellp());
|
||||
EXPECT_EQ(3u, stream.size());
|
||||
EXPECT_EQ(1u, stream.available());
|
||||
EXPECT_EQ(4u, stream.capacity());
|
||||
EXPECT_LE(stream.size(), stream.capacity());
|
||||
EXPECT_EQ(stream.available(), stream.capacity() - stream.size());
|
||||
|
||||
const std::size_t capacity = stream.capacity();
|
||||
stream.clear();
|
||||
|
||||
EXPECT_EQ(loc, stream.data());
|
||||
EXPECT_EQ(loc, stream.tellp());
|
||||
EXPECT_EQ(0u, stream.size());
|
||||
EXPECT_EQ(4u, stream.available());
|
||||
EXPECT_EQ(4u, stream.capacity());
|
||||
EXPECT_EQ(capacity, stream.capacity());
|
||||
EXPECT_EQ(stream.available(), stream.capacity() - stream.size());
|
||||
}
|
||||
|
||||
TEST(ToHex, String)
|
||||
|
@ -120,7 +120,12 @@ namespace
|
||||
{
|
||||
std::map<cryptonote::relay_method, std::vector<cryptonote::blobdata>> relayed_;
|
||||
|
||||
uint64_t get_target_blockchain_height() const override
|
||||
virtual bool is_synchronized() const final
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual uint64_t get_current_blockchain_height() const final
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -233,9 +238,9 @@ namespace
|
||||
return {connection, std::move(request)};
|
||||
}
|
||||
|
||||
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, cryptonote::levin::detail::p2p_context& context) override final
|
||||
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, epee::byte_slice& buff_out, cryptonote::levin::detail::p2p_context& context) override final
|
||||
{
|
||||
buff_out.clear();
|
||||
buff_out = nullptr;
|
||||
invoked_.push_back(
|
||||
{context.m_connection_id, command, std::string{reinterpret_cast<const char*>(in_buff.data()), in_buff.size()}}
|
||||
);
|
||||
@ -329,7 +334,8 @@ namespace
|
||||
epee::byte_slice noise = nullptr;
|
||||
if (noise_size)
|
||||
noise = epee::levin::make_noise_notify(noise_size);
|
||||
return cryptonote::levin::notify{io_service_, connections_, std::move(noise), is_public, pad_txs, events_};
|
||||
epee::net_utils::zone zone = is_public ? epee::net_utils::zone::public_ : epee::net_utils::zone::i2p;
|
||||
return cryptonote::levin::notify{io_service_, connections_, std::move(noise), zone, pad_txs, events_};
|
||||
}
|
||||
|
||||
boost::uuids::random_generator random_generator_;
|
||||
|
@ -245,7 +245,7 @@ namespace
|
||||
|
||||
TEST(tor_address, epee_serializev_v2)
|
||||
{
|
||||
std::string buffer{};
|
||||
epee::byte_slice buffer{};
|
||||
{
|
||||
test_command_tor command{MONERO_UNWRAP(net::tor_address::make(v2_onion, 10))};
|
||||
EXPECT_FALSE(command.tor.is_unknown());
|
||||
@ -266,7 +266,7 @@ TEST(tor_address, epee_serializev_v2)
|
||||
EXPECT_EQ(0u, command.tor.port());
|
||||
|
||||
epee::serialization::portable_storage stg{};
|
||||
EXPECT_TRUE(stg.load_from_binary(buffer));
|
||||
EXPECT_TRUE(stg.load_from_binary(epee::to_span(buffer)));
|
||||
EXPECT_TRUE(command.load(stg));
|
||||
}
|
||||
EXPECT_FALSE(command.tor.is_unknown());
|
||||
@ -277,7 +277,7 @@ TEST(tor_address, epee_serializev_v2)
|
||||
// make sure that exceeding max buffer doesn't destroy tor_address::_load
|
||||
{
|
||||
epee::serialization::portable_storage stg{};
|
||||
stg.load_from_binary(buffer);
|
||||
stg.load_from_binary(epee::to_span(buffer));
|
||||
|
||||
std::string host{};
|
||||
ASSERT_TRUE(stg.get_value("host", host, stg.open_section("tor", nullptr, false)));
|
||||
@ -296,7 +296,7 @@ TEST(tor_address, epee_serializev_v2)
|
||||
|
||||
TEST(tor_address, epee_serializev_v3)
|
||||
{
|
||||
std::string buffer{};
|
||||
epee::byte_slice buffer{};
|
||||
{
|
||||
test_command_tor command{MONERO_UNWRAP(net::tor_address::make(v3_onion, 10))};
|
||||
EXPECT_FALSE(command.tor.is_unknown());
|
||||
@ -317,7 +317,7 @@ TEST(tor_address, epee_serializev_v3)
|
||||
EXPECT_EQ(0u, command.tor.port());
|
||||
|
||||
epee::serialization::portable_storage stg{};
|
||||
EXPECT_TRUE(stg.load_from_binary(buffer));
|
||||
EXPECT_TRUE(stg.load_from_binary(epee::to_span(buffer)));
|
||||
EXPECT_TRUE(command.load(stg));
|
||||
}
|
||||
EXPECT_FALSE(command.tor.is_unknown());
|
||||
@ -328,7 +328,7 @@ TEST(tor_address, epee_serializev_v3)
|
||||
// make sure that exceeding max buffer doesn't destroy tor_address::_load
|
||||
{
|
||||
epee::serialization::portable_storage stg{};
|
||||
stg.load_from_binary(buffer);
|
||||
stg.load_from_binary(epee::to_span(buffer));
|
||||
|
||||
std::string host{};
|
||||
ASSERT_TRUE(stg.get_value("host", host, stg.open_section("tor", nullptr, false)));
|
||||
@ -347,7 +347,7 @@ TEST(tor_address, epee_serializev_v3)
|
||||
|
||||
TEST(tor_address, epee_serialize_unknown)
|
||||
{
|
||||
std::string buffer{};
|
||||
epee::byte_slice buffer{};
|
||||
{
|
||||
test_command_tor command{net::tor_address::unknown()};
|
||||
EXPECT_TRUE(command.tor.is_unknown());
|
||||
@ -368,7 +368,7 @@ TEST(tor_address, epee_serialize_unknown)
|
||||
EXPECT_EQ(0u, command.tor.port());
|
||||
|
||||
epee::serialization::portable_storage stg{};
|
||||
EXPECT_TRUE(stg.load_from_binary(buffer));
|
||||
EXPECT_TRUE(stg.load_from_binary(epee::to_span(buffer)));
|
||||
EXPECT_TRUE(command.load(stg));
|
||||
}
|
||||
EXPECT_TRUE(command.tor.is_unknown());
|
||||
@ -379,7 +379,7 @@ TEST(tor_address, epee_serialize_unknown)
|
||||
// make sure that exceeding max buffer doesn't destroy tor_address::_load
|
||||
{
|
||||
epee::serialization::portable_storage stg{};
|
||||
stg.load_from_binary(buffer);
|
||||
stg.load_from_binary(epee::to_span(buffer));
|
||||
|
||||
std::string host{};
|
||||
ASSERT_TRUE(stg.get_value("host", host, stg.open_section("tor", nullptr, false)));
|
||||
@ -700,7 +700,7 @@ namespace
|
||||
|
||||
TEST(i2p_address, epee_serializev_b32)
|
||||
{
|
||||
std::string buffer{};
|
||||
epee::byte_slice buffer{};
|
||||
{
|
||||
test_command_i2p command{MONERO_UNWRAP(net::i2p_address::make(b32_i2p, 10))};
|
||||
EXPECT_FALSE(command.i2p.is_unknown());
|
||||
@ -721,7 +721,7 @@ TEST(i2p_address, epee_serializev_b32)
|
||||
EXPECT_EQ(0u, command.i2p.port());
|
||||
|
||||
epee::serialization::portable_storage stg{};
|
||||
EXPECT_TRUE(stg.load_from_binary(buffer));
|
||||
EXPECT_TRUE(stg.load_from_binary(epee::to_span(buffer)));
|
||||
EXPECT_TRUE(command.load(stg));
|
||||
}
|
||||
EXPECT_FALSE(command.i2p.is_unknown());
|
||||
@ -732,7 +732,7 @@ TEST(i2p_address, epee_serializev_b32)
|
||||
// make sure that exceeding max buffer doesn't destroy i2p_address::_load
|
||||
{
|
||||
epee::serialization::portable_storage stg{};
|
||||
stg.load_from_binary(buffer);
|
||||
stg.load_from_binary(epee::to_span(buffer));
|
||||
|
||||
std::string host{};
|
||||
ASSERT_TRUE(stg.get_value("host", host, stg.open_section("i2p", nullptr, false)));
|
||||
@ -751,7 +751,7 @@ TEST(i2p_address, epee_serializev_b32)
|
||||
|
||||
TEST(i2p_address, epee_serialize_unknown)
|
||||
{
|
||||
std::string buffer{};
|
||||
epee::byte_slice buffer{};
|
||||
{
|
||||
test_command_i2p command{net::i2p_address::unknown()};
|
||||
EXPECT_TRUE(command.i2p.is_unknown());
|
||||
@ -772,7 +772,7 @@ TEST(i2p_address, epee_serialize_unknown)
|
||||
EXPECT_EQ(0u, command.i2p.port());
|
||||
|
||||
epee::serialization::portable_storage stg{};
|
||||
EXPECT_TRUE(stg.load_from_binary(buffer));
|
||||
EXPECT_TRUE(stg.load_from_binary(epee::to_span(buffer)));
|
||||
EXPECT_TRUE(command.load(stg));
|
||||
}
|
||||
EXPECT_TRUE(command.i2p.is_unknown());
|
||||
@ -783,7 +783,7 @@ TEST(i2p_address, epee_serialize_unknown)
|
||||
// make sure that exceeding max buffer doesn't destroy i2p_address::_load
|
||||
{
|
||||
epee::serialization::portable_storage stg{};
|
||||
stg.load_from_binary(buffer);
|
||||
stg.load_from_binary(epee::to_span(buffer));
|
||||
|
||||
std::string host{};
|
||||
ASSERT_TRUE(stg.get_value("host", host, stg.open_section("i2p", nullptr, false)));
|
||||
|
@ -47,9 +47,10 @@ namespace cryptonote {
|
||||
class test_core : public cryptonote::i_core_events
|
||||
{
|
||||
public:
|
||||
virtual bool is_synchronized() const final { return true; }
|
||||
void on_synchronized(){}
|
||||
void safesyncmode(const bool){}
|
||||
uint64_t get_current_blockchain_height() const {return 1;}
|
||||
virtual uint64_t get_current_blockchain_height() const final {return 1;}
|
||||
void set_target_blockchain_height(uint64_t) {}
|
||||
bool init(const boost::program_options::variables_map& vm) {return true ;}
|
||||
bool deinit(){return true;}
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
TEST(protocol_pack, protocol_pack_command)
|
||||
{
|
||||
std::string buff;
|
||||
epee::byte_slice buff;
|
||||
cryptonote::NOTIFY_RESPONSE_CHAIN_ENTRY::request r;
|
||||
r.start_height = 1;
|
||||
r.total_height = 3;
|
||||
@ -47,7 +47,7 @@ TEST(protocol_pack, protocol_pack_command)
|
||||
ASSERT_TRUE(res);
|
||||
|
||||
cryptonote::NOTIFY_RESPONSE_CHAIN_ENTRY::request r2;
|
||||
res = epee::serialization::load_t_from_binary(r2, buff);
|
||||
res = epee::serialization::load_t_from_binary(r2, epee::to_span(buff));
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_TRUE(r.m_block_ids.size() == i);
|
||||
ASSERT_TRUE(r.start_height == 1);
|
||||
|
34
utils/health/README.md
Normal file
34
utils/health/README.md
Normal file
@ -0,0 +1,34 @@
|
||||
#Intro
|
||||
This directory contains tools, which can be used for checking the health of the project, like build/run time analyzers, lints, etc.
|
||||
|
||||
#Usage
|
||||
Unless it's stated differently, these scripts should be called from a given source directory, where you want the checks to be performed, for instance:
|
||||
|
||||
`og@ghetto:~/dev/monero$ utils/health/clang-build-time-analyzer-run.sh`
|
||||
|
||||
##ClangBuildAnalyzer
|
||||
`utils/health/clang-build-time-analyzer-run.sh`
|
||||
The CBA helps in finding culprints of slow compilation.
|
||||
On the first run, the script will complain about the missing ClangBuildAnalyzer binary and will point you to another script, which is able to clone and build the required binary.
|
||||
|
||||
##clang-tidy
|
||||
`utils/health/clang-tidy-run.sh`
|
||||
Performs Lint checks on the source code and stores the result in the build directory. More information on the [home page](https://clang.llvm.org/extra/clang-tidy/).
|
||||
|
||||
|
||||
##Valgrind checks
|
||||
`utils/health/valgrind-tests.sh`
|
||||
This script is able to run valgrind's callgrind, cachegrind and memcheck for a given set of executables.
|
||||
It expects ONE PARAMETER, which points to a file with paths to executables and their arguments, written line by line. For example:
|
||||
|
||||
```
|
||||
ls -l -h
|
||||
build/tests/unit_tests/unit_tests
|
||||
```
|
||||
|
||||
The `*.out` results can be interpreted with the `kcachegrind` tool.
|
||||
The memcheck output is just a readable text file with a summary at the end.
|
||||
|
||||
#Footer
|
||||
Responsible: mj-xmr
|
||||
|
54
utils/health/build-scripts/clang-build-time-analyzer-clone-build.sh
Executable file
54
utils/health/build-scripts/clang-build-time-analyzer-clone-build.sh
Executable file
@ -0,0 +1,54 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# Copyright (c) 2014-2020, 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.
|
||||
|
||||
# This script checkouts and builds ClangBuildAnalyzer.
|
||||
# The result is put into bin directory
|
||||
|
||||
DIR_THIS="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
TAG="v1.2.0"
|
||||
PROG="ClangBuildAnalyzer"
|
||||
DIR_OUT="$DIR_THIS/../bin"
|
||||
DIR_BUILD="build"
|
||||
|
||||
mkdir -p "$DIR_BUILD" && cd "$DIR_BUILD"
|
||||
if [ ! -d "$PROG" ]; then
|
||||
git clone https://github.com/aras-p/$PROG.git
|
||||
fi
|
||||
cd "$PROG"
|
||||
git checkout "$TAG"
|
||||
mkdir -p build && cd build
|
||||
cmake ..
|
||||
make -j`nproc`
|
||||
|
||||
mkdir -p "$DIR_OUT"
|
||||
cp -v "$PROG" "$DIR_OUT"
|
||||
make clean # Clean the used space
|
||||
|
75
utils/health/clang-build-time-analyzer-run.sh
Executable file
75
utils/health/clang-build-time-analyzer-run.sh
Executable file
@ -0,0 +1,75 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# Copyright (c) 2014-2020, 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.
|
||||
|
||||
# ClangBuildAnalyzer is able to analyze the aggregate build time of particular headers.
|
||||
|
||||
DIR_THIS="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
# Build variables
|
||||
PROG="ClangBuildAnalyzer"
|
||||
PROG_PATH="$DIR_THIS/bin/$PROG"
|
||||
DIR_BUILD="build/clang-build-analyser"
|
||||
|
||||
# ClangBuildAnalyzer variables
|
||||
DIR_MONITORED="."
|
||||
RESULT="cba-result.txt"
|
||||
TRACE="cba-trace.txt"
|
||||
|
||||
if [ -f "$PROG_PATH" ]; then
|
||||
echo "Found: $PROG_PATH"
|
||||
else
|
||||
echo "Couldn't find: $PROG_PATH"
|
||||
echo "Please run the below script to clone and build $PROG:"
|
||||
echo "$DIR_THIS/build-scripts/clang-build-time-analyzer-clone-build.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$DIR_BUILD" && cd "$DIR_BUILD"
|
||||
|
||||
cmake ../.. \
|
||||
-DCMAKE_C_COMPILER=clang \
|
||||
-DCMAKE_CXX_COMPILER=clang++ \
|
||||
-DUSE_CCACHE=OFF \
|
||||
-DUSE_COMPILATION_TIME_PROFILER=ON \
|
||||
-DBUILD_SHARED_LIBS=ON \
|
||||
-DBUILD_TESTS=ON
|
||||
|
||||
make clean # Clean up, so that the trace can be regenerated from scratch
|
||||
$PROG_PATH --start $DIR_MONITORED # Start monitoring
|
||||
time make # Build
|
||||
#time make easylogging # Quick testing: build a single target
|
||||
$PROG_PATH --stop $DIR_MONITORED $TRACE # Stop and output to trace file
|
||||
$PROG_PATH --analyze $TRACE | tee $RESULT # Analyze the trace, and store it in a readable format
|
||||
gzip -f $TRACE # Zip the trace, because it's huge. -f overwrites the previously generated trace
|
||||
|
||||
echo ""
|
||||
echo "Readable result stored in: $DIR_BUILD/$RESULT"
|
||||
echo "The trace (analyser's input data) in: $DIR_BUILD/$TRACE.gz"
|
||||
|
65
utils/health/clang-tidy-run.sh
Executable file
65
utils/health/clang-tidy-run.sh
Executable file
@ -0,0 +1,65 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# Copyright (c) 2014-2020, 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.
|
||||
|
||||
# clang-tidy runs lint checks on C & C++ sources and headers.
|
||||
# Run this script from the source directory.
|
||||
|
||||
DIR_BUILD_BASE="build/clang-tidy"
|
||||
RESULT_BASE="clang-tidy-result"
|
||||
|
||||
function tidy_for_language() {
|
||||
LANG="${1}"
|
||||
DIR_BUILD="${DIR_BUILD_BASE}-${LANG}"
|
||||
RESULT="${RESULT_BASE}-${LANG}.txt"
|
||||
|
||||
mkdir -p "$DIR_BUILD" && pushd "$DIR_BUILD"
|
||||
|
||||
cmake ../.. \
|
||||
-DCMAKE_C_COMPILER=clang \
|
||||
-DCMAKE_CXX_COMPILER=clang++ \
|
||||
-DUSE_CCACHE=ON \
|
||||
-DUSE_CLANG_TIDY_${LANG}=ON \
|
||||
-DBUILD_SHARED_LIBS=ON \
|
||||
-DBUILD_TESTS=ON
|
||||
|
||||
make clean # Clean up, so that the result can be regenerated from scratch
|
||||
time make -k 2>&1 | tee "$RESULT" # Build and store the result. -k means: ignore errors
|
||||
#time make -k easylogging 2>&1 | tee "$RESULT" # Quick testing: build a single target
|
||||
gzip -f "$RESULT" # Zip the result, because it's huge. -f overwrites the previously generated result
|
||||
|
||||
echo ""
|
||||
echo "Readable result stored in: $DIR_BUILD/$RESULT.gz"
|
||||
|
||||
popd
|
||||
}
|
||||
|
||||
tidy_for_language "C"
|
||||
tidy_for_language "CXX"
|
||||
|
Loading…
Reference in New Issue
Block a user