mirror of
https://git.wownero.com/wownero/wownero.git
synced 2025-01-06 20:48:53 +00:00
commit
d85d908ddc
@ -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,
|
||||
|
17
Dockerfile
17
Dockerfile
@ -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()
|
||||
|
43
cmake/test-protobuf.cpp
Normal file
43
cmake/test-protobuf.cpp
Normal file
@ -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;
|
||||
}
|
7
cmake/test-protobuf.proto
Normal file
7
cmake/test-protobuf.proto
Normal file
@ -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
|
||||
|
28
contrib/depends/packages/native_protobuf.mk
Normal file
28
contrib/depends/packages/native_protobuf.mk
Normal file
@ -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(¤t_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§ion=all&arch=any&searchon=names&keywords=g%2B%2B)
|
||||
# - libc version 2.11.3 (https://packages.debian.org/search?suite=default§ion=all&arch=any&searchon=names&keywords=libc6)
|
||||
# - libstdc++ version 4.4.5 (https://packages.debian.org/search?suite=default§ion=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§ion=all)
|
||||
# - libc version 2.11.1 (http://packages.ubuntu.com/search?keywords=libc6&searchon=names&suite=lucid§ion=all)
|
||||
# - libstdc++ version 4.4.3 (http://packages.ubuntu.com/search?suite=lucid§ion=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)
|
||||
|
||||
|
34
external/easylogging++/easylogging++.cc
vendored
34
external/easylogging++/easylogging++.cc
vendored
@ -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)) {
|
||||
|
4
external/easylogging++/easylogging++.h
vendored
4
external/easylogging++/easylogging++.h
vendored
@ -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
|
||||
|
98
src/common/compat/glibc_compat.cpp
Normal file
98
src/common/compat/glibc_compat.cpp
Normal file
@ -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…
Reference in New Issue
Block a user