Merge pull request #153 from wowario/upstream

Upstream
release-v0.5.0
jw 5 years ago committed by GitHub
commit d85d908ddc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -23,9 +23,9 @@ env:
- DOCKER_PACKAGES="build-essential libtool cmake autotools-dev automake pkg-config bsdmainutils curl git ca-certificates ccache"
matrix:
# ARM v7
- HOST=arm-linux-gnueabihf PACKAGES="gperf g++-arm-linux-gnueabihf"
- HOST=arm-linux-gnueabihf PACKAGES="python3 gperf g++-arm-linux-gnueabihf"
# ARM v8
- HOST=aarch64-linux-gnu PACKAGES="gperf g++-aarch64-linux-gnu"
- HOST=aarch64-linux-gnu PACKAGES="python3 gperf g++-aarch64-linux-gnu"
# i686 Win
- HOST=i686-w64-mingw32 PACKAGES="python3 nsis g++-mingw-w64-i686"
# i686 Linux
@ -33,7 +33,7 @@ env:
# Win64
- HOST=x86_64-w64-mingw32 PACKAGES="cmake python3 nsis g++-mingw-w64-x86-64 wine-binfmt wine64 bc" RUN_TESTS=true
# x86_64 Linux
- HOST=x86_64-unknown-linux-gnu PACKAGES="gperf cmake python3-zmq protobuf-compiler libdbus-1-dev libharfbuzz-dev libprotobuf-dev" RUN_TESTS=true
- HOST=x86_64-unknown-linux-gnu PACKAGES="gperf cmake python3-zmq libdbus-1-dev libharfbuzz-dev" RUN_TESTS=true
# Cross-Mac
- HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev python3-setuptools-git" OSX_SDK=10.11
@ -52,6 +52,7 @@ before_script:
- if [ -n "$OSX_SDK" -a ! -f contrib/depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then curl --location --fail $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -o contrib/depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
- if [ -n "$OSX_SDK" -a -f contrib/depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then tar -C contrib/depends/SDKs -xf contrib/depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
- if [[ $HOST = *-mingw32 ]]; then $DOCKER_EXEC bash -c "update-alternatives --set $HOST-g++ \$(which $HOST-g++-posix)"; fi
- if [[ $HOST = *-mingw32 ]]; then $DOCKER_EXEC bash -c "update-alternatives --set $HOST-gcc \$(which $HOST-gcc-posix)"; fi
- if [ -z "$NO_DEPENDS" ]; then $DOCKER_EXEC bash -c "CONFIG_SHELL= make $MAKEJOBS -C contrib/depends HOST=$HOST $DEP_OPTS"; fi
script:
- git submodule init && git submodule update

@ -601,9 +601,6 @@ else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARCH_FLAG}")
set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wundef -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-unused-variable -Wno-error=unused-variable -Wno-error=undef -Wno-error=uninitialized")
if(NOT MINGW)
set(WARNINGS_AS_ERRORS_FLAG "-Werror")
endif()
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
if(ARM)
set(WARNINGS "${WARNINGS} -Wno-error=inline-asm")
@ -698,6 +695,13 @@ else()
set(LD_SECURITY_FLAGS "${LD_SECURITY_FLAGS} -Wl,-z,noexecheap")
endif()
if(BACKCOMPAT)
add_definitions(-DFDELT_TYPE=long\ int)
add_linker_flag_if_supported(-Wl,--wrap=__divmoddi4 LD_BACKCOMPAT_FLAGS)
add_linker_flag_if_supported(-Wl,--wrap=glob LD_BACKCOMPAT_FLAGS)
message(STATUS "Using Lib C back compat flags: ${LD_BACKCOMPAT_FLAGS}")
endif()
# some windows linker bits
if (WIN32)
add_linker_flag_if_supported(-Wl,--dynamicbase LD_SECURITY_FLAGS)
@ -710,7 +714,7 @@ else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${COVERAGE_FLAGS} ${PIC_FLAG} ${C_SECURITY_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_CPP_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${COVERAGE_FLAGS} ${PIC_FLAG} ${CXX_SECURITY_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS} ${LD_BACKCOMPAT_FLAGS}")
# With GCC 6.1.1 the compiled binary malfunctions due to aliasing. Until that
# is fixed in the code (Issue #847), force compiler to be conservative.

@ -19,7 +19,8 @@ posted to #monero-dev on irc.freenode.net).
Patches should be self contained. A good rule of thumb is to have
one patch per separate issue, feature, or logical change. Also, no
other changes, such as random whitespace changes or reindentation.
other changes, such as random whitespace changes, reindentation,
or fixing typoes, spelling, or wording, unless user visible.
Following the code style of the particular chunk of code you're
modifying is encouraged. Proper squashing should be done (eg, if
you're making a buggy patch, then a later patch to fix the bug,

@ -20,7 +20,8 @@ RUN set -ex && \
automake \
bzip2 \
xsltproc \
gperf
gperf \
unzip
WORKDIR /usr/local
@ -147,6 +148,20 @@ RUN set -ex \
&& make \
&& make install
# Protobuf
ARG PROTOBUF_VERSION=v3.6.1
ARG PROTOBUF_HASH=48cb18e5c419ddd23d9badcfe4e9df7bde1979b2
RUN set -ex \
&& git clone https://github.com/protocolbuffers/protobuf -b ${PROTOBUF_VERSION} \
&& cd protobuf \
&& test `git rev-parse HEAD` = ${PROTOBUF_HASH} || exit 1 \
&& git submodule update --init --recursive \
&& ./autogen.sh \
&& CFLAGS="-fPIC" CXXFLAGS="-fPIC" ./configure --enable-static --disable-shared \
&& make \
&& make install \
&& ldconfig
WORKDIR /src
COPY . .

@ -2,13 +2,55 @@ OPTION(USE_DEVICE_TREZOR "Trezor support compilation" OFF)
OPTION(USE_DEVICE_TREZOR_LIBUSB "Trezor LibUSB compilation" OFF)
OPTION(USE_DEVICE_TREZOR_UDP_RELEASE "Trezor UdpTransport in release mode" OFF)
# Helper function to fix cmake < 3.6.0 FindProtobuf variables
function(_trezor_protobuf_fix_vars)
if(${CMAKE_VERSION} VERSION_LESS "3.6.0")
foreach(UPPER
PROTOBUF_SRC_ROOT_FOLDER
PROTOBUF_IMPORT_DIRS
PROTOBUF_DEBUG
PROTOBUF_LIBRARY
PROTOBUF_PROTOC_LIBRARY
PROTOBUF_INCLUDE_DIR
PROTOBUF_PROTOC_EXECUTABLE
PROTOBUF_LIBRARY_DEBUG
PROTOBUF_PROTOC_LIBRARY_DEBUG
PROTOBUF_LITE_LIBRARY
PROTOBUF_LITE_LIBRARY_DEBUG
)
if (DEFINED ${UPPER})
string(REPLACE "PROTOBUF_" "Protobuf_" Camel ${UPPER})
if (NOT DEFINED ${Camel})
set(${Camel} ${${UPPER}} PARENT_SCOPE)
endif()
endif()
endforeach()
endif()
endfunction()
# Use Trezor master switch
if (USE_DEVICE_TREZOR)
# Protobuf is required to build protobuf messages for Trezor
include(FindProtobuf OPTIONAL)
find_package(Protobuf)
if(NOT Protobuf_FOUND)
_trezor_protobuf_fix_vars()
# Protobuf handling the cache variables set in docker.
if(NOT Protobuf_FOUND AND NOT Protobuf_LIBRARY AND NOT Protobuf_PROTOC_EXECUTABLE AND NOT Protobuf_INCLUDE_DIR)
message(STATUS "Could not find Protobuf")
elseif(NOT Protobuf_LIBRARY OR NOT EXISTS "${Protobuf_LIBRARY}")
message(STATUS "Protobuf library not found: ${Protobuf_LIBRARY}")
unset(Protobuf_FOUND)
elseif(NOT Protobuf_PROTOC_EXECUTABLE OR NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
message(STATUS "Protobuf executable not found: ${Protobuf_PROTOC_EXECUTABLE}")
unset(Protobuf_FOUND)
elseif(NOT Protobuf_INCLUDE_DIR OR NOT EXISTS "${Protobuf_INCLUDE_DIR}")
message(STATUS "Protobuf include dir not found: ${Protobuf_INCLUDE_DIR}")
unset(Protobuf_FOUND)
else()
message(STATUS "Protobuf lib: ${Protobuf_LIBRARY}, inc: ${Protobuf_INCLUDE_DIR}, protoc: ${Protobuf_PROTOC_EXECUTABLE}")
set(Protobuf_INCLUDE_DIRS ${Protobuf_INCLUDE_DIR})
set(Protobuf_FOUND 1) # override found if all rquired info was provided by variables
endif()
else()
@ -37,9 +79,32 @@ if(Protobuf_FOUND AND USE_DEVICE_TREZOR)
endif()
endif()
# Try to build protobuf messages
# Protobuf compilation test
if(Protobuf_FOUND AND USE_DEVICE_TREZOR AND TREZOR_PYTHON)
set(ENV{PROTOBUF_INCLUDE_DIRS} "${Protobuf_INCLUDE_DIRS}")
execute_process(COMMAND ${Protobuf_PROTOC_EXECUTABLE} -I "${CMAKE_SOURCE_DIR}/cmake" -I "${Protobuf_INCLUDE_DIR}" "${CMAKE_SOURCE_DIR}/cmake/test-protobuf.proto" --cpp_out ${CMAKE_BINARY_DIR} RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE ERR)
if(RET)
message(STATUS "Protobuf test generation failed: ${OUT} ${ERR}")
endif()
try_compile(Protobuf_COMPILE_TEST_PASSED
"${CMAKE_BINARY_DIR}"
SOURCES
"${CMAKE_BINARY_DIR}/test-protobuf.pb.cc"
"${CMAKE_SOURCE_DIR}/cmake/test-protobuf.cpp"
CMAKE_FLAGS
"-DINCLUDE_DIRECTORIES=${Protobuf_INCLUDE_DIR};${CMAKE_BINARY_DIR}"
"-DCMAKE_CXX_STANDARD=11"
LINK_LIBRARIES ${Protobuf_LIBRARY}
OUTPUT_VARIABLE OUTPUT
)
if(NOT Protobuf_COMPILE_TEST_PASSED)
message(STATUS "Protobuf Compilation test failed: ${OUTPUT}.")
endif()
endif()
# Try to build protobuf messages
if(Protobuf_FOUND AND USE_DEVICE_TREZOR AND TREZOR_PYTHON AND Protobuf_COMPILE_TEST_PASSED)
set(ENV{PROTOBUF_INCLUDE_DIRS} "${Protobuf_INCLUDE_DIR}")
set(ENV{PROTOBUF_PROTOC_EXECUTABLE} "${Protobuf_PROTOC_EXECUTABLE}")
execute_process(COMMAND ${TREZOR_PYTHON} tools/build_protob.py WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../src/device_trezor/trezor RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE ERR)
if(RET)
@ -47,9 +112,10 @@ if(Protobuf_FOUND AND USE_DEVICE_TREZOR AND TREZOR_PYTHON)
"OUT: ${OUT}, ERR: ${ERR}."
"Please read src/device_trezor/trezor/tools/README.md")
else()
message(STATUS "Trezor protobuf messages regenerated ${OUT}")
message(STATUS "Trezor protobuf messages regenerated out: \"${OUT}.\"")
set(DEVICE_TREZOR_READY 1)
add_definitions(-DDEVICE_TREZOR_READY=1)
add_definitions(-DPROTOBUF_INLINE_NOT_IN_HEADERS=0)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DTREZOR_DEBUG=1)
@ -75,5 +141,26 @@ if(Protobuf_FOUND AND USE_DEVICE_TREZOR AND TREZOR_PYTHON)
include_directories(${LibUSB_INCLUDE_DIRS})
endif()
endif()
set(TREZOR_LIBUSB_LIBRARIES "")
if(LibUSB_COMPILE_TEST_PASSED)
list(APPEND TREZOR_LIBUSB_LIBRARIES ${LibUSB_LIBRARIES})
message(STATUS "Trezor compatible LibUSB found at: ${LibUSB_INCLUDE_DIRS}")
endif()
if (BUILD_GUI_DEPS)
set(TREZOR_DEP_LIBS "")
set(TREZOR_DEP_LINKER "")
if (Protobuf_LIBRARY)
list(APPEND TREZOR_DEP_LIBS ${Protobuf_LIBRARY})
string(APPEND TREZOR_DEP_LINKER " -lprotobuf")
endif()
if (TREZOR_LIBUSB_LIBRARIES)
list(APPEND TREZOR_DEP_LIBS ${TREZOR_LIBUSB_LIBRARIES})
string(APPEND TREZOR_DEP_LINKER " -lusb-1.0")
endif()
endif()
endif()
endif()

@ -0,0 +1,43 @@
// Copyright (c) 2014-2018, 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.
#include <string>
#include <iostream>
#include <google/protobuf/message.h>
#include <google/protobuf/unknown_field_set.h>
#include "test-protobuf.pb.h"
int main(int argc, char *argv[]) {
google::protobuf::UnknownFieldSet ufs;
ufs.ClearAndFreeMemory();
Success sc;
sc.set_message("test");
sc.SerializeToOstream(&std::cerr);
return 0;
}

@ -0,0 +1,7 @@
syntax = "proto2";
import "google/protobuf/descriptor.proto";
message Success {
optional string message = 1;
}

@ -26,10 +26,5 @@
# 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.
# warnings are cleared only for GCC on Linux
if (NOT (MINGW OR APPLE OR FREEBSD OR OPENBSD OR DRAGONFLY))
add_compile_options("${WARNINGS_AS_ERRORS_FLAG}") # applies only to targets that follow
endif()
add_subdirectory(epee)

@ -53,6 +53,16 @@ Download it from apple, or search for it on github. Create a new directoty calle
directory and place the entire MacOSX10.11.sdk folder in it. The depends build will then pick it up automatically
(without requiring SDK_PATH).
#Mingw builds
Building for 32/64bit mingw requires switching alternatives to a posix mode
```bash
update-alternatives --set x86_64-w64-mingw32-g++ x86_64-w64-mingw32-g++-posix
update-alternatives --set x86_64-w64-mingw32-gcc x86_64-w64-mingw32-gcc-posix
```
### Other documentation
- [description.md](description.md): General description of the depends system

@ -11,13 +11,21 @@ endef
define $(package)_set_vars
$(package)_config_opts=--disable-shared
$(package)_config_opts_linux=--with-pic --disable-udev
$(package)_config_opts_mingw32=--disable-udev
$(package)_config_opts_darwin=--disable-udev
endef
define $(package)_config_cmds
cp -f $(BASEDIR)/config.guess config.guess &&\
cp -f $(BASEDIR)/config.sub config.sub &&\
$($(package)_autoconf)
endef
ifneq ($(host_os),darwin)
define $(package)_config_cmds
cp -f $(BASEDIR)/config.guess config.guess &&\
cp -f $(BASEDIR)/config.sub config.sub &&\
$($(package)_autoconf)
endef
else
define $(package)_config_cmds
$($(package)_autoconf)
endef
endif
define $(package)_build_cmd
$(MAKE)
@ -27,5 +35,5 @@ define $(package)_stage_cmds
$(MAKE) DESTDIR=$($(package)_staging_dir) install
endef
define $(package)_postprocess_cmds cp -f lib/libusb-1.0.a lib/libusb.a
define $(package)_postprocess_cmds cp -f lib/libusb-1.0.a lib/libusb.a
endef

@ -0,0 +1,28 @@
package=protobuf3
$(package)_version=3.6.1
$(package)_download_path=https://github.com/protocolbuffers/protobuf/releases/download/v$($(package)_version)/
$(package)_file_name=protobuf-cpp-$($(package)_version).tar.gz
$(package)_sha256_hash=b3732e471a9bb7950f090fd0457ebd2536a9ba0891b7f3785919c654fe2a2529
$(package)_cxxflags=-std=c++11
define $(package)_set_vars
$(package)_config_opts=--disable-shared --prefix=$(build_prefix)
$(package)_config_opts_linux=--with-pic
endef
define $(package)_config_cmds
$($(package)_autoconf)
endef
define $(package)_build_cmds
$(MAKE) -C src libprotobuf.la all
endef
define $(package)_stage_cmds
$(MAKE) DESTDIR=$($(package)_staging_dir) -C src install install-libLTLIBRARIES install-nobase_includeHEADERS &&\
$(MAKE) DESTDIR=$($(package)_staging_dir) install-pkgconfigDATA
endef
define $(package)_postprocess_cmds
rm lib/libprotoc.a
endef

@ -1,10 +1,10 @@
packages:=boost openssl libevent zeromq cppzmq zlib expat ldns cppzmq readline libiconv qt hidapi
native_packages := native_ccache
packages:=boost openssl libevent zeromq cppzmq zlib expat ldns cppzmq readline libiconv qt hidapi protobuf libusb
native_packages := native_ccache native_protobuf
darwin_native_packages = native_biplist native_ds_store native_mac_alias
darwin_packages = sodium-darwin
linux_packages = eudev libusb
linux_packages = eudev
ifeq ($(host_os),linux)
packages += unwind

@ -21,6 +21,12 @@ SET(LIBUNWIND_LIBRARY_DIRS @prefix@/lib)
SET(LIBUSB-1.0_LIBRARY @prefix@/lib/libusb-1.0.a)
SET(LIBUDEV_LIBRARY @prefix@/lib/libudev.a)
SET(Protobuf_FOUND 1)
SET(Protobuf_PROTOC_EXECUTABLE @prefix@/native/bin/protoc CACHE FILEPATH "Path to the native protoc")
SET(Protobuf_INCLUDE_DIR @prefix@/include CACHE PATH "Protobuf include dir")
SET(Protobuf_INCLUDE_DIRS @prefix@/include CACHE PATH "Protobuf include dir")
SET(Protobuf_LIBRARY @prefix@/lib/libprotobuf.a CACHE FILEPATH "Protobuf library")
SET(ZMQ_INCLUDE_PATH @prefix@/include)
SET(ZMQ_LIB @prefix@/lib/libzmq.a)

@ -230,35 +230,56 @@ namespace math_helper
}
}
template<int default_interval, bool start_immediate = true>
class once_a_time_seconds
template<uint64_t scale, int default_interval, bool start_immediate = true>
class once_a_time
{
uint64_t get_time() const
{
#ifdef _WIN32
FILETIME fileTime;
GetSystemTimeAsFileTime(&fileTime);
unsigned __int64 present = 0;
present |= fileTime.dwHighDateTime;
present = present << 32;
present |= fileTime.dwLowDateTime;
present /= 10; // mic-sec
#else
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000000 + tv.tv_usec;
#endif
}
public:
once_a_time_seconds():m_interval(default_interval)
once_a_time():m_interval(default_interval * scale)
{
m_last_worked_time = 0;
if(!start_immediate)
time(&m_last_worked_time);
m_last_worked_time = get_time();
}
template<class functor_t>
bool do_call(functor_t functr)
{
time_t current_time = 0;
time(&current_time);
uint64_t current_time = get_time();
if(current_time - m_last_worked_time > m_interval)
{
bool res = functr();
time(&m_last_worked_time);
m_last_worked_time = get_time();
return res;
}
return true;
}
private:
time_t m_last_worked_time;
time_t m_interval;
uint64_t m_last_worked_time;
uint64_t m_interval;
};
template<int default_interval, bool start_immediate = true>
class once_a_time_seconds: public once_a_time<1000000, default_interval, start_immediate> {};
template<int default_interval, bool start_immediate = true>
class once_a_time_milliseconds: public once_a_time<1000, default_interval, start_immediate> {};
}
}

@ -38,14 +38,21 @@
#define MAX_LOG_FILE_SIZE 104850000 // 100 MB - 7600 bytes
#define MAX_LOG_FILES 50
#define MCFATAL(cat,x) CLOG(FATAL,cat) << x
#define MCERROR(cat,x) CLOG(ERROR,cat) << x
#define MCWARNING(cat,x) CLOG(WARNING,cat) << x
#define MCINFO(cat,x) CLOG(INFO,cat) << x
#define MCDEBUG(cat,x) CLOG(DEBUG,cat) << x
#define MCTRACE(cat,x) CLOG(TRACE,cat) << x
#define MCLOG(level,cat,x) ELPP_WRITE_LOG(el::base::Writer, level, el::base::DispatchAction::NormalLog, cat) << x
#define MCLOG_FILE(level,cat,x) ELPP_WRITE_LOG(el::base::Writer, level, el::base::DispatchAction::FileOnlyLog, cat) << x
#define MCLOG_TYPE(level, cat, type, x) do { \
if (ELPP->vRegistry()->allowed(level, cat)) { \
el::base::Writer(level, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \
} \
} while (0)
#define MCLOG(level, cat, x) MCLOG_TYPE(level, cat, el::base::DispatchAction::NormalLog, x)
#define MCLOG_FILE(level, cat, x) MCLOG_TYPE(level, cat, el::base::DispatchAction::FileOnlyLog, x)
#define MCFATAL(cat,x) MCLOG(el::Level::Fatal,cat, x)
#define MCERROR(cat,x) MCLOG(el::Level::Error,cat, x)
#define MCWARNING(cat,x) MCLOG(el::Level::Warning,cat, x)
#define MCINFO(cat,x) MCLOG(el::Level::Info,cat, x)
#define MCDEBUG(cat,x) MCLOG(el::Level::Debug,cat, x)
#define MCTRACE(cat,x) MCLOG(el::Level::Trace,cat, x)
#define MCLOG_COLOR(level,cat,color,x) MCLOG(level,cat,"\033[1;" color "m" << x << "\033[0m")
#define MCLOG_RED(level,cat,x) MCLOG_COLOR(level,cat,"31",x)

@ -431,7 +431,7 @@ namespace levin
}
CRITICAL_REGION_END();
LOG_PRINT_L4("LEVIN_PACKET_RECIEVED. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]");
LOG_PRINT_L4("LEVIN_PACKET_RECEIVED. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]");
if(is_request)
{

@ -416,7 +416,7 @@ public:
bool is_response = (m_oponent_protocol_ver == LEVIN_PROTOCOL_VER_1 && m_current_head.m_flags&LEVIN_PACKET_RESPONSE);
MDEBUG(m_connection_context << "LEVIN_PACKET_RECIEVED. [len=" << m_current_head.m_cb
MDEBUG(m_connection_context << "LEVIN_PACKET_RECEIVED. [len=" << m_current_head.m_cb
<< ", flags" << m_current_head.m_flags
<< ", r?=" << m_current_head.m_have_to_return_data
<<", cmd = " << m_current_head.m_command

@ -91,11 +91,15 @@ namespace misc_utils
*/
inline void match_string2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val)
{
val.clear();
val.reserve(std::distance(star_end_string, buf_end));
bool escape_mode = false;
std::string::const_iterator it = star_end_string;
++it;
std::string::const_iterator fi = it;
while (fi != buf_end && *fi != '\\' && *fi != '\"')
++fi;
val.assign(it, fi);
val.reserve(std::distance(star_end_string, buf_end));
it = fi;
for(;it != buf_end;it++)
{
if(escape_mode/*prev_ch == '\\'*/)

@ -117,16 +117,12 @@ namespace string_tools
return to_hex::string(to_byte_span(to_span(src)));
}
//----------------------------------------------------------------------------
template<class CharT>
bool parse_hexstr_to_binbuff(const std::basic_string<CharT>& s, std::basic_string<CharT>& res)
inline bool parse_hexstr_to_binbuff(const epee::span<const char> s, epee::span<char>& res)
{
res.clear();
if (s.size() & 1)
return false;
try
{
res.resize(s.size() / 2);
unsigned char *dst = (unsigned char *)res.data();
if (s.size() != res.size() * 2)
return false;
unsigned char *dst = (unsigned char *)&res[0];
const unsigned char *src = (const unsigned char *)s.data();
for(size_t i = 0; i < s.size(); i += 2)
{
@ -140,28 +136,15 @@ namespace string_tools
}
return true;
}
catch(...)
{
return false;
}
}
//----------------------------------------------------------------------------
template<class t_pod_type>
bool parse_tpod_from_hex_string(const std::string& str_hash, t_pod_type& t_pod)
inline bool parse_hexstr_to_binbuff(const std::string& s, std::string& res)
{
static_assert(std::is_pod<t_pod_type>::value, "expected pod type");
std::string buf;
bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf);
if (!res || buf.size() != sizeof(t_pod_type))
{
if (s.size() & 1)
return false;
}
else
{
buf.copy(reinterpret_cast<char *>(&t_pod), sizeof(t_pod_type));
return true;
}
res.resize(s.size() / 2);
epee::span<char> rspan((char*)&res[0], res.size());
return parse_hexstr_to_binbuff(epee::to_span(s), rspan);
}
//----------------------------------------------------------------------------
PUSH_WARNINGS
@ -360,17 +343,10 @@ POP_WARNINGS
bool hex_to_pod(const std::string& hex_str, t_pod_type& s)
{
static_assert(std::is_pod<t_pod_type>::value, "expected pod type");
std::string hex_str_tr = trim(hex_str);
if(sizeof(s)*2 != hex_str.size())
return false;
std::string bin_buff;
if(!parse_hexstr_to_binbuff(hex_str_tr, bin_buff))
return false;
if(bin_buff.size()!=sizeof(s))
return false;
s = *(t_pod_type*)bin_buff.data();
return true;
epee::span<char> rspan((char*)&s, sizeof(s));
return parse_hexstr_to_binbuff(epee::to_span(hex_str), rspan);
}
//----------------------------------------------------------------------------
template<class t_pod_type>

@ -40,6 +40,9 @@
#include <atomic>
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "mlocker"
// did an mlock operation previously fail? we only
// want to log an error once and be done with it
static std::atomic<bool> previously_failed{ false };

@ -103,7 +103,7 @@ static const char *get_default_categories(int level)
categories = "*:WARNING,net:FATAL,net.http:FATAL,net.p2p:FATAL,net.cn:FATAL,global:INFO,verify:FATAL,stacktrace:INFO,logging:INFO,msgwriter:INFO";
break;
case 1:
categories = "*:INFO,global:INFO,stacktrace:INFO,logging:INFO,msgwriter:INFO";
categories = "*:INFO,global:INFO,stacktrace:INFO,logging:INFO,msgwriter:INFO,perf.*:DEBUG";
break;
case 2:
categories = "*:DEBUG";

@ -14,8 +14,8 @@ IF (MSVC)
include_directories(SYSTEM platform/msvc)
ELSE()
# set stuff for other systems
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -Wall -Werror")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Werror -Wno-reorder")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -Wall")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wno-reorder")
ENDIF()

@ -152,7 +152,7 @@ script: |
for i in ${HOSTS}; do
export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH}
mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DBACKCOMPAT=ON
make
DISTNAME=monero-${i}
mv bin ${DISTNAME}

@ -1,163 +0,0 @@
#!/usr/bin/env python3
# Copyright (c) 2014 Wladimir J. van der Laan
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
'''
A script to check that the (Linux) executables produced by gitian only contain
allowed gcc, glibc and libstdc++ version symbols. This makes sure they are
still compatible with the minimum supported Linux distribution versions.
Example usage:
find ../gitian-builder/build -type f -executable | xargs python contrib/devtools/symbol-check.py
'''
import subprocess
import re
import sys
import os
# Debian 6.0.9 (Squeeze) has:
#
# - g++ version 4.4.5 (https://packages.debian.org/search?suite=default&section=all&arch=any&searchon=names&keywords=g%2B%2B)
# - libc version 2.11.3 (https://packages.debian.org/search?suite=default&section=all&arch=any&searchon=names&keywords=libc6)
# - libstdc++ version 4.4.5 (https://packages.debian.org/search?suite=default&section=all&arch=any&searchon=names&keywords=libstdc%2B%2B6)
#
# Ubuntu 10.04.4 (Lucid Lynx) has:
#
# - g++ version 4.4.3 (http://packages.ubuntu.com/search?keywords=g%2B%2B&searchon=names&suite=lucid&section=all)
# - libc version 2.11.1 (http://packages.ubuntu.com/search?keywords=libc6&searchon=names&suite=lucid&section=all)
# - libstdc++ version 4.4.3 (http://packages.ubuntu.com/search?suite=lucid&section=all&arch=any&keywords=libstdc%2B%2B&searchon=names)
#
# Taking the minimum of these as our target.
#
# According to GNU ABI document (http://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html) this corresponds to:
# GCC 4.4.0: GCC_4.4.0
# GCC 4.4.2: GLIBCXX_3.4.13, CXXABI_1.3.3
# (glibc) GLIBC_2_11
#
MAX_VERSIONS = {
'GCC': (4,4,0),
'CXXABI': (1,3,3),
'GLIBCXX': (3,4,13),
'GLIBC': (2,11)
}
# See here for a description of _IO_stdin_used:
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=634261#109
# Ignore symbols that are exported as part of every executable
IGNORE_EXPORTS = {
'_edata', '_end', '_init', '__bss_start', '_fini', '_IO_stdin_used', 'stdin', 'stdout', 'stderr'
}
READELF_CMD = os.getenv('READELF', '/usr/bin/readelf')
CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt')
# Allowed NEEDED libraries
ALLOWED_LIBRARIES = {
# bitcoind and bitcoin-qt
'libgcc_s.so.1', # GCC base support
'libc.so.6', # C library
'libpthread.so.0', # threading
'libanl.so.1', # DNS resolve
'libm.so.6', # math library
'librt.so.1', # real-time (clock)
'ld-linux-x86-64.so.2', # 64-bit dynamic linker
'ld-linux.so.2', # 32-bit dynamic linker
# bitcoin-qt only
'libX11-xcb.so.1', # part of X11
'libX11.so.6', # part of X11
'libxcb.so.1', # part of X11
'libfontconfig.so.1', # font support
'libfreetype.so.6', # font parsing
'libdl.so.2' # programming interface to dynamic linker
}
class CPPFilt(object):
'''
Demangle C++ symbol names.
Use a pipe to the 'c++filt' command.
'''
def __init__(self):
self.proc = subprocess.Popen(CPPFILT_CMD, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True)
def __call__(self, mangled):
self.proc.stdin.write(mangled + '\n')
self.proc.stdin.flush()
return self.proc.stdout.readline().rstrip()
def close(self):
self.proc.stdin.close()
self.proc.stdout.close()
self.proc.wait()
def read_symbols(executable, imports=True):
'''
Parse an ELF executable and return a list of (symbol,version) tuples
for dynamic, imported symbols.
'''
p = subprocess.Popen([READELF_CMD, '--dyn-syms', '-W', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
(stdout, stderr) = p.communicate()
if p.returncode:
raise IOError('Could not read symbols for %s: %s' % (executable, stderr.strip()))
syms = []
for line in stdout.splitlines():
line = line.split()
if len(line)>7 and re.match('[0-9]+:$', line[0]):
(sym, _, version) = line[7].partition('@')
is_import = line[6] == 'UND'
if version.startswith('@'):
version = version[1:]
if is_import == imports:
syms.append((sym, version))
return syms
def check_version(max_versions, version):
if '_' in version:
(lib, _, ver) = version.rpartition('_')
else:
lib = version
ver = '0'
ver = tuple([int(x) for x in ver.split('.')])
if not lib in max_versions:
return False
return ver <= max_versions[lib]
def read_libraries(filename):
p = subprocess.Popen([READELF_CMD, '-d', '-W', filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
(stdout, stderr) = p.communicate()
if p.returncode:
raise IOError('Error opening file')
libraries = []
for line in stdout.splitlines():
tokens = line.split()
if len(tokens)>2 and tokens[1] == '(NEEDED)':
match = re.match('^Shared library: \[(.*)\]$', ' '.join(tokens[2:]))
if match:
libraries.append(match.group(1))
else:
raise ValueError('Unparseable (NEEDED) specification')
return libraries
if __name__ == '__main__':
cppfilt = CPPFilt()
retval = 0
for filename in sys.argv[1:]:
# Check imported symbols
for sym,version in read_symbols(filename, True):
if version and not check_version(MAX_VERSIONS, version):
print('%s: symbol %s from unsupported version %s' % (filename, cppfilt(sym), version))
retval = 1
# Check exported symbols
for sym,version in read_symbols(filename, False):
if sym in IGNORE_EXPORTS:
continue
print('%s: export of symbol %s not allowed' % (filename, cppfilt(sym)))
retval = 1
# Check dependency libraries
for library_name in read_libraries(filename):
if library_name not in ALLOWED_LIBRARIES:
print('%s: NEEDED library %s is not allowed' % (filename, library_name))
retval = 1
sys.exit(retval)

@ -2130,24 +2130,23 @@ static int priority(Level level) {
return 7;
}
bool VRegistry::allowed(Level level, const char* category) {
bool VRegistry::allowed(Level level, const std::string &category) {
base::threading::ScopedLock scopedLock(lock());
const std::string scategory = category;
const std::map<std::string, int>::const_iterator it = m_cached_allowed_categories.find(scategory);
const std::map<std::string, int>::const_iterator it = m_cached_allowed_categories.find(category);
if (it != m_cached_allowed_categories.end())
return priority(level) <= it->second;
if (m_categories.empty() || category == nullptr) {
if (m_categories.empty()) {
return false;
} else {
std::vector<std::pair<std::string, Level>>::const_reverse_iterator it = m_categories.rbegin();
for (; it != m_categories.rend(); ++it) {
if (base::utils::Str::wildCardMatch(category, it->first.c_str())) {
if (base::utils::Str::wildCardMatch(category.c_str(), it->first.c_str())) {
const int p = priority(it->second);
m_cached_allowed_categories.insert(std::make_pair(std::move(scategory), p));
m_cached_allowed_categories.insert(std::make_pair(category, p));
return priority(level) <= p;
}
}
m_cached_allowed_categories.insert(std::make_pair(std::move(scategory), -1));
m_cached_allowed_categories.insert(std::make_pair(category, -1));
return false;
}
}
@ -2694,6 +2693,12 @@ Writer& Writer::construct(int count, const char* loggerIds, ...) {
return *this;
}
Writer& Writer::construct(const char *loggerId) {
initializeLogger(ELPP->registeredLoggers()->get(loggerId, ELPP->hasFlag(LoggingFlag::CreateLoggerAutomatically)));
m_messageBuilder.initialize(m_logger);
return *this;
}
void Writer::initializeLogger(const std::string& loggerId, bool lookup, bool needLock) {
if (lookup) {
m_logger = ELPP->registeredLoggers()->get(loggerId, ELPP->hasFlag(LoggingFlag::CreateLoggerAutomatically));
@ -2715,13 +2720,26 @@ void Writer::initializeLogger(const std::string& loggerId, bool lookup, bool nee
}
if (ELPP->hasFlag(LoggingFlag::HierarchicalLogging)) {
m_proceed = m_level == Level::Verbose ? m_logger->enabled(m_level) :
ELPP->vRegistry()->allowed(m_level, loggerId.c_str());
ELPP->vRegistry()->allowed(m_level, loggerId);
} else {
m_proceed = m_logger->enabled(m_level);
}
}
}
void Writer::initializeLogger(Logger *logger, bool needLock) {
m_logger = logger;
if (m_logger == nullptr) {
m_proceed = false;
} else {
if (needLock) {
m_logger->acquireLock(); // This should not be unlocked by checking m_proceed because
// m_proceed can be changed by lines below
}
m_proceed = true;
}
}
void Writer::processDispatch() {
#if ELPP_LOGGING_ENABLED
if (ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) {

@ -2463,7 +2463,7 @@ class VRegistry : base::NoCopy, public base::threading::ThreadSafe {
void setModules(const char* modules);
bool allowed(Level level, const char* category);
bool allowed(Level level, const std::string &category);
bool allowed(base::type::VerboseLevel vlevel, const char* file);
@ -3290,6 +3290,7 @@ class Writer : base::NoCopy {
Writer& construct(Logger* logger, bool needLock = true);
Writer& construct(int count, const char* loggerIds, ...);
Writer& construct(const char *loggerId);
protected:
LogMessage* m_msg;
Level m_level;
@ -3305,6 +3306,7 @@ class Writer : base::NoCopy {
friend class el::Helpers;
void initializeLogger(const std::string& loggerId, bool lookup = true, bool needLock = true);
void initializeLogger(Logger *logger, bool needLock = true);
void processDispatch();
void triggerDispatch(void);
};

@ -34,11 +34,6 @@ if (WIN32 OR STATIC)
add_definitions(-DMINIUPNP_STATICLIB)
endif ()
# warnings are cleared only for GCC on Linux
if (NOT (MINGW OR APPLE OR FREEBSD OR OPENBSD OR DRAGONFLY))
add_compile_options("${WARNINGS_AS_ERRORS_FLAG}") # applies only to targets that follow
endif()
function (monero_private_headers group)
source_group("${group}\\Private"
FILES

@ -714,29 +714,6 @@ bool BlockchainBDB::for_all_outputs(std::function<bool(uint64_t amount, const cr
return ret;
}
blobdata BlockchainBDB::output_to_blob(const tx_out& output) const
{
LOG_PRINT_L3("BlockchainBDB::" << __func__);
blobdata b;
if (!t_serializable_object_to_blob(output, b))
throw1(DB_ERROR("Error serializing output to blob"));
return b;
}
tx_out BlockchainBDB::output_from_blob(const blobdata& blob) const
{
LOG_PRINT_L3("BlockchainBDB::" << __func__);
std::stringstream ss;
ss << blob;
binary_archive<false> ba(ss);
tx_out o;
if (!(::serialization::serialize(ba, o)))
throw1(DB_ERROR("Error deserializing tx output blob"));
return o;
}
uint64_t BlockchainBDB::get_output_global_index(const uint64_t& amount, const uint64_t& index)
{
LOG_PRINT_L3("BlockchainBDB::" << __func__);
@ -1655,7 +1632,7 @@ output_data_t BlockchainBDB::get_output_key(const uint64_t& global_index) const
return v;
}
output_data_t BlockchainBDB::get_output_key(const uint64_t& amount, const uint64_t& index)
output_data_t BlockchainBDB::get_output_key(const uint64_t& amount, const uint64_t& index) const
{
LOG_PRINT_L3("BlockchainBDB::" << __func__);
check_open();
@ -1664,7 +1641,7 @@ output_data_t BlockchainBDB::get_output_key(const uint64_t& amount, const uint64
return get_output_key(glob_index);
}
tx_out_index BlockchainBDB::get_output_tx_and_index(const uint64_t& amount, const uint64_t& index)
tx_out_index BlockchainBDB::get_output_tx_and_index(const uint64_t& amount, const uint64_t& index) const
{
LOG_PRINT_L3("BlockchainBDB::" << __func__);
std::vector < uint64_t > offsets;

@ -391,24 +391,6 @@ private:
virtual void check_hard_fork_info();
virtual void drop_hard_fork_info();
/**
* @brief convert a tx output to a blob for storage
*
* @param output the output to convert
*
* @return the resultant blob
*/
blobdata output_to_blob(const tx_out& output) const;
/**
* @brief convert a tx output blob to a tx output
*
* @param blob the blob to convert
*
* @return the resultant tx output
*/
tx_out output_from_blob(const blobdata& blob) const;
/**
* @brief get the global index of the index-th output of the given amount
*

@ -170,7 +170,7 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const transacti
uint64_t tx_id = add_transaction_data(blk_hash, tx, tx_hash, tx_prunable_hash);
std::vector<uint64_t> amount_output_indices;
std::vector<uint64_t> amount_output_indices(tx.vout.size());
// iterate tx.vout using indices instead of C++11 foreach syntax because
// we need the index
@ -183,13 +183,13 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const transacti
cryptonote::tx_out vout = tx.vout[i];
rct::key commitment = rct::zeroCommit(vout.amount);
vout.amount = 0;
amount_output_indices.push_back(add_output(tx_hash, vout, i, tx.unlock_time,
&commitment));
amount_output_indices[i] = add_output(tx_hash, vout, i, tx.unlock_time,
&commitment);
}
else
{
amount_output_indices.push_back(add_output(tx_hash, tx.vout[i], i, tx.unlock_time,
tx.version > 1 ? &tx.rct_signatures.outPk[i].mask : NULL));
amount_output_indices[i] = add_output(tx_hash, tx.vout[i], i, tx.unlock_time,
tx.version > 1 ? &tx.rct_signatures.outPk[i].mask : NULL);
}
}
add_tx_amount_output_indices(tx_id, amount_output_indices);

@ -1258,7 +1258,7 @@ public:
*
* @return the requested output data
*/
virtual output_data_t get_output_key(const uint64_t& amount, const uint64_t& index) = 0;
virtual output_data_t get_output_key(const uint64_t& amount, const uint64_t& index) const = 0;
/**
* @brief gets an output's tx hash and index
@ -1310,7 +1310,7 @@ public:
* @param offsets a list of amount-specific output indices
* @param outputs return-by-reference a list of outputs' metadata
*/
virtual void get_output_key(const epee::span<const uint64_t> &amounts, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs, bool allow_partial = false) = 0;
virtual void get_output_key(const epee::span<const uint64_t> &amounts, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs, bool allow_partial = false) const = 0;
/*
* FIXME: Need to check with git blame and ask what this does to

@ -456,6 +456,12 @@ inline int lmdb_txn_renew(MDB_txn *txn)
return res;
}
inline void BlockchainLMDB::check_open() const
{
if (!m_open)
throw0(DB_ERROR("DB operation attempted on a not-open DB instance"));
}
void BlockchainLMDB::do_resize(uint64_t increase_size)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
@ -1166,36 +1172,6 @@ void BlockchainLMDB::remove_spent_key(const crypto::key_image& k_image)
}
}
blobdata BlockchainLMDB::output_to_blob(const tx_out& output) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
blobdata b;
if (!t_serializable_object_to_blob(output, b))
throw1(DB_ERROR("Error serializing output to blob"));
return b;
}
tx_out BlockchainLMDB::output_from_blob(const blobdata& blob) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
std::stringstream ss;
ss << blob;
binary_archive<false> ba(ss);
tx_out o;
if (!(::serialization::serialize(ba, o)))
throw1(DB_ERROR("Error deserializing tx output blob"));
return o;
}
void BlockchainLMDB::check_open() const
{
// LOG_PRINT_L3("BlockchainLMDB::" << __func__);
if (!m_open)
throw0(DB_ERROR("DB operation attempted on a not-open DB instance"));
}
BlockchainLMDB::~BlockchainLMDB()
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
@ -2559,7 +2535,7 @@ uint64_t BlockchainLMDB::get_num_outputs(const uint64_t& amount) const
return num_elems;
}
output_data_t BlockchainLMDB::get_output_key(const uint64_t& amount, const uint64_t& index)
output_data_t BlockchainLMDB::get_output_key(const uint64_t& amount, const uint64_t& index) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@ -3192,7 +3168,7 @@ uint64_t BlockchainLMDB::add_block(const block& blk, size_t block_weight, const
check_open();
uint64_t m_height = height();
if (m_height % 1000 == 0)
if (m_height % 1024 == 0)
{
// for batch mode, DB resize check is done at start of batch transaction
if (! m_batch_active && need_resize())
@ -3266,7 +3242,7 @@ void BlockchainLMDB::get_output_tx_and_index_from_global(const std::vector<uint6
TXN_POSTFIX_RDONLY();
}
void BlockchainLMDB::get_output_key(const epee::span<const uint64_t> &amounts, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs, bool allow_partial)
void BlockchainLMDB::get_output_key(const epee::span<const uint64_t> &amounts, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs, bool allow_partial) const
{
if (amounts.size() != 1 && amounts.size() != offsets.size())
throw0(DB_ERROR("Invalid sizes of amounts and offets"));

@ -242,8 +242,8 @@ public:
virtual uint64_t get_num_outputs(const uint64_t& amount) const;
virtual output_data_t get_output_key(const uint64_t& amount, const uint64_t& index);
virtual void get_output_key(const epee::span<const uint64_t> &amounts, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs, bool allow_partial = false);
virtual output_data_t get_output_key(const uint64_t& amount, const uint64_t& index) const;
virtual void get_output_key(const epee::span<const uint64_t> &amounts, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs, bool allow_partial = false) const;
virtual tx_out_index get_output_tx_and_index_from_global(const uint64_t& index) const;
virtual void get_output_tx_and_index_from_global(const std::vector<uint64_t> &global_indices,
@ -359,25 +359,7 @@ private:
virtual void check_hard_fork_info();
virtual void drop_hard_fork_info();
/**
* @brief convert a tx output to a blob for storage
*
* @param output the output to convert
*
* @return the resultant blob
*/
blobdata output_to_blob(const tx_out& output) const;
/**
* @brief convert a tx output blob to a tx output
*
* @param blob the blob to convert
*
* @return the resultant tx output
*/
tx_out output_from_blob(const blobdata& blob) const;
void check_open() const;
inline void check_open() const;
virtual bool is_read_only() const;

@ -39,7 +39,7 @@ foreach(BLOB_NAME checkpoints testnet_blocks stagenet_blocks)
cd ${CMAKE_CURRENT_BINARY_DIR} &&
echo "'#include\t<stddef.h>'" > ${OUTPUT_C_SOURCE} &&
echo "'const\tunsigned\tchar\t${BLOB_NAME}[]={'" >> ${OUTPUT_C_SOURCE} &&
od -v -An -tu1 ${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_DAT_FILE} | sed -e "'s/[0-9]\\{1,\\}/&,/g'" -e "'$$s/.$$//'" >> ${OUTPUT_C_SOURCE} &&
od -v -An -tx1 ${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_DAT_FILE} | sed -e "'s/[0-9a-fA-F]\\{1,\\}/0x&,/g'" -e "'$$s/.$$//'" >> ${OUTPUT_C_SOURCE} &&
echo "'};'" >> ${OUTPUT_C_SOURCE} &&
echo "'const\tsize_t\t${BLOB_NAME}_len\t=\tsizeof(${BLOB_NAME});'" >> ${OUTPUT_C_SOURCE}
)

@ -74,7 +74,7 @@ namespace cryptonote
bool checkpoints::add_checkpoint(uint64_t height, const std::string& hash_str)
{
crypto::hash h = crypto::null_hash;
bool r = epee::string_tools::parse_tpod_from_hex_string(hash_str, h);
bool r = epee::string_tools::hex_to_pod(hash_str, h);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse checkpoint hash string into binary representation!");
// return false if adding at a height we already have AND the hash is different
@ -283,7 +283,7 @@ namespace cryptonote
// parse the second part as crypto::hash,
// if this fails move on to the next record
std::string hashStr = record.substr(pos + 1);
if (!epee::string_tools::parse_tpod_from_hex_string(hashStr, hash))
if (!epee::string_tools::hex_to_pod(hashStr, hash))
{
continue;
}

@ -50,6 +50,10 @@ if (STACK_TRACE)
list(APPEND common_sources stack_trace.cpp)
endif()
if (BACKCOMPAT)
list(APPEND common_sources compat/glibc_compat.cpp)
endif()
set(common_headers)
set(common_private_headers

@ -0,0 +1,98 @@
#include <cstddef>
#include <cstdint>
#include <strings.h>
#include <string.h>
#include <glob.h>
#include <unistd.h>
#include <fnmatch.h>
#if defined(HAVE_SYS_SELECT_H)
#include <sys/select.h>
#endif
// Prior to GLIBC_2.14, memcpy was aliased to memmove.
extern "C" void* memmove(void* a, const void* b, size_t c);
//extern "C" void* memset(void* a, int b, long unsigned int c);
extern "C" void* memcpy(void* a, const void* b, size_t c)
{
return memmove(a, b, c);
}
extern "C" void __chk_fail(void) __attribute__((__noreturn__));
#if defined(__i386__) || defined(__arm__)
extern "C" int64_t __udivmoddi4(uint64_t u, uint64_t v, uint64_t* rp);
extern "C" int64_t __wrap___divmoddi4(int64_t u, int64_t v, int64_t* rp)
{
int32_t c1 = 0, c2 = 0;
int64_t uu = u, vv = v;
int64_t w;
int64_t r;
if (uu < 0) {
c1 = ~c1, c2 = ~c2, uu = -uu;
}
if (vv < 0) {
c1 = ~c1, vv = -vv;
}
w = __udivmoddi4(uu, vv, (uint64_t*)&r);
if (c1)
w = -w;
if (c2)
r = -r;
*rp = r;
return w;
}
#endif
/* glibc-internal users use __explicit_bzero_chk, and explicit_bzero
redirects to that. */
#undef explicit_bzero
/* Set LEN bytes of S to 0. The compiler will not delete a call to
this function, even if S is dead after the call. */
void
explicit_bzero (void *s, size_t len)
{
memset (s, '\0', len);
/* Compiler barrier. */
asm volatile ("" ::: "memory");
}
// Redefine explicit_bzero_chk
void
__explicit_bzero_chk (void *dst, size_t len, size_t dstlen)
{
/* Inline __memset_chk to avoid a PLT reference to __memset_chk. */
if (__glibc_unlikely (dstlen < len))
__chk_fail ();
memset (dst, '\0', len);
/* Compiler barrier. */
asm volatile ("" ::: "memory");
}
/* libc-internal references use the hidden
__explicit_bzero_chk_internal symbol. This is necessary if
__explicit_bzero_chk is implemented as an IFUNC because some
targets do not support hidden references to IFUNC symbols. */
#define strong_alias (__explicit_bzero_chk, __explicit_bzero_chk_internal)
#undef glob
extern "C" int glob_old(const char * pattern, int flags, int (*errfunc) (const char *epath, int eerrno), glob_t *pglob);
#ifdef __i386__
__asm__(".symver glob_old,glob@GLIBC_2.1");
#elif defined(__amd64__)
__asm__(".symver glob_old,glob@GLIBC_2.2.5");
#elif defined(__arm__)
__asm(".symver glob_old,glob@GLIBC_2.4");
#elif defined(__aarch64__)
__asm__(".symver glob_old,glob@GLIBC_2.17");
#endif
extern "C" int __wrap_glob(const char * pattern, int flags, int (*errfunc) (const char *epath, int eerrno), glob_t *pglob)
{
return glob_old(pattern, flags, errfunc, pglob);
}

@ -33,6 +33,13 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "perf"
#define PERF_LOG_ALWAYS(level, cat, x) \
el::base::Writer(level, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::FileOnlyLog).construct(cat) << x
#define PERF_LOG(level, cat, x) \
do { \
if (ELPP->vRegistry()->allowed(level, cat)) PERF_LOG_ALWAYS(level, cat, x); \
} while(0)
namespace tools
{
uint64_t get_tick_count()
@ -106,9 +113,11 @@ PerformanceTimer::PerformanceTimer(bool paused): started(true), paused(paused)
LoggingPerformanceTimer::LoggingPerformanceTimer(const std::string &s, const std::string &cat, uint64_t unit, el::Level l): PerformanceTimer(), name(s), cat(cat), unit(unit), level(l)
{
const bool log = ELPP->vRegistry()->allowed(level, cat.c_str());
if (!performance_timers)
{
MCLOG(level, cat.c_str(), "PERF ----------");
if (log)
PERF_LOG_ALWAYS(level, cat.c_str(), "PERF ----------");
performance_timers = new std::vector<LoggingPerformanceTimer*>();
performance_timers->reserve(16); // how deep before realloc
}
@ -117,8 +126,11 @@ LoggingPerformanceTimer::LoggingPerformanceTimer(const std::string &s, const std
LoggingPerformanceTimer *pt = performance_timers->back();
if (!pt->started && !pt->paused)
{
size_t size = 0; for (const auto *tmp: *performance_timers) if (!tmp->paused) ++size;
MCLOG(pt->level, cat.c_str(), "PERF " << std::string((size-1) * 2, ' ') << " " << pt->name);
if (log)
{
size_t size = 0; for (const auto *tmp: *performance_timers) if (!tmp->paused) ++size;
PERF_LOG_ALWAYS(pt->level, cat.c_str(), "PERF " << std::string((size-1) * 2, ' ') << " " << pt->name);
}
pt->started = true;
}
}
@ -135,10 +147,14 @@ LoggingPerformanceTimer::~LoggingPerformanceTimer()
{
pause();
performance_timers->pop_back();
char s[12];
snprintf(s, sizeof(s), "%8llu ", (unsigned long long)(ticks_to_ns(ticks) / (1000000000 / unit)));
size_t size = 0; for (const auto *tmp: *performance_timers) if (!tmp->paused || tmp==this) ++size;
MCLOG(level, cat.c_str(), "PERF " << s << std::string(size * 2, ' ') << " " << name);
const bool log = ELPP->vRegistry()->allowed(level, cat.c_str());
if (log)
{
char s[12];
snprintf(s, sizeof(s), "%8llu ", (unsigned long long)(ticks_to_ns(ticks) / (1000000000 / unit)));
size_t size = 0; for (const auto *tmp: *performance_timers) if (!tmp->paused || tmp==this) ++size;
PERF_LOG_ALWAYS(level, cat.c_str(), "PERF " << s << std::string(size * 2, ' ') << " " << name);
}
if (performance_timers->empty())
{
delete performance_timers;
@ -162,4 +178,20 @@ void PerformanceTimer::resume()
paused = false;
}
void PerformanceTimer::reset()
{
if (paused)
ticks = 0;
else
ticks = get_tick_count();
}
uint64_t PerformanceTimer::value() const
{
uint64_t v = ticks;
if (!paused)
v = get_tick_count() - v;
return ticks_to_ns(v);
}
}

@ -51,8 +51,8 @@ public:
~PerformanceTimer();
void pause();
void resume();
uint64_t value() const { return ticks; }
void reset();
uint64_t value() const;
protected:
uint64_t ticks;
@ -63,7 +63,7 @@ protected:
class LoggingPerformanceTimer: public PerformanceTimer
{
public:
LoggingPerformanceTimer(const std::string &s, const std::string &cat, uint64_t unit, el::Level l = el::Level::Debug);
LoggingPerformanceTimer(const std::string &s, const std::string &cat, uint64_t unit, el::Level l = el::Level::Info);
~LoggingPerformanceTimer();
private:

@ -35,6 +35,7 @@
#include <windows.h>
#else
#include <sys/wait.h>
#include <signal.h>
#endif
#include "misc_log_ex.h"
@ -114,7 +115,10 @@ int spawn(const char *filename, const std::vector<std::string>& args, bool wait)
if (pid > 0)
{
if (!wait)
{
signal(SIGCHLD, SIG_IGN);
return 0;
}
while (1)
{

@ -82,6 +82,32 @@ using namespace epee;
#include <boost/asio.hpp>
#include <openssl/sha.h>
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "util"
namespace
{
#ifndef _WIN32
static int flock_exnb(int fd)
{
struct flock fl;
int ret;
memset(&fl, 0, sizeof(fl));
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
ret = fcntl(fd, F_SETLK, &fl);
if (ret < 0)
MERROR("Error locking fd " << fd << ": " << errno << " (" << strerror(errno) << ")");
return ret;
}
#endif
}
namespace tools
{
std::function<void(int)> signal_handler::m_handler;
@ -182,7 +208,7 @@ namespace tools
struct stat wstats = {};
if (fstat(fdw, std::addressof(wstats)) == 0 &&
rstats.st_dev == wstats.st_dev && rstats.st_ino == wstats.st_ino &&
flock(fdw, (LOCK_EX | LOCK_NB)) == 0 && ftruncate(fdw, 0) == 0)
flock_exnb(fdw) == 0 && ftruncate(fdw, 0) == 0)
{
std::FILE* file = fdopen(fdw, "w");
if (file) return {file, std::move(name)};
@ -235,10 +261,10 @@ namespace tools
MERROR("Failed to open " << filename << ": " << std::error_code(GetLastError(), std::system_category()));
}
#else
m_fd = open(filename.c_str(), O_RDONLY | O_CREAT | O_CLOEXEC, 0666);
m_fd = open(filename.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0666);
if (m_fd != -1)
{
if (flock(m_fd, LOCK_EX | LOCK_NB) == -1)
if (flock_exnb(m_fd) == -1)
{
MERROR("Failed to lock " << filename << ": " << std::strerror(errno));
close(m_fd);

@ -211,6 +211,8 @@ namespace cryptonote
void set_hash_valid(bool v) const { hash_valid.store(v,std::memory_order_release); }
bool is_blob_size_valid() const { return blob_size_valid.load(std::memory_order_acquire); }
void set_blob_size_valid(bool v) const { blob_size_valid.store(v,std::memory_order_release); }
void set_hash(const crypto::hash &h) { hash = h; set_hash_valid(true); }
void set_blob_size(size_t sz) { blob_size = sz; set_blob_size_valid(true); }
BEGIN_SERIALIZE_OBJECT()
if (!typename Archive<W>::is_saving())

@ -204,6 +204,7 @@ namespace cryptonote
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data");
tx.invalidate_hashes();
tx.set_blob_size(tx_blob.size());
return true;
}
//---------------------------------------------------------------
@ -401,11 +402,19 @@ namespace cryptonote
//---------------------------------------------------------------
uint64_t get_transaction_weight(const transaction &tx)
{
std::ostringstream s;
binary_archive<true> a(s);
::serialization::serialize(a, const_cast<transaction&>(tx));
const cryptonote::blobdata blob = s.str();
return get_transaction_weight(tx, blob.size());
size_t blob_size;
if (tx.is_blob_size_valid())
{
blob_size = tx.blob_size;
}
else
{
std::ostringstream s;
binary_archive<true> a(s);
::serialization::serialize(a, const_cast<transaction&>(tx));
blob_size = s.str().size();
}
return get_transaction_weight(tx, blob_size);
}
//---------------------------------------------------------------
bool get_tx_fee(const transaction& tx, uint64_t & fee)

@ -128,6 +128,11 @@ Blockchain::Blockchain(tx_memory_pool& tx_pool) :
LOG_PRINT_L3("Blockchain::" << __func__);
}
//------------------------------------------------------------------
Blockchain::~Blockchain()
{
deinit();
}
//------------------------------------------------------------------
bool Blockchain::have_tx(const crypto::hash &id) const
{
LOG_PRINT_L3("Blockchain::" << __func__);
@ -507,15 +512,13 @@ bool Blockchain::deinit()
// as this should be called if handling a SIGSEGV, need to check
// if m_db is a NULL pointer (and thus may have caused the illegal
// memory operation), otherwise we may cause a loop.
if (m_db == NULL)
{
throw DB_ERROR("The db pointer is null in Blockchain, the blockchain may be corrupt!");
}
try
{
m_db->close();
MTRACE("Local blockchain read/write activity stopped successfully");
if (m_db)
{
m_db->close();
MTRACE("Local blockchain read/write activity stopped successfully");
}
}
catch (const std::exception& e)
{
@ -1270,7 +1273,9 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
uint64_t already_generated_coins;
uint64_t pool_cookie;
CRITICAL_REGION_BEGIN(m_blockchain_lock);
m_tx_pool.lock();
const auto unlock_guard = epee::misc_utils::create_scope_leave_handler([&]() { m_tx_pool.unlock(); });
CRITICAL_REGION_LOCAL(m_blockchain_lock);
height = m_db->height();
if (m_btc_valid) {
// The pool cookie is atomic. The lack of locking is OK, as if it changes
@ -1306,8 +1311,6 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
median_weight = m_current_block_cumul_weight_limit / 2;
already_generated_coins = m_db->get_block_already_generated_coins(height - 1);
CRITICAL_REGION_END();
size_t txs_weight;
uint64_t fee;
if (!m_tx_pool.fill_block_template(b, median_weight, already_generated_coins, txs_weight, fee, expected_reward, m_hardfork->get_current_version()))
@ -1318,7 +1321,6 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
size_t real_txs_weight = 0;
uint64_t real_fee = 0;
CRITICAL_REGION_BEGIN(m_tx_pool.m_transactions_lock);
for(crypto::hash &cur_hash: b.tx_hashes)
{
auto cur_res = m_tx_pool.m_transactions.find(cur_hash);
@ -1362,7 +1364,6 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
{
LOG_ERROR("Creating block template: error: wrongly calculated fee");
}
CRITICAL_REGION_END();
MDEBUG("Creating block template: height " << height <<
", median weight " << median_weight <<
", already generated coins " << already_generated_coins <<

@ -120,6 +120,11 @@ namespace cryptonote
*/
Blockchain(tx_memory_pool& tx_pool);
/**
* @brief Blockchain destructor
*/
~Blockchain();
/**
* @brief Initialize the Blockchain state
*

@ -480,6 +480,10 @@ namespace cryptonote
MERROR("Failed to parse tx from txpool");
return false;
}
else
{
tx.set_hash(id);
}
tx_weight = meta.weight;
fee = meta.fee;
relayed = meta.relayed;
@ -659,7 +663,8 @@ namespace cryptonote
// continue
return true;
}
txs.push_back(tx);
tx.set_hash(txid);
txs.push_back(std::move(tx));
return true;
}, true, include_unrelayed_txes);
}
@ -782,6 +787,7 @@ namespace cryptonote
// continue
return true;
}
tx.set_hash(txid);
txi.tx_json = obj_to_json_str(tx);
txi.blob_size = bd->size();
txi.weight = meta.weight;
@ -798,7 +804,7 @@ namespace cryptonote
txi.last_relayed_time = include_sensitive_data ? meta.last_relayed_time : 0;
txi.do_not_relay = meta.do_not_relay;
txi.double_spend_seen = meta.double_spend_seen;
tx_infos.push_back(txi);
tx_infos.push_back(std::move(txi));
return true;
}, true, include_sensitive_data);
@ -847,14 +853,13 @@ namespace cryptonote
m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
cryptonote::rpc::tx_in_pool txi;
txi.tx_hash = txid;
transaction tx;
if (!parse_and_validate_tx_from_blob(*bd, tx))
if (!parse_and_validate_tx_from_blob(*bd, txi.tx))
{
MERROR("Failed to parse tx from txpool");
// continue
return true;
}
txi.tx = tx;
txi.tx.set_hash(txid);
txi.blob_size = bd->size();
txi.weight = meta.weight;
txi.fee = meta.fee;
@ -881,7 +886,7 @@ namespace cryptonote
}
const crypto::key_image& k_image = kee.first;
key_image_infos[k_image] = tx_hashes;
key_image_infos[k_image] = std::move(tx_hashes);
}
return true;
}
@ -990,21 +995,23 @@ namespace cryptonote
{
struct transction_parser
{
transction_parser(const cryptonote::blobdata &txblob, transaction &tx): txblob(txblob), tx(tx), parsed(false) {}
transction_parser(const cryptonote::blobdata &txblob, const crypto::hash &txid, transaction &tx): txblob(txblob), txid(txid), tx(tx), parsed(false) {}
cryptonote::transaction &operator()()
{
if (!parsed)
{
if (!parse_and_validate_tx_from_blob(txblob, tx))
throw std::runtime_error("failed to parse transaction blob");
tx.set_hash(txid);
parsed = true;
}
return tx;
}
const cryptonote::blobdata &txblob;
const crypto::hash &txid;
transaction &tx;
bool parsed;
} lazy_tx(txblob, tx);
} lazy_tx(txblob, txid, tx);
//not the best implementation at this time, sorry :(
//check is ring_signature already checked ?

@ -131,6 +131,7 @@ namespace cryptonote
bool should_download_next_span(cryptonote_connection_context& context) const;
void drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans);
bool kick_idle_peers();
bool check_standby_peers();
int try_add_next_blocks(cryptonote_connection_context &context);
t_core& m_core;
@ -143,6 +144,7 @@ namespace cryptonote
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_milliseconds<100> m_standby_checker;
boost::mutex m_buffer_mutex;
double get_avg_block_size();

@ -1208,6 +1208,7 @@ skip:
bool t_cryptonote_protocol_handler<t_core>::on_idle()
{
m_idle_peer_kicker.do_call(boost::bind(&t_cryptonote_protocol_handler<t_core>::kick_idle_peers, this));
m_standby_checker.do_call(boost::bind(&t_cryptonote_protocol_handler<t_core>::check_standby_peers, this));
return m_core.on_idle();
}
//------------------------------------------------------------------------------------------------------------------------
@ -1243,6 +1244,22 @@ skip:
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::check_standby_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_standby)
{
LOG_PRINT_CCONTEXT_L2("requesting callback");
++context.m_callback_request_count;
m_p2p->request_callback(context);
}
return true;
});
return true;
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
int t_cryptonote_protocol_handler<t_core>::handle_request_chain(int command, NOTIFY_REQUEST_CHAIN::request& arg, cryptonote_connection_context& context)
{
MLOG_P2P_MESSAGE("Received NOTIFY_REQUEST_CHAIN (" << arg.block_ids.size() << " blocks");
@ -1336,14 +1353,13 @@ skip:
bool start_from_current_chain = false;
if (!force_next_span)
{
bool first = true;
while (1)
do
{
size_t nblocks = m_block_queue.get_num_filled_spans();
size_t size = m_block_queue.get_data_size();
if (nblocks < BLOCK_QUEUE_NBLOCKS_THRESHOLD || size < BLOCK_QUEUE_SIZE_THRESHOLD)
{
if (!first)
if (context.m_state != cryptonote_connection_context::state_standby)
{
LOG_DEBUG_CC(context, "Block queue is " << nblocks << " and " << size << ", resuming");
}
@ -1366,10 +1382,9 @@ skip:
break;
}
if (first)
if (context.m_state != cryptonote_connection_context::state_standby)
{
LOG_DEBUG_CC(context, "Block queue is " << nblocks << " and " << size << ", pausing");
first = false;
context.m_state = cryptonote_connection_context::state_standby;
}
@ -1383,13 +1398,8 @@ skip:
return true;
}
for (size_t n = 0; n < 50; ++n)
{
if (m_stopping)
return true;
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
}
}
return true;
} while(0);
context.m_state = cryptonote_connection_context::state_synchronizing;
}

@ -67,14 +67,6 @@ set(trezor_private_headers)
if(DEVICE_TREZOR_READY)
message(STATUS "Trezor support enabled")
add_definitions(-DPROTOBUF_INLINE_NOT_IN_HEADERS=0)
set(TREZOR_LIBUSB_LIBRARIES "")
if(LibUSB_COMPILE_TEST_PASSED)
list(APPEND TREZOR_LIBUSB_LIBRARIES ${LibUSB_LIBRARIES})
message(STATUS "Trezor compatible LibUSB found at: ${LibUSB_INCLUDE_DIRS}")
endif()
monero_private_headers(device_trezor
${device_private_headers})

@ -50,8 +50,8 @@ namespace Language
class Singleton
{
Singleton() {}
Singleton(Singleton &s) {}
Singleton& operator=(const Singleton&) {}
Singleton(Singleton &s) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static T* instance()
{

@ -194,12 +194,12 @@ namespace nodetool
const boost::program_options::variables_map& vm
);
bool idle_worker();
bool handle_remote_peerlist(const std::list<peerlist_entry>& peerlist, time_t local_time, const epee::net_utils::connection_context_base& context);
bool handle_remote_peerlist(const std::vector<peerlist_entry>& peerlist, time_t local_time, const epee::net_utils::connection_context_base& context);
bool get_local_node_data(basic_node_data& node_data);
//bool get_local_handshake_data(handshake_data& hshd);
bool merge_peerlist_with_local(const std::list<peerlist_entry>& bs);
bool fix_time_delta(std::list<peerlist_entry>& local_peerlist, time_t local_time, int64_t& delta);
bool merge_peerlist_with_local(const std::vector<peerlist_entry>& bs);
bool fix_time_delta(std::vector<peerlist_entry>& local_peerlist, time_t local_time, int64_t& delta);
bool connections_maker();
bool peer_sync_idle_maker();

@ -1365,7 +1365,7 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::fix_time_delta(std::list<peerlist_entry>& local_peerlist, time_t local_time, int64_t& delta)
bool node_server<t_payload_net_handler>::fix_time_delta(std::vector<peerlist_entry>& local_peerlist, time_t local_time, int64_t& delta)
{
//fix time delta
time_t now = 0;
@ -1385,10 +1385,10 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::handle_remote_peerlist(const std::list<peerlist_entry>& peerlist, time_t local_time, const epee::net_utils::connection_context_base& context)
bool node_server<t_payload_net_handler>::handle_remote_peerlist(const std::vector<peerlist_entry>& peerlist, time_t local_time, const epee::net_utils::connection_context_base& context)
{
int64_t delta = 0;
std::list<peerlist_entry> peerlist_ = peerlist;
std::vector<peerlist_entry> peerlist_ = peerlist;
if(!fix_time_delta(peerlist_, local_time, delta))
return false;
LOG_DEBUG_CC(context, "REMOTE PEERLIST: TIME_DELTA: " << delta << ", remote peerlist size=" << peerlist_.size());
@ -1770,8 +1770,8 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::log_peerlist()
{
std::list<peerlist_entry> pl_white;
std::list<peerlist_entry> pl_gray;
std::vector<peerlist_entry> pl_white;
std::vector<peerlist_entry> pl_gray;
m_peerlist.get_peerlist_full(pl_gray, pl_white);
MINFO(ENDL << "Peerlist white:" << ENDL << print_peerlist_to_string(pl_white) << ENDL << "Peerlist gray:" << ENDL << print_peerlist_to_string(pl_gray) );
return true;

@ -68,9 +68,9 @@ namespace nodetool
bool deinit();
size_t get_white_peers_count(){CRITICAL_REGION_LOCAL(m_peerlist_lock); return m_peers_white.size();}
size_t get_gray_peers_count(){CRITICAL_REGION_LOCAL(m_peerlist_lock); return m_peers_gray.size();}
bool merge_peerlist(const std::list<peerlist_entry>& outer_bs);
bool get_peerlist_head(std::list<peerlist_entry>& bs_head, uint32_t depth = P2P_DEFAULT_PEERS_IN_HANDSHAKE);
bool get_peerlist_full(std::list<peerlist_entry>& pl_gray, std::list<peerlist_entry>& pl_white);
bool merge_peerlist(const std::vector<peerlist_entry>& outer_bs);
bool get_peerlist_head(std::vector<peerlist_entry>& bs_head, uint32_t depth = P2P_DEFAULT_PEERS_IN_HANDSHAKE);
bool get_peerlist_full(std::vector<peerlist_entry>& pl_gray, std::vector<peerlist_entry>& pl_white);
bool get_white_peer_by_index(peerlist_entry& p, size_t i);
bool get_gray_peer_by_index(peerlist_entry& p, size_t i);
bool append_with_peer_white(const peerlist_entry& pr);
@ -265,7 +265,7 @@ namespace nodetool
}
//--------------------------------------------------------------------------------------------------
inline
bool peerlist_manager::merge_peerlist(const std::list<peerlist_entry>& outer_bs)
bool peerlist_manager::merge_peerlist(const std::vector<peerlist_entry>& outer_bs)
{
CRITICAL_REGION_LOCAL(m_peerlist_lock);
for(const peerlist_entry& be: outer_bs)
@ -315,12 +315,13 @@ namespace nodetool
}
//--------------------------------------------------------------------------------------------------
inline
bool peerlist_manager::get_peerlist_head(std::list<peerlist_entry>& bs_head, uint32_t depth)
bool peerlist_manager::get_peerlist_head(std::vector<peerlist_entry>& bs_head, uint32_t depth)
{
CRITICAL_REGION_LOCAL(m_peerlist_lock);
peers_indexed::index<by_time>::type& by_time_index=m_peers_white.get<by_time>();
uint32_t cnt = 0;
bs_head.reserve(depth);
for(const peers_indexed::value_type& vl: boost::adaptors::reverse(by_time_index))
{
if(!vl.last_seen)
@ -335,16 +336,18 @@ namespace nodetool
}
//--------------------------------------------------------------------------------------------------
inline
bool peerlist_manager::get_peerlist_full(std::list<peerlist_entry>& pl_gray, std::list<peerlist_entry>& pl_white)
bool peerlist_manager::get_peerlist_full(std::vector<peerlist_entry>& pl_gray, std::vector<peerlist_entry>& pl_white)
{
CRITICAL_REGION_LOCAL(m_peerlist_lock);
peers_indexed::index<by_time>::type& by_time_index_gr=m_peers_gray.get<by_time>();
pl_gray.resize(pl_gray.size() + by_time_index_gr.size());
for(const peers_indexed::value_type& vl: boost::adaptors::reverse(by_time_index_gr))
{
pl_gray.push_back(vl);
}
peers_indexed::index<by_time>::type& by_time_index_wt=m_peers_white.get<by_time>();
pl_white.resize(pl_white.size() + by_time_index_wt.size());
for(const peers_indexed::value_type& vl: boost::adaptors::reverse(by_time_index_wt))
{
pl_white.push_back(vl);

@ -114,7 +114,7 @@ namespace nodetool
#pragma pack(pop)
inline
std::string print_peerlist_to_string(const std::list<peerlist_entry>& pl)
std::string print_peerlist_to_string(const std::vector<peerlist_entry>& pl)
{
time_t now_time = 0;
time(&now_time);
@ -189,7 +189,7 @@ namespace nodetool
{
basic_node_data node_data;
t_playload_type payload_data;
std::list<peerlist_entry> local_peerlist_new;
std::vector<peerlist_entry> local_peerlist_new;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(node_data)
@ -198,7 +198,7 @@ namespace nodetool
{
// saving: save both, so old and new peers can understand it
KV_SERIALIZE(local_peerlist_new)
std::list<peerlist_entry_base<network_address_old>> local_peerlist;
std::vector<peerlist_entry_base<network_address_old>> local_peerlist;
for (const auto &p: this_ref.local_peerlist_new)
{
if (p.adr.get_type_id() == epee::net_utils::ipv4_network_address::ID)
@ -217,7 +217,7 @@ namespace nodetool
// loading: load old list only if there is no new one
if (!epee::serialization::selector<is_store>::serialize(this_ref.local_peerlist_new, stg, hparent_section, "local_peerlist_new"))
{
std::list<peerlist_entry_base<network_address_old>> local_peerlist;
std::vector<peerlist_entry_base<network_address_old>> local_peerlist;
epee::serialization::selector<is_store>::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist");
for (const auto &p: local_peerlist)
((response&)this_ref).local_peerlist_new.push_back(peerlist_entry({epee::net_utils::ipv4_network_address(p.adr.ip, p.adr.port), p.id, p.last_seen}));
@ -248,7 +248,7 @@ namespace nodetool
{
uint64_t local_time;
t_playload_type payload_data;
std::list<peerlist_entry> local_peerlist_new;
std::vector<peerlist_entry> local_peerlist_new;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(local_time)
@ -257,7 +257,7 @@ namespace nodetool
{
// saving: save both, so old and new peers can understand it
KV_SERIALIZE(local_peerlist_new)
std::list<peerlist_entry_base<network_address_old>> local_peerlist;
std::vector<peerlist_entry_base<network_address_old>> local_peerlist;
for (const auto &p: this_ref.local_peerlist_new)
{
if (p.adr.get_type_id() == epee::net_utils::ipv4_network_address::ID)
@ -276,7 +276,7 @@ namespace nodetool
// loading: load old list only if there is no new one
if (!epee::serialization::selector<is_store>::serialize(this_ref.local_peerlist_new, stg, hparent_section, "local_peerlist_new"))
{
std::list<peerlist_entry_base<network_address_old>> local_peerlist;
std::vector<peerlist_entry_base<network_address_old>> local_peerlist;
epee::serialization::selector<is_store>::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist");
for (const auto &p: local_peerlist)
((response&)this_ref).local_peerlist_new.push_back(peerlist_entry({epee::net_utils::ipv4_network_address(p.adr.ip, p.adr.port), p.id, p.last_seen}));
@ -389,9 +389,9 @@ namespace nodetool
struct response
{
std::list<peerlist_entry> local_peerlist_white;
std::list<peerlist_entry> local_peerlist_gray;
std::list<connection_entry> connections_list;
std::vector<peerlist_entry> local_peerlist_white;
std::vector<peerlist_entry> local_peerlist_gray;
std::vector<connection_entry> connections_list;
peerid_type my_id;
uint64_t local_time;
BEGIN_KV_SERIALIZE_MAP()

@ -857,11 +857,11 @@ namespace cryptonote
bool core_rpc_server::on_get_peer_list(const COMMAND_RPC_GET_PEER_LIST::request& req, COMMAND_RPC_GET_PEER_LIST::response& res)
{
PERF_TIMER(on_get_peer_list);
std::list<nodetool::peerlist_entry> white_list;
std::list<nodetool::peerlist_entry> gray_list;
std::vector<nodetool::peerlist_entry> white_list;
std::vector<nodetool::peerlist_entry> gray_list;
m_p2p.get_peerlist_manager().get_peerlist_full(gray_list, white_list);
res.white_list.reserve(white_list.size());
for (auto & entry : white_list)
{
if (entry.adr.get_type_id() == epee::net_utils::ipv4_network_address::ID)
@ -871,6 +871,7 @@ namespace cryptonote
res.white_list.emplace_back(entry.id, entry.adr.str(), entry.last_seen);
}
res.gray_list.reserve(gray_list.size());
for (auto & entry : gray_list)
{
if (entry.adr.get_type_id() == epee::net_utils::ipv4_network_address::ID)

@ -2474,6 +2474,19 @@ bool simple_wallet::set_ignore_fractional_outputs(const std::vector<std::string>
return true;
}
bool simple_wallet::set_track_uses(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
const auto pwd_container = get_and_verify_password();
if (pwd_container)
{
parse_bool_and_use(args[1], [&](bool r) {
m_wallet->track_uses(r);
m_wallet->rewrite(m_wallet_file, pwd_container->password());
});
}
return true;
}
bool simple_wallet::set_device_name(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
const auto pwd_container = get_and_verify_password();
@ -3031,6 +3044,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
success_msg_writer() << "subaddress-lookahead = " << lookahead.first << ":" << lookahead.second;
success_msg_writer() << "segregation-height = " << m_wallet->segregation_height();
success_msg_writer() << "ignore-fractional-outputs = " << m_wallet->ignore_fractional_outputs();
success_msg_writer() << "track-uses = " << m_wallet->track_uses();
success_msg_writer() << "device_name = " << m_wallet->device_name();
return true;
}
@ -3087,6 +3101,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
CHECK_SIMPLE_VARIABLE("subaddress-lookahead", set_subaddress_lookahead, tr("<major>:<minor>"));
CHECK_SIMPLE_VARIABLE("segregation-height", set_segregation_height, tr("unsigned integer"));
CHECK_SIMPLE_VARIABLE("ignore-fractional-outputs", set_ignore_fractional_outputs, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("track-uses", set_track_uses, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("device-name", set_device_name, tr("<device_name[:device_spec]>"));
}
fail_msg_writer() << tr("set: unrecognized argument(s)");
@ -4814,6 +4829,7 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args
bool filter = false;
bool available = false;
bool verbose = false;
bool uses = false;
if (local_args.size() > 0)
{
if (local_args[0] == "available")
@ -4829,12 +4845,22 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args
local_args.erase(local_args.begin());
}
}
if (local_args.size() > 0 && local_args[0] == "verbose")
while (local_args.size() > 0)
{
verbose = true;
if (local_args[0] == "verbose")
verbose = true;
else if (local_args[0] == "uses")
uses = true;
else
{
fail_msg_writer() << tr("Invalid keyword: ") << local_args.front();
break;
}
local_args.erase(local_args.begin());
}
const uint64_t blockchain_height = m_wallet->get_blockchain_current_height();
PAUSE_READLINE();
std::set<uint32_t> subaddr_indices;
@ -4868,9 +4894,16 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args
verbose_string = (boost::format("%68s%68s") % tr("pubkey") % tr("key image")).str();
message_writer() << boost::format("%21s%8s%12s%8s%16s%68s%16s%s") % tr("amount") % tr("spent") % tr("unlocked") % tr("ringct") % tr("global index") % tr("tx id") % tr("addr index") % verbose_string;
}
std::string verbose_string;
std::string extra_string;
if (verbose)
verbose_string = (boost::format("%68s%68s") % td.get_public_key() % (td.m_key_image_known ? epee::string_tools::pod_to_hex(td.m_key_image) : td.m_key_image_partial ? (epee::string_tools::pod_to_hex(td.m_key_image) + "/p") : std::string(64, '?'))).str();
extra_string += (boost::format("%68s%68s") % td.get_public_key() % (td.m_key_image_known ? epee::string_tools::pod_to_hex(td.m_key_image) : td.m_key_image_partial ? (epee::string_tools::pod_to_hex(td.m_key_image) + "/p") : std::string(64, '?'))).str();
if (uses)
{
std::vector<uint64_t> heights;
for (const auto &e: td.m_uses) heights.push_back(e.first);
const std::pair<std::string, std::string> line = show_outputs_line(heights, blockchain_height, td.m_spent_height);
extra_string += tr("Heights: ") + line.first + "\n" + line.second;
}
message_writer(td.m_spent ? console_color_magenta : console_color_green, false) <<
boost::format("%21s%8s%12s%8s%16u%68s%16u%s") %
print_money(td.amount()) %
@ -4880,7 +4913,7 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args
td.m_global_output_index %
td.m_txid %
td.m_subaddr_index.minor %
verbose_string;
extra_string;
++transfers_found;
}
}
@ -4978,6 +5011,33 @@ bool simple_wallet::rescan_spent(const std::vector<std::string> &args)
return true;
}
//----------------------------------------------------------------------------------------------------
std::pair<std::string, std::string> simple_wallet::show_outputs_line(const std::vector<uint64_t> &heights, uint64_t blockchain_height, uint64_t highlight_height) const
{
std::stringstream ostr;
for (uint64_t h: heights)
blockchain_height = std::max(blockchain_height, h);
for (size_t j = 0; j < heights.size(); ++j)
ostr << (heights[j] == highlight_height ? " *" : " ") << heights[j];
// visualize the distribution, using the code by moneroexamples onion-monero-viewer
const uint64_t resolution = 79;
std::string ring_str(resolution, '_');
for (size_t j = 0; j < heights.size(); ++j)
{
uint64_t pos = (heights[j] * resolution) / blockchain_height;
ring_str[pos] = 'o';
}
if (highlight_height < blockchain_height)
{
uint64_t pos = (highlight_height * resolution) / blockchain_height;
ring_str[pos] = '*';
}
return std::make_pair(ostr.str(), ring_str);
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::print_ring_members(const std::vector<tools::wallet2::pending_tx>& ptx_vector, std::ostream& ostr)
{
uint32_t version;
@ -5048,21 +5108,18 @@ bool simple_wallet::print_ring_members(const std::vector<tools::wallet2::pending
}
}
ostr << tr("\nOriginating block heights: ");
for (size_t j = 0; j < absolute_offsets.size(); ++j)
ostr << tr(j == source.real_output ? " *" : " ") << res.outs[j].height;
spent_key_height[i] = res.outs[source.real_output].height;
spent_key_txid [i] = res.outs[source.real_output].txid;
// visualize the distribution, using the code by moneroexamples onion-monero-viewer
const uint64_t resolution = 79;
std::string ring_str(resolution, '_');
std::vector<uint64_t> heights(absolute_offsets.size(), 0);
uint64_t highlight_height = std::numeric_limits<uint64_t>::max();
for (size_t j = 0; j < absolute_offsets.size(); ++j)
{
uint64_t pos = (res.outs[j].height * resolution) / blockchain_height;
ring_str[pos] = 'o';
heights[j] = res.outs[j].height;
if (j == source.real_output)
highlight_height = heights[j];
}
uint64_t pos = (res.outs[source.real_output].height * resolution) / blockchain_height;
ring_str[pos] = '*';
ostr << tr("\n|") << ring_str << tr("|\n");
std::pair<std::string, std::string> ring_str = show_outputs_line(heights, highlight_height);
ostr << ring_str.first << tr("\n|") << ring_str.second << tr("|\n");
}
// warn if rings contain keys originating from the same tx or temporally very close block heights
bool are_keys_from_same_tx = false;
@ -6268,8 +6325,18 @@ bool simple_wallet::donate(const std::vector<std::string> &args_)
local_args.pop_back();
}
// get amount and pop
amount_str = local_args.back();
local_args.pop_back();
uint64_t amount;
bool ok = cryptonote::parse_amount(amount, local_args.back());
if (ok && amount != 0)
{
amount_str = local_args.back();
local_args.pop_back();
}
else
{
fail_msg_writer() << tr("amount is wrong: ") << local_args.back() << ", " << tr("expected number from 0 to ") << print_money(std::numeric_limits<uint64_t>::max());
return true;
}
// push back address, amount, payment id
std::string address_str;
if (m_wallet->nettype() != cryptonote::MAINNET)

@ -142,6 +142,7 @@ namespace cryptonote
bool set_subaddress_lookahead(const std::vector<std::string> &args = std::vector<std::string>());
bool set_segregation_height(const std::vector<std::string> &args = std::vector<std::string>());
bool set_ignore_fractional_outputs(const std::vector<std::string> &args = std::vector<std::string>());
bool set_track_uses(const std::vector<std::string> &args = std::vector<std::string>());
bool set_device_name(const std::vector<std::string> &args = std::vector<std::string>());
bool help(const std::vector<std::string> &args = std::vector<std::string>());
bool help_advanced(const std::vector<std::string> &args = std::vector<std::string>());
@ -249,6 +250,7 @@ namespace cryptonote
bool print_seed(bool encrypted);
void key_images_sync_intern();
void on_refresh_finished(uint64_t start_height, uint64_t fetched_blocks, bool is_init, bool received_money);
std::pair<std::string, std::string> show_outputs_line(const std::vector<uint64_t> &heights, uint64_t blockchain_height, uint64_t highlight_height = std::numeric_limits<uint64_t>::max()) const;
struct transfer_view
{

@ -139,6 +139,12 @@ if (BUILD_GUI_DEPS)
endif()
install(TARGETS wallet_merged
ARCHIVE DESTINATION ${lib_folder})
install(FILES ${TREZOR_DEP_LIBS}
DESTINATION ${lib_folder})
file(WRITE "trezor_link_flags.txt" ${TREZOR_DEP_LINKER})
install(FILES "trezor_link_flags.txt"
DESTINATION ${lib_folder})
endif()
add_subdirectory(api)

@ -1141,7 +1141,7 @@ std::string WalletImpl::getSubaddressLabel(uint32_t accountIndex, uint32_t addre
}
catch (const std::exception &e)
{
LOG_ERROR("Error getting subaddress label: ") << e.what();
LOG_ERROR("Error getting subaddress label: " << e.what());
setStatusError(string(tr("Failed to get subaddress label: ")) + e.what());
return "";
}
@ -1154,7 +1154,7 @@ void WalletImpl::setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex
}
catch (const std::exception &e)
{
LOG_ERROR("Error setting subaddress label: ") << e.what();
LOG_ERROR("Error setting subaddress label: " << e.what());
setStatusError(string(tr("Failed to set subaddress label: ")) + e.what());
}
}
@ -1171,7 +1171,7 @@ string WalletImpl::getMultisigInfo() const {
clearStatus();
return m_wallet->get_multisig_info();
} catch (const exception& e) {
LOG_ERROR("Error on generating multisig info: ") << e.what();
LOG_ERROR("Error on generating multisig info: " << e.what());
setStatusError(string(tr("Failed to get multisig info: ")) + e.what());
}
@ -1188,7 +1188,7 @@ string WalletImpl::makeMultisig(const vector<string>& info, uint32_t threshold)
return m_wallet->make_multisig(epee::wipeable_string(m_password), info, threshold);
} catch (const exception& e) {
LOG_ERROR("Error on making multisig wallet: ") << e.what();
LOG_ERROR("Error on making multisig wallet: " << e.what());
setStatusError(string(tr("Failed to make multisig: ")) + e.what());
}
@ -1202,7 +1202,7 @@ std::string WalletImpl::exchangeMultisigKeys(const std::vector<std::string> &inf
return m_wallet->exchange_multisig_keys(epee::wipeable_string(m_password), info);
} catch (const exception& e) {
LOG_ERROR("Error on exchanging multisig keys: ") << e.what();
LOG_ERROR("Error on exchanging multisig keys: " << e.what());
setStatusError(string(tr("Failed to make multisig: ")) + e.what());
}
@ -1220,7 +1220,7 @@ bool WalletImpl::finalizeMultisig(const vector<string>& extraMultisigInfo) {
setStatusError(tr("Failed to finalize multisig wallet creation"));
} catch (const exception& e) {
LOG_ERROR("Error on finalizing multisig wallet creation: ") << e.what();
LOG_ERROR("Error on finalizing multisig wallet creation: " << e.what());
setStatusError(string(tr("Failed to finalize multisig wallet creation: ")) + e.what());
}
@ -1236,7 +1236,7 @@ bool WalletImpl::exportMultisigImages(string& images) {
images = epee::string_tools::buff_to_hex_nodelimer(blob);
return true;
} catch (const exception& e) {
LOG_ERROR("Error on exporting multisig images: ") << e.what();
LOG_ERROR("Error on exporting multisig images: " << e.what());
setStatusError(string(tr("Failed to export multisig images: ")) + e.what());
}
@ -1264,7 +1264,7 @@ size_t WalletImpl::importMultisigImages(const vector<string>& images) {
return m_wallet->import_multisig(blobs);
} catch (const exception& e) {
LOG_ERROR("Error on importing multisig images: ") << e.what();
LOG_ERROR("Error on importing multisig images: " << e.what());
setStatusError(string(tr("Failed to import multisig images: ")) + e.what());
}
@ -1278,7 +1278,7 @@ bool WalletImpl::hasMultisigPartialKeyImages() const {
return m_wallet->has_multisig_partial_key_images();
} catch (const exception& e) {
LOG_ERROR("Error on checking for partial multisig key images: ") << e.what();
LOG_ERROR("Error on checking for partial multisig key images: " << e.what());
setStatusError(string(tr("Failed to check for partial multisig key images: ")) + e.what());
}
@ -1306,7 +1306,7 @@ PendingTransaction* WalletImpl::restoreMultisigTransaction(const string& signDat
return ptx;
} catch (exception& e) {
LOG_ERROR("Error on restoring multisig transaction: ") << e.what();
LOG_ERROR("Error on restoring multisig transaction: " << e.what());
setStatusError(string(tr("Failed to restore multisig transaction: ")) + e.what());
}

@ -125,7 +125,7 @@ void message_store::set_signer(const multisig_wallet_state &state,
const boost::optional<std::string> &transport_address,
const boost::optional<cryptonote::account_public_address> monero_address)
{
THROW_WALLET_EXCEPTION_IF(index >= m_num_authorized_signers, tools::error::wallet_internal_error, "Invalid signer index " + index);
THROW_WALLET_EXCEPTION_IF(index >= m_num_authorized_signers, tools::error::wallet_internal_error, "Invalid signer index " + std::to_string(index));
authorized_signer &m = m_signers[index];
if (label)
{
@ -146,7 +146,7 @@ void message_store::set_signer(const multisig_wallet_state &state,
const authorized_signer &message_store::get_signer(uint32_t index) const
{
THROW_WALLET_EXCEPTION_IF(index >= m_num_authorized_signers, tools::error::wallet_internal_error, "Invalid signer index " + index);
THROW_WALLET_EXCEPTION_IF(index >= m_num_authorized_signers, tools::error::wallet_internal_error, "Invalid signer index " + std::to_string(index));
return m_signers[index];
}
@ -201,7 +201,7 @@ void message_store::unpack_signer_config(const multisig_wallet_state &state, con
THROW_WALLET_EXCEPTION_IF(true, tools::error::wallet_internal_error, "Invalid structure of signer config");
}
uint32_t num_signers = (uint32_t)signers.size();
THROW_WALLET_EXCEPTION_IF(num_signers != m_num_authorized_signers, tools::error::wallet_internal_error, "Wrong number of signers in config: " + num_signers);
THROW_WALLET_EXCEPTION_IF(num_signers != m_num_authorized_signers, tools::error::wallet_internal_error, "Wrong number of signers in config: " + std::to_string(num_signers));
}
void message_store::process_signer_config(const multisig_wallet_state &state, const std::string &signer_config)
@ -424,7 +424,7 @@ void message_store::setup_signer_for_auto_config(uint32_t index, const std::stri
// auto-config parameters. In the wallet of somebody using the token to send auto-config
// data the auto-config parameters are stored in the "me" signer and taken from there
// to send that data.
THROW_WALLET_EXCEPTION_IF(index >= m_num_authorized_signers, tools::error::wallet_internal_error, "Invalid signer index " + index);
THROW_WALLET_EXCEPTION_IF(index >= m_num_authorized_signers, tools::error::wallet_internal_error, "Invalid signer index " + std::to_string(index));
authorized_signer &m = m_signers[index];
m.auto_config_token = token;
crypto::hash_to_scalar(token.data(), token.size(), m.auto_config_secret_key);
@ -506,7 +506,7 @@ void message_store::process_wallet_created_data(const multisig_wallet_state &sta
break;
default:
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, "Illegal message type " + (uint32_t)type);
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, "Illegal message type " + std::to_string((uint32_t)type));
break;
}
}
@ -573,7 +573,7 @@ size_t message_store::get_message_index_by_id(uint32_t id) const
{
size_t index;
bool found = get_message_index_by_id(id, index);
THROW_WALLET_EXCEPTION_IF(!found, tools::error::wallet_internal_error, "Invalid message id " + id);
THROW_WALLET_EXCEPTION_IF(!found, tools::error::wallet_internal_error, "Invalid message id " + std::to_string(id));
return index;
}
@ -601,7 +601,7 @@ message message_store::get_message_by_id(uint32_t id) const
{
message m;
bool found = get_message_by_id(id, m);
THROW_WALLET_EXCEPTION_IF(!found, tools::error::wallet_internal_error, "Invalid message id " + id);
THROW_WALLET_EXCEPTION_IF(!found, tools::error::wallet_internal_error, "Invalid message id " + std::to_string(id));
return m;
}

@ -894,6 +894,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended):
m_key_reuse_mitigation2(false),
m_segregation_height(0),
m_ignore_fractional_outputs(true),
m_track_uses(false),
m_is_initialized(false),
m_kdf_rounds(kdf_rounds),
is_old_file_format(false),
@ -1448,8 +1449,9 @@ void wallet2::cache_tx_data(const cryptonote::transaction& tx, const crypto::has
}
}
//----------------------------------------------------------------------------------------------------
void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen, const tx_cache_data &tx_cache_data)
void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen, const tx_cache_data &tx_cache_data, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache)
{
PERF_TIMER(process_new_transaction);
// In this function, tx (probably) only contains the base information
// (that is, the prunable stuff may or may not be included)
if (!miner_tx && !pool)
@ -1686,6 +1688,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
if (!m_multisig && !m_watch_only)
m_key_images[td.m_key_image] = m_transfers.size()-1;
m_pub_keys[tx_scan_info[o].in_ephemeral.pub] = m_transfers.size()-1;
if (output_tracker_cache)
(*output_tracker_cache)[std::make_pair(tx.vout[o].amount, td.m_global_output_index)] = m_transfers.size() - 1;
if (m_multisig)
{
THROW_WALLET_EXCEPTION_IF(!m_multisig_rescan_k && m_multisig_rescan_info,
@ -1751,6 +1755,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
td.m_mask = rct::identity();
td.m_rct = false;
}
if (output_tracker_cache)
(*output_tracker_cache)[std::make_pair(tx.vout[o].amount, td.m_global_output_index)] = kit->second;
if (m_multisig)
{
THROW_WALLET_EXCEPTION_IF(!m_multisig_rescan_k && m_multisig_rescan_info,
@ -1782,11 +1788,12 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
{
if(in.type() != typeid(cryptonote::txin_to_key))
continue;
auto it = m_key_images.find(boost::get<cryptonote::txin_to_key>(in).k_image);
const cryptonote::txin_to_key &in_to_key = boost::get<cryptonote::txin_to_key>(in);
auto it = m_key_images.find(in_to_key.k_image);
if(it != m_key_images.end())
{
transfer_details& td = m_transfers[it->second];
uint64_t amount = boost::get<cryptonote::txin_to_key>(in).amount;
uint64_t amount = in_to_key.amount;
if (amount > 0)
{
if(amount != td.amount())
@ -1817,6 +1824,34 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
m_callback->on_money_spent(height, txid, tx, amount, tx, td.m_subaddr_index);
}
}
if (!pool && m_track_uses)
{
PERF_TIMER(track_uses);
const uint64_t amount = in_to_key.amount;
std::vector<uint64_t> offsets = cryptonote::relative_output_offsets_to_absolute(in_to_key.key_offsets);
if (output_tracker_cache)
{
for (uint64_t offset: offsets)
{
const std::map<std::pair<uint64_t, uint64_t>, size_t>::const_iterator i = output_tracker_cache->find(std::make_pair(amount, offset));
if (i != output_tracker_cache->end())
{
size_t idx = i->second;
THROW_WALLET_EXCEPTION_IF(idx >= m_transfers.size(), error::wallet_internal_error, "Output tracker cache index out of range");
m_transfers[idx].m_uses.push_back(std::make_pair(height, txid));
}
}
}
else for (transfer_details &td: m_transfers)
{
if (amount != in_to_key.amount)
continue;
for (uint64_t offset: offsets)
if (offset == td.m_global_output_index)
td.m_uses.push_back(std::make_pair(height, txid));
}
}
}
uint64_t fee = miner_tx ? 0 : tx.version == 1 ? tx_money_spent_in_ins - get_outs_money_amount(tx) : tx.rct_signatures.txnFee;
@ -1999,7 +2034,7 @@ void wallet2::process_outgoing(const crypto::hash &txid, const cryptonote::trans
add_rings(tx);
}
//----------------------------------------------------------------------------------------------------
void wallet2::process_new_blockchain_entry(const cryptonote::block& b, const cryptonote::block_complete_entry& bche, const parsed_block &parsed_block, const crypto::hash& bl_id, uint64_t height, const std::vector<tx_cache_data> &tx_cache_data, size_t tx_cache_data_offset)
void wallet2::process_new_blockchain_entry(const cryptonote::block& b, const cryptonote::block_complete_entry& bche, const parsed_block &parsed_block, const crypto::hash& bl_id, uint64_t height, const std::vector<tx_cache_data> &tx_cache_data, size_t tx_cache_data_offset, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache)
{
THROW_WALLET_EXCEPTION_IF(bche.txs.size() + 1 != parsed_block.o_indices.indices.size(), error::wallet_internal_error,
"block transactions=" + std::to_string(bche.txs.size()) +
@ -2012,7 +2047,7 @@ void wallet2::process_new_blockchain_entry(const cryptonote::block& b, const cry
{
TIME_MEASURE_START(miner_tx_handle_time);
if (m_refresh_type != RefreshNoCoinbase)
process_new_transaction(get_transaction_hash(b.miner_tx), b.miner_tx, parsed_block.o_indices.indices[0].indices, height, b.timestamp, true, false, false, tx_cache_data[tx_cache_data_offset]);
process_new_transaction(get_transaction_hash(b.miner_tx), b.miner_tx, parsed_block.o_indices.indices[0].indices, height, b.timestamp, true, false, false, tx_cache_data[tx_cache_data_offset], output_tracker_cache);
++tx_cache_data_offset;
TIME_MEASURE_FINISH(miner_tx_handle_time);
@ -2021,7 +2056,7 @@ void wallet2::process_new_blockchain_entry(const cryptonote::block& b, const cry
THROW_WALLET_EXCEPTION_IF(bche.txs.size() != parsed_block.txes.size(), error::wallet_internal_error, "Wrong amount of transactions for block");
for (size_t idx = 0; idx < b.tx_hashes.size(); ++idx)
{
process_new_transaction(b.tx_hashes[idx], parsed_block.txes[idx], parsed_block.o_indices.indices[idx+1].indices, height, b.timestamp, false, false, false, tx_cache_data[tx_cache_data_offset++]);
process_new_transaction(b.tx_hashes[idx], parsed_block.txes[idx], parsed_block.o_indices.indices[idx+1].indices, height, b.timestamp, false, false, false, tx_cache_data[tx_cache_data_offset++], output_tracker_cache);
}
TIME_MEASURE_FINISH(txs_handle_time);
m_last_block_reward = cryptonote::get_outs_money_amount(b.miner_tx);
@ -2119,7 +2154,7 @@ void wallet2::pull_hashes(uint64_t start_height, uint64_t &blocks_start_height,
hashes = std::move(res.m_block_ids);
}
//----------------------------------------------------------------------------------------------------
void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector<cryptonote::block_complete_entry> &blocks, const std::vector<parsed_block> &parsed_blocks, uint64_t& blocks_added)
void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector<cryptonote::block_complete_entry> &blocks, const std::vector<parsed_block> &parsed_blocks, uint64_t& blocks_added, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache)
{
size_t current_index = start_height;
blocks_added = 0;
@ -2226,7 +2261,7 @@ void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector<cry
if(current_index >= m_blockchain.size())
{
process_new_blockchain_entry(bl, blocks[i], parsed_blocks[i], bl_id, current_index, tx_cache_data, tx_cache_data_offset);
process_new_blockchain_entry(bl, blocks[i], parsed_blocks[i], bl_id, current_index, tx_cache_data, tx_cache_data_offset, output_tracker_cache);
++blocks_added;
}
else if(bl_id != m_blockchain[current_index])
@ -2238,7 +2273,7 @@ void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector<cry
string_tools::pod_to_hex(m_blockchain[current_index]));
detach_blockchain(current_index);
process_new_blockchain_entry(bl, blocks[i], parsed_blocks[i], bl_id, current_index, tx_cache_data, tx_cache_data_offset);
process_new_blockchain_entry(bl, blocks[i], parsed_blocks[i], bl_id, current_index, tx_cache_data, tx_cache_data_offset, output_tracker_cache);
}
else
{
@ -2670,6 +2705,17 @@ bool wallet2::delete_address_book_row(std::size_t row_id) {
return true;
}
//----------------------------------------------------------------------------------------------------
std::shared_ptr<std::map<std::pair<uint64_t, uint64_t>, size_t>> wallet2::create_output_tracker_cache() const
{
std::shared_ptr<std::map<std::pair<uint64_t, uint64_t>, size_t>> cache{new std::map<std::pair<uint64_t, uint64_t>, size_t>()};
for (size_t i = 0; i < m_transfers.size(); ++i)
{
const transfer_details &td = m_transfers[i];
(*cache)[std::make_pair(td.is_rct() ? 0 : td.amount(), td.m_global_output_index)] = i;
}
return cache;
}
//----------------------------------------------------------------------------------------------------
void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blocks_fetched, bool& received_money)
{
@ -2717,6 +2763,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
std::vector<cryptonote::block_complete_entry> blocks;
std::vector<parsed_block> parsed_blocks;
bool refreshed = false;
std::shared_ptr<std::map<std::pair<uint64_t, uint64_t>, size_t>> output_tracker_cache;
// pull the first set of blocks
get_short_chain_history(short_chain_history, (m_first_refresh_done || trusted_daemon) ? 1 : FIRST_REFRESH_GRANULARITY);
@ -2770,7 +2817,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
{
try
{
process_parsed_blocks(blocks_start_height, blocks, parsed_blocks, added_blocks);
process_parsed_blocks(blocks_start_height, blocks, parsed_blocks, added_blocks, output_tracker_cache.get());
}
catch (const tools::error::out_of_hashchain_bounds_error&)
{
@ -2813,6 +2860,11 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
throw std::runtime_error("proxy exception in refresh thread");
}
// if we've got at least 10 blocks to refresh, assume we're starting
// a long refresh, and setup a tracking output cache if we need to
if (m_track_uses && !output_tracker_cache && next_blocks.size() >= 10)
output_tracker_cache = create_output_tracker_cache();
// switch to the new blocks from the daemon
blocks_start_height = next_blocks_start_height;
blocks = std::move(next_blocks);
@ -3182,6 +3234,9 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
value2.SetInt(m_ignore_fractional_outputs ? 1 : 0);
json.AddMember("ignore_fractional_outputs", value2, json.GetAllocator());
value2.SetInt(m_track_uses ? 1 : 0);
json.AddMember("track_uses", value2, json.GetAllocator());
value2.SetUint(m_subaddress_lookahead_major);
json.AddMember("subaddress_lookahead_major", value2, json.GetAllocator());
@ -3328,6 +3383,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
m_key_reuse_mitigation2 = true;
m_segregation_height = 0;
m_ignore_fractional_outputs = true;
m_track_uses = false;
m_subaddress_lookahead_major = SUBADDRESS_LOOKAHEAD_MAJOR;
m_subaddress_lookahead_minor = SUBADDRESS_LOOKAHEAD_MINOR;
m_original_keys_available = false;
@ -3480,6 +3536,8 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
m_segregation_height = field_segregation_height;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, ignore_fractional_outputs, int, Int, false, true);
m_ignore_fractional_outputs = field_ignore_fractional_outputs;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, track_uses, int, Int, false, false);
m_track_uses = field_track_uses;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, subaddress_lookahead_major, uint32_t, Uint, false, SUBADDRESS_LOOKAHEAD_MAJOR);
m_subaddress_lookahead_major = field_subaddress_lookahead_major;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, subaddress_lookahead_minor, uint32_t, Uint, false, SUBADDRESS_LOOKAHEAD_MINOR);
@ -5266,6 +5324,10 @@ void wallet2::rescan_blockchain(bool hard, bool refresh)
m_transfers.clear();
m_key_images.clear();
m_pub_keys.clear();
m_unconfirmed_txs.clear();
m_payments.clear();
m_confirmed_txs.clear();
m_unconfirmed_payments.clear();
m_scanned_pool_txs[0].clear();
m_scanned_pool_txs[1].clear();

@ -273,6 +273,7 @@ namespace tools
bool m_key_image_partial;
std::vector<rct::key> m_multisig_k;
std::vector<multisig_info> m_multisig_info; // one per other participant
std::vector<std::pair<uint64_t, crypto::hash>> m_uses;
bool is_rct() const { return m_rct; }
uint64_t amount() const { return m_amount; }
@ -297,6 +298,7 @@ namespace tools
FIELD(m_key_image_partial)
FIELD(m_multisig_k)
FIELD(m_multisig_info)
FIELD(m_uses)
END_SERIALIZE()
};
@ -984,6 +986,8 @@ namespace tools
void ignore_fractional_outputs(bool value) { m_ignore_fractional_outputs = value; }
bool confirm_non_default_ring_size() const { return m_confirm_non_default_ring_size; }
void confirm_non_default_ring_size(bool always) { m_confirm_non_default_ring_size = always; }
bool track_uses() const { return m_track_uses; }
void track_uses(bool value) { m_track_uses = value; }
const std::string & device_name() const { return m_device_name; }
void device_name(const std::string & device_name) { m_device_name = device_name; }
const std::string & device_derivation_path() const { return m_device_derivation_path; }
@ -1249,8 +1253,8 @@ namespace tools
* \param password Password of wallet file
*/
bool load_keys(const std::string& keys_file_name, const epee::wipeable_string& password);
void process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen, const tx_cache_data &tx_cache_data);
void process_new_blockchain_entry(const cryptonote::block& b, const cryptonote::block_complete_entry& bche, const parsed_block &parsed_block, const crypto::hash& bl_id, uint64_t height, const std::vector<tx_cache_data> &tx_cache_data, size_t tx_cache_data_offset);
void process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen, const tx_cache_data &tx_cache_data, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache = NULL);
void process_new_blockchain_entry(const cryptonote::block& b, const cryptonote::block_complete_entry& bche, const parsed_block &parsed_block, const crypto::hash& bl_id, uint64_t height, const std::vector<tx_cache_data> &tx_cache_data, size_t tx_cache_data_offset, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache = NULL);
void detach_blockchain(uint64_t height);
void get_short_chain_history(std::list<crypto::hash>& ids, uint64_t granularity = 1) const;
bool clear();
@ -1258,7 +1262,7 @@ namespace tools
void pull_hashes(uint64_t start_height, uint64_t& blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::vector<crypto::hash> &hashes);
void fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, bool force = false);
void pull_and_parse_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, const std::vector<cryptonote::block_complete_entry> &prev_blocks, const std::vector<parsed_block> &prev_parsed_blocks, std::vector<cryptonote::block_complete_entry> &blocks, std::vector<parsed_block> &parsed_blocks, bool &error);
void process_parsed_blocks(uint64_t start_height, const std::vector<cryptonote::block_complete_entry> &blocks, const std::vector<parsed_block> &parsed_blocks, uint64_t& blocks_added);
void process_parsed_blocks(uint64_t start_height, const std::vector<cryptonote::block_complete_entry> &blocks, const std::vector<parsed_block> &parsed_blocks, uint64_t& blocks_added, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache = NULL);
uint64_t select_transfers(uint64_t needed_money, std::vector<size_t> unused_transfers_indices, std::vector<size_t>& selected_transfers) const;
bool prepare_file_names(const std::string& file_path);
void process_unconfirmed(const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t height);
@ -1312,6 +1316,7 @@ namespace tools
std::unordered_set<crypto::public_key> &pkeys) const;
void cache_tx_data(const cryptonote::transaction& tx, const crypto::hash &txid, tx_cache_data &tx_cache_data) const;
std::shared_ptr<std::map<std::pair<uint64_t, uint64_t>, size_t>> create_output_tracker_cache() const;
void setup_new_blockchain();
void create_keys_file(const std::string &wallet_, bool watch_only, const epee::wipeable_string &password, bool create_address_file);
@ -1395,6 +1400,7 @@ namespace tools
bool m_key_reuse_mitigation2;
uint64_t m_segregation_height;
bool m_ignore_fractional_outputs;
bool m_track_uses;
bool m_is_initialized;
NodeRPCProxy m_node_rpc_proxy;
std::unordered_set<crypto::hash> m_scanned_pool_txs[2];
@ -1444,7 +1450,7 @@ namespace tools
};
}
BOOST_CLASS_VERSION(tools::wallet2, 27)
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 10)
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 11)
BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1)
BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0)
BOOST_CLASS_VERSION(tools::wallet2::multisig_tx_set, 1)
@ -1593,6 +1599,9 @@ namespace boost
return;
}
a & x.m_key_image_requested;
if (ver < 11)
return;
a & x.m_uses;
}
template <class Archive>

@ -69,11 +69,22 @@ TEST(notify, works)
tools::Notify notify(spec.c_str());
notify.notify("1111111111111111111111111111111111111111111111111111111111111111");
epee::misc_utils::sleep_no_w(100);
std::string s;
ASSERT_TRUE(epee::file_io_utils::load_file_to_string(name_template, s));
ASSERT_TRUE(s == "1111111111111111111111111111111111111111111111111111111111111111");
bool ok = false;
for (int i = 0; i < 10; ++i)
{
epee::misc_utils::sleep_no_w(100);
std::string s;
if (epee::file_io_utils::load_file_to_string(name_template, s))
{
if (s == "1111111111111111111111111111111111111111111111111111111111111111")
{
ok = true;
break;
}
std::cout << "got: [" << s << "]" << std::endl;
}
}
boost::filesystem::remove(name_template);
ASSERT_TRUE(ok);
}

@ -42,7 +42,7 @@ TEST(peer_list, peer_list_general)
#define ADD_GRAY_NODE(addr_, id_, last_seen_) { nodetool::peerlist_entry ple; ple.last_seen=last_seen_;ple.adr = addr_; ple.id = id_;plm.append_with_peer_gray(ple);}
#define ADD_WHITE_NODE(addr_, id_, last_seen_) { nodetool::peerlist_entry ple;ple.last_seen=last_seen_; ple.adr = addr_; ple.id = id_;plm.append_with_peer_white(ple);}
#define PRINT_HEAD(step) {std::list<nodetool::peerlist_entry> bs_head; bool r = plm.get_peerlist_head(bs_head, 100);std::cout << "step " << step << ": " << bs_head.size() << std::endl;}
#define PRINT_HEAD(step) {std::vector<nodetool::peerlist_entry> bs_head; bool r = plm.get_peerlist_head(bs_head, 100);std::cout << "step " << step << ": " << bs_head.size() << std::endl;}
ADD_GRAY_NODE(MAKE_IPV4_ADDRESS(123,43,12,1, 8080), 121241, 34345);
ADD_GRAY_NODE(MAKE_IPV4_ADDRESS(123,43,12,2, 8080), 121241, 34345);
@ -58,7 +58,7 @@ TEST(peer_list, peer_list_general)
size_t gray_list_size = plm.get_gray_peers_count();
ASSERT_EQ(gray_list_size, 1);
std::list<nodetool::peerlist_entry> bs_head;
std::vector<nodetool::peerlist_entry> bs_head;
bool r = plm.get_peerlist_head(bs_head, 100);
std::cout << bs_head.size() << std::endl;
ASSERT_TRUE(r);
@ -78,7 +78,7 @@ TEST(peer_list, merge_peer_lists)
//ADD_NODE_TO_PL("\2", \3, 0x\1, (1353346618 -(\4*60*60*24+\5*60*60+\6*60+\7 )));\n
nodetool::peerlist_manager plm;
plm.init(false);
std::list<nodetool::peerlist_entry> outer_bs;
std::vector<nodetool::peerlist_entry> outer_bs;
#define ADD_NODE_TO_PL(ip_, port_, id_, timestamp_) { nodetool::peerlist_entry ple; epee::string_tools::get_ip_int32_from_string(ple.adr.ip, ip_); ple.last_seen = timestamp_; ple.adr.port = port_; ple.id = id_;outer_bs.push_back(ple);}

@ -89,11 +89,11 @@ public:
virtual uint64_t get_tx_block_height(const crypto::hash& h) const { return 0; }
virtual uint64_t get_num_outputs(const uint64_t& amount) const { return 1; }
virtual uint64_t get_indexing_base() const { return 0; }
virtual cryptonote::output_data_t get_output_key(const uint64_t& amount, const uint64_t& index) { return cryptonote::output_data_t(); }
virtual cryptonote::output_data_t get_output_key(const uint64_t& amount, const uint64_t& index) const { return cryptonote::output_data_t(); }
virtual cryptonote::tx_out_index get_output_tx_and_index_from_global(const uint64_t& index) const { return cryptonote::tx_out_index(); }
virtual cryptonote::tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index) const { return cryptonote::tx_out_index(); }
virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<cryptonote::tx_out_index> &indices) const {}
virtual void get_output_key(const epee::span<const uint64_t> &amounts, const std::vector<uint64_t> &offsets, std::vector<cryptonote::output_data_t> &outputs, bool allow_partial = false) {}
virtual void get_output_key(const epee::span<const uint64_t> &amounts, const std::vector<uint64_t> &offsets, std::vector<cryptonote::output_data_t> &outputs, bool allow_partial = false) const {}
virtual bool can_thread_bulk_indices() const { return false; }
virtual std::vector<uint64_t> get_tx_output_indices(const crypto::hash& h) const { return std::vector<uint64_t>(); }
virtual std::vector<uint64_t> get_tx_amount_output_indices(const uint64_t tx_index) const { return std::vector<uint64_t>(); }

@ -13,18 +13,18 @@ p7gDvxXOGxzq0sqfPTWTBdCj1OPfunHbbeH8ypwBlNpwVG40fJdya+Dqjwu25qX6
Xh5vxLzeJTBmlawa97MCliPvzzJgW9qHRVCa9lLloGVYLiUOS0N+dZ/r/QARAQAB
tD5tb25lcm9tb29vLW1vbmVybyA8bW9uZXJvbW9vby1tb25lcm9AdXNlcnMubm9y
ZXBseS5naXRodWIuY29tPokCPwQTAQIAKQIbAwcLCQgHAwIBBhUIAgkKCwQWAgMB
Ah4BAheABQJbof8TBQkLMcqRAAoJEGhvB0VNbO/DOrcP/1eG3gkIgq+lXKlv/lta
ZFl8jS5iQUwxTHv8s+O7pbL2mwKt5oM8QmXVMFLlaanENmH0y/DhWRYIYuKTifDN
tXOxENCZhxgjlVxAtnMdD2J8MJANzV2MYGLbGQeFAuZHIL2LMfvUENLYx/jJpe7f
93kXZoQio7rIolnlbM1QoJLxi/7HlOt/VsopJlV2wAmOmlpyWDnOZtUtZgiCGV6a
apFzTs2m3n2GP7+8PG/W01/jVyFqixGW8cWVZORBMhjro2JqrRvw7U+Ypk2o7Em4
SAnAJyzqpTDh9zf0QWkQXN83YThB3dk1M1FXOyKtZ8G+YVNfs5Ldr7tHNbqKi2v8
lPaPIDQ7UmxZhy9vraKss0/3AEXaiE2eSvLc4eCcLiS4yVQ2KJpK5TUvz3cP1D5C
USsjxUZvolUELBtNaRVAsxX6OAyA8FjwJ8AKCqyR0NHvrbYhj54N1Js8PWtb+qqk
5sBLKOwEPaWM1uG6SJabrY1xu2VNLOGdJA9bRfyyzfpXksD0lFgwLKki6ReqqoMS
QiVdymhcp55J4tFwsDkzJX7296d1x3r7GAIQMLNc7YizukWfNtvUkSUsAwp+RKUx
TTwkwL1ztzSRpt3hGMJ9SfULTaQD7YAYfz4kitMBNpm90CLFa4CeINu98gE9Ogmc
R+CGQOHLUC3rXubgRCiQg5wfuQINBFQym34BEADHtTHduZFdu76RAzqTjT94F92L
Ah4BAheABQJcEB4SBQkLn+mRAAoJEGhvB0VNbO/DzSIQALXk6ST5Uoxh5+NLBJgI
GR2NOCFwsU+97VOkZWZnzpk+JdUrq/I9JmWWTegGKu3it5YvM8xY1zD1l+RXlnmY
Bg7oT6N63lL8hBhxGm9Hk2A1VJlEjtgtvjbg5yLSdvjxJL1vrmchWGwFWoHT9uIh
oefemb3TQ1U+ADVsW42jXca650/rqvsUMpmQbDfHxUBIfpbxgTWz8sHuMfhFB3R0
nzSuZ1E1Pbg5jWYxd6sXpb1VFZ7TaQNVGB+4wMe8AH8/0qziLVTXvSkoer6qxU+r
e9M9/Rgue1FJSzZogUekIqyNLsvAeATSCYzi8NoywkUbAq6AqazJtdcOD+7M2/Vl
pdQEnIKSO/9xrziUQifRsPx4LOjf2d2Hvor/rBJYwoI1cFgR5pmH30Mi7OY0mMmm
2TMUPPz7YiVY+RPPpY3Mg5oPRe6sHVAdFYBmc0PTR4v92iYgfQXzoCd5HOJI9QB3
SwrKz7cNLQwob2za1AXZ3sUp+yok6QMt8Tk6xIbMAjeR4jVeP8iQHhiVS1zx5z/g
lCAfb0hJnykoANgIZvJR/L+tuZjVStqnXjHgreY3IjlWTaNjZ/X5uMvd6zivqI9a
aEmqw/ZDCXRMAtjUCpUvpNlqAgqqbQsx6MFDnMbd4BuKQONeAFLm/Rp31nIvt1vb
+Iu3vkXBbbjb5yMu/dcpgSRUuQINBFQym34BEADHtTHduZFdu76RAzqTjT94F92L
xSSopLSk7/sdLWTc2ERmjDId7dKmqrL1Kh2kqAtHY3Rq8Y839LGmbJCzI1kJyOHF
o9jkEI93sqXcztLjizPVukqClOZNt3NV/nvefH6JSdqWcnC4V1mQr2Ztl0j+51i+
NYVwGjlsOMlBER+LW/s7egRqAQonrcEB5vsSAzd8mOlNKjRAnDCV+C21GDKxzb80
@ -35,17 +35,17 @@ xRFfhoiiPyjjPRmJ+/iG3KXLzEiMfbyTFzGkX3Z9BJTxemUx8JOSVQXa++t4w39J
UwzwBKNItDhtQqJpCaF43fJ4ykLMJi5gRpgqtb+T3CF0abXNII1IfS8a0fSpd48d
6hzoCVqpvWsI1fOY5Ui0BIgubNhkr4OJDCWBT5zhxjCJ3QiUSKyyqjfw1Fpuf/0Y
CSA9Q9FSCq9qTppJs5ITHVjhWw2zxrJEG+P2+dvryBhV9l4T2xx1oHqlKX8zzLBG
kS8NmnxoRFQs5rZYvQARAQABiQIlBBgBAgAPAhsMBQJX3tl5BQkHbqT4AAoJEGhv
B0VNbO/DrN4QAJVTg2l91LSxb2dTikXbkRCPev1Eiqjd3d4TZIyE7yeYreHUyfcz
sytEsMUpd5nqqL/QMOwgC8Dm+77Yp480atI/c0wQh30EfJq1YP4q/gwv8EtriFo6
ZaqYNzajmB8otz6yyb5RD9S6ocZX5b22nnNM/ihiTQJiqJKC2XHPQH3/grniU9if
WXUlY7Fo+8lRn/aRPMjYT2elsugru8GoplDMyfPRymnMJmTwNPYkg0Dnm2JUXYhH
VLO6Ebh7fUChsiGNmSp+siv7fcZIf20+LvoymgyT+49LrrQMvRleOqaJc1LBKaK6
1yU+jLk1f9bFCMORQoTxvIVaSnjMWAeKDxi8nwuVfUJpQYXmbOOqMZgoFi6t+U7/
T6Cz1CGKv3JgEveWyHeOvsjopej3a4Hmk7QGM/xJrd83roUjypjx5lTeMDvcPlPs
IQOy33qWguR1xoEnwAp9ov/meS7HtUOoC0m9ROZqWT6ArN+1ONplFP4GTsuW91Qz
pacQMl09F0KF1MacAdpauCOKj+wy9XPUW8v3kWZufUSgNtOLHS+kVumkqdJuJ0aB
7Ezc1yYY6DwRFOdlUpTJkRMozyPRvS15Lz/vPEhcbxMHRAg611CS2CqTEIbk2chJ
QBlj77a45lDTXGQHFVYXlbXx/HWb5zOGpNji0QhY1hOABRo78DT5yda+
=ksQj
kS8NmnxoRFQs5rZYvQARAQABiQIlBBgBAgAPAhsMBQJcEB4eBQkLn+meAAoJEGhv
B0VNbO/DjzYP/2A6HtpvPkD+s/0+Ghmp5Rw7HIvZz0RnCsvM3qVQqVn3JTqHXyhD
5GmZrCxhliW1nRBITaKSRHXSGeE/O1BtK6eW/Z1P6bWJVd+R9vhaZlLU2sswiFzu
q3s7bL/Fo9VRc0SX6j6JDh1FZ3JcebUfY59sixHLqZuAk9m97z6H1NjS+f4pB5Tp
n1nnRgdvYk4tjlk4mmluIAwjq8Ll6gw6ntwjX9Gq9OblutTr2MZDyTIOxcG54ZN2
2t5JA7Syh0He6dn/NLlb//bPPnic3GuYfkgKht8M1XCJfnDKju+I9qRGf1DYIjP7
m24IDC0MM9Fo7KIUY+vcV0J/BIkkZtZ9xh0iEEnR/KqYXmClym+EiWCwPhLloKL3
6cZr5MaiYJsodYa73x35pSGvioUrBDb78v8nCNhoTUXzZv8E0s/0YI2UZSGhVEC6
ANNXPvKeOdibGNDM4JOwETabkEng38UE6Oa7Qonra2MWsPegh+mnZ7/sqrktQRMB
T/Xne6vapDONeLeY2hVcT0j9f/S8rgpHPjP4/hmYE9d38Euwa7TZ0lHWcmJzQy6F
7HfGR3oYAYAwRnvl+kYUGZ46u9Nodi4+wycFc4+IpwFtnlUzRBOcOilnR2X6KFJW
SiVss1i7ECcWaKCBNN1MrpwGWeuSbCQ00c3bxe6ZN6goB1t2u1KAZqMK
=HFHX
-----END PGP PUBLIC KEY BLOCK-----

Loading…
Cancel
Save