mirror of https://github.com/oxen-io/oxen-core.git
merge dev branch with RPC/wallet3 changes
Incomplete, many things to fix, some annotated with a comment MERGEFIX
This commit is contained in:
commit
1311a20e9f
|
@ -6,7 +6,6 @@ local default_deps_nocxx = [
|
|||
'libevent-dev',
|
||||
'libgtest-dev',
|
||||
'libhidapi-dev',
|
||||
'libminiupnpc-dev',
|
||||
'libreadline-dev',
|
||||
'libsodium-dev',
|
||||
'libsqlite3-dev',
|
||||
|
@ -35,6 +34,7 @@ local submodules = {
|
|||
|
||||
local apt_get_quiet = 'apt-get -o=Dpkg::Use-Pty=0 -q';
|
||||
|
||||
local cmake_options(opts) = std.join(' ', [' -D' + o + '=' + (if opts[o] then 'ON' else 'OFF') for o in std.objectFields(opts)]) + ' ';
|
||||
|
||||
// Regular build on a debian-like system:
|
||||
local debian_pipeline(name,
|
||||
|
@ -74,15 +74,14 @@ local debian_pipeline(name,
|
|||
'mkdir build',
|
||||
'cd build',
|
||||
'cmake .. -G Ninja -DCMAKE_CXX_FLAGS=-fdiagnostics-color=always -DCMAKE_BUILD_TYPE=' + build_type + ' ' +
|
||||
'-DLOCAL_MIRROR=https://builds.lokinet.dev/deps -DUSE_LTO=' + (if lto then 'ON ' else 'OFF ') +
|
||||
(if werror then '-DWARNINGS_AS_ERRORS=ON ' else '') +
|
||||
(if build_tests || run_tests then '-DBUILD_TESTS=ON ' else '') +
|
||||
cmake_extra,
|
||||
'-DLOCAL_MIRROR=https://builds.lokinet.dev/deps '
|
||||
+ cmake_options({ USE_LTO: lto, WARNINGS_AS_ERRORS: werror, BUILD_TESTS: build_tests || run_tests })
|
||||
+ cmake_extra,
|
||||
] + (
|
||||
if arch == 'arm64' && jobs > 1 then
|
||||
// The wallet code is too bloated to be compiled at -j2 with only 4GB ram, so do
|
||||
// the huge bloated jobs at -j1 and the rest at -j2
|
||||
['ninja -j1 rpc wallet -v', 'ninja -j2 daemon device_trezor -v', 'ninja -j1 wallet_rpc_server -v', 'ninja -j2 -v']
|
||||
['ninja -j1 rpc wallet -v', 'ninja -j2 daemon -v', 'ninja -j1 wallet_rpc_server -v', 'ninja -j2 -v']
|
||||
else
|
||||
['ninja -j' + jobs + ' -v']
|
||||
) + (
|
||||
|
@ -178,7 +177,7 @@ local android_build_steps(android_abi, android_platform=21, jobs=6, cmake_extra=
|
|||
'-DCMAKE_BUILD_TYPE=Release ' +
|
||||
'-DCMAKE_TOOLCHAIN_FILE=/usr/lib/android-sdk/ndk-bundle/build/cmake/android.toolchain.cmake ' +
|
||||
'-DANDROID_PLATFORM=' + android_platform + ' -DANDROID_ABI=' + android_abi + ' ' +
|
||||
'-DMONERO_SLOW_HASH=ON ' +
|
||||
cmake_options({ MONERO_SLOW_HASH: true, WARNINGS_AS_ERRORS: false, BUILD_TESTS: false }) +
|
||||
'-DLOCAL_MIRROR=https://builds.lokinet.dev/deps ' +
|
||||
'-DBUILD_STATIC_DEPS=ON -DSTATIC=ON -G Ninja ' + cmake_extra,
|
||||
'ninja -j' + jobs + ' -v wallet_merged',
|
||||
|
@ -327,13 +326,13 @@ local gui_wallet_step_darwin = {
|
|||
'mkdir -p build/{arm64,sim64}',
|
||||
'cd build/arm64',
|
||||
'cmake ../.. -G Ninja ' +
|
||||
'-DCMAKE_TOOLCHAIN_FILE=../../cmake/ios.toolchain.cmake -DPLATFORM=OS -DDEPLOYMENT_TARGET=11 -DENABLE_VISIBILITY=ON -DENABLE_BITCODE=OFF ' +
|
||||
'-DCMAKE_TOOLCHAIN_FILE=../../cmake/ios.toolchain.cmake -DPLATFORM=OS -DDEPLOYMENT_TARGET=13 -DENABLE_VISIBILITY=ON -DENABLE_BITCODE=OFF ' +
|
||||
'-DSTATIC=ON -DBUILD_STATIC_DEPS=ON -DUSE_LTO=OFF -DCMAKE_BUILD_TYPE=Release ' +
|
||||
'-DRANDOMX_ENABLE_JIT=OFF -DCMAKE_CXX_FLAGS=-fcolor-diagnostics',
|
||||
'ninja -j6 -v wallet_merged',
|
||||
'cd ../sim64',
|
||||
'cmake ../.. -G Ninja ' +
|
||||
'-DCMAKE_TOOLCHAIN_FILE=../../cmake/ios.toolchain.cmake -DPLATFORM=SIMULATOR64 -DDEPLOYMENT_TARGET=11 -DENABLE_VISIBILITY=ON -DENABLE_BITCODE=OFF ' +
|
||||
'-DCMAKE_TOOLCHAIN_FILE=../../cmake/ios.toolchain.cmake -DPLATFORM=SIMULATOR64 -DDEPLOYMENT_TARGET=13 -DENABLE_VISIBILITY=ON -DENABLE_BITCODE=OFF ' +
|
||||
'-DSTATIC=ON -DBUILD_STATIC_DEPS=ON -DUSE_LTO=OFF -DCMAKE_BUILD_TYPE=Release ' +
|
||||
'-DRANDOMX_ENABLE_JIT=OFF -DCMAKE_CXX_FLAGS=-fcolor-diagnostics',
|
||||
'ninja -j6 -v wallet_merged',
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
[submodule "external/miniupnp"]
|
||||
path = external/miniupnp
|
||||
url = https://github.com/miniupnp/miniupnp
|
||||
[submodule "external/rapidjson"]
|
||||
path = external/rapidjson
|
||||
url = https://github.com/Tencent/rapidjson
|
||||
|
@ -11,7 +8,7 @@
|
|||
path = external/randomx
|
||||
url = https://github.com/oxen-io/loki-randomXL
|
||||
[submodule "external/loki-mq"]
|
||||
path = external/loki-mq
|
||||
path = external/oxen-mq
|
||||
url = https://github.com/oxen-io/loki-mq.git
|
||||
[submodule "external/googletest"]
|
||||
path = external/googletest
|
||||
|
@ -46,6 +43,6 @@
|
|||
[submodule "external/fmt"]
|
||||
path = external/fmt
|
||||
url = https://github.com/fmtlib/fmt.git
|
||||
[submodule "external/oxenc"]
|
||||
path = external/oxenc
|
||||
url = https://www.github.com/oxen-io/oxen-encoding.git
|
||||
[submodule "external/oxen-encoding"]
|
||||
path = external/oxen-encoding
|
||||
url = https://github.com/oxen-io/oxen-encoding.git
|
||||
|
|
|
@ -51,9 +51,9 @@ message(STATUS "CMake version ${CMAKE_VERSION}")
|
|||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.12 CACHE STRING "macOS deployment target (Apple clang only)")
|
||||
|
||||
project(oxen
|
||||
VERSION 9.2.0
|
||||
VERSION 10.1.0
|
||||
LANGUAGES CXX C)
|
||||
set(OXEN_RELEASE_CODENAME "Audacious Aurochs")
|
||||
set(OXEN_RELEASE_CODENAME "Wistful Wagyu")
|
||||
|
||||
# String value to append to the full version string; this is intended to easily identify whether a
|
||||
# binary was build from the release or development branches. This should be permanently set to an
|
||||
|
@ -284,11 +284,11 @@ if(NOT MANUAL_SUBMODULES)
|
|||
endfunction ()
|
||||
|
||||
message(STATUS "Checking submodules")
|
||||
check_submodule(external/miniupnp)
|
||||
check_submodule(external/rapidjson)
|
||||
check_submodule(external/trezor-common)
|
||||
check_submodule(external/randomx)
|
||||
check_submodule(external/loki-mq cppzmq)
|
||||
check_submodule(external/oxen-mq cppzmq)
|
||||
check_submodule(external/SQLiteCpp)
|
||||
if(BUILD_TESTS)
|
||||
check_submodule(external/googletest)
|
||||
check_submodule(external/Catch2)
|
||||
|
@ -324,7 +324,6 @@ else()
|
|||
endif()
|
||||
message(STATUS "Building for a ${ARCH_WIDTH}-bit system")
|
||||
|
||||
# Check if we're on FreeBSD so we can exclude the local miniupnpc (it should be installed from ports instead)
|
||||
# CMAKE_SYSTEM_NAME checks are commonly known, but specifically taken from libsdl's CMakeLists
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "kFreeBSD.*|FreeBSD")
|
||||
set(FREEBSD TRUE)
|
||||
|
@ -431,24 +430,6 @@ find_package(Threads)
|
|||
|
||||
if (APPLE AND NOT IOS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -fvisibility=default")
|
||||
if (NOT OpenSSL_DIR)
|
||||
EXECUTE_PROCESS(COMMAND brew --prefix openssl
|
||||
OUTPUT_VARIABLE OPENSSL_ROOT_DIR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
message(STATUS "Using OpenSSL found at ${OPENSSL_ROOT_DIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_STATIC_DEPS)
|
||||
# SSL::* targets already set up
|
||||
else()
|
||||
find_package(OpenSSL REQUIRED)
|
||||
endif()
|
||||
message(STATUS "Using OpenSSL include dir at ${OPENSSL_INCLUDE_DIR}")
|
||||
|
||||
if(MINGW)
|
||||
# OpenSSL doesn't seem to properly set up its dependencies on Windows, leading to linking errors
|
||||
target_link_libraries(OpenSSL::Crypto INTERFACE ws2_32)
|
||||
endif()
|
||||
|
||||
add_definition_if_library_exists(c memset_s "string.h" HAVE_MEMSET_S)
|
||||
|
@ -458,7 +439,6 @@ add_definition_if_function_found(strptime HAVE_STRPTIME)
|
|||
# Generate header for embedded translations
|
||||
add_subdirectory(translations)
|
||||
|
||||
add_library(miniupnpc INTERFACE)
|
||||
add_library(systemd INTERFACE) # Will do nothing unless we find and enable systemd support
|
||||
|
||||
if(NOT TARGET sodium)
|
||||
|
@ -481,17 +461,10 @@ if(NOT TARGET sodium)
|
|||
target_link_libraries(sodium INTERFACE sodium_vendor)
|
||||
endif()
|
||||
|
||||
# Need this target export so that loki-mq properly picks up sodium
|
||||
# Need this target export so that oxen-mq properly picks up sodium
|
||||
export(TARGETS sodium NAMESPACE sodium:: FILE sodium-exports.cmake)
|
||||
endif()
|
||||
|
||||
if (NOT BUILD_STATIC_DEPS)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(UNBOUND libunbound REQUIRED IMPORTED_TARGET)
|
||||
add_library(libunbound INTERFACE)
|
||||
target_link_libraries(libunbound INTERFACE PkgConfig::UNBOUND)
|
||||
endif()
|
||||
|
||||
option(WITH_SYSTEMD "Attempts to link against and enable systemd daemon notification support" ON)
|
||||
if (WITH_SYSTEMD AND NOT BUILD_STATIC_DEPS)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
@ -507,6 +480,7 @@ endif()
|
|||
|
||||
|
||||
if(NOT BUILD_STATIC_DEPS)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(SQLITE3 REQUIRED sqlite3 IMPORTED_TARGET GLOBAL)
|
||||
message(STATUS "Found sqlite3 ${SQLITE3_VERSION}")
|
||||
add_library(SQLite::SQLite3 ALIAS PkgConfig::SQLITE3)
|
||||
|
@ -797,7 +771,7 @@ set(Boost_USE_MULTITHREADED TRUE) # Needed for macOS, at least, and won't hurt e
|
|||
if(BUILD_STATIC_DEPS)
|
||||
# StaticBuild.cmake sets Boost targets up for us
|
||||
else()
|
||||
find_package(Boost 1.58 QUIET REQUIRED COMPONENTS system thread serialization program_options)
|
||||
find_package(Boost 1.62 QUIET REQUIRED COMPONENTS system thread serialization program_options)
|
||||
endif()
|
||||
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_LIB_SUFFIXES})
|
||||
|
@ -805,12 +779,6 @@ if(NOT Boost_FOUND)
|
|||
message(FATAL_ERROR "Could not find Boost libraries, please make sure you have installed Boost or libboost-all-dev (>=1.58) or the equivalent")
|
||||
elseif(Boost_FOUND)
|
||||
message(STATUS "Found Boost Version: ${Boost_VERSION}")
|
||||
if (OPENSSL_VERSION VERSION_GREATER_EQUAL 1.1 AND (
|
||||
Boost_VERSION VERSION_LESS 1.62.0 OR (Boost_VERSION VERSION_GREATER 100000 AND Boost_VERSION VERSION_LESS 106200)))
|
||||
message(FATAL_ERROR "Boost ${Boost_VERSION} (older than 1.62) is too old to link with OpenSSL ${OPENSSL_VERSION} (1.1 or newer) found at ${OPENSSL_INCLUDE_DIR} and ${OPENSSL_LIBRARIES}. "
|
||||
"Update Boost or install OpenSSL 1.0 and set path to it when running cmake: "
|
||||
"cmake -DOPENSSL_ROOT_DIR='/usr/include/openssl-1.0'")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Interface target for random extra system libraries that we need to link everything against
|
||||
|
|
62
README.md
62
README.md
|
@ -43,18 +43,14 @@ library archives (`.a`).
|
|||
| CMake | 3.10 | NO | `cmake` | `cmake` | `cmake` | NO | |
|
||||
| pkg-config | any | NO | `pkg-config` | `base-devel` | `pkgconf` | NO | |
|
||||
| Boost | 1.65 | NO | `libboost-all-dev`[2] | `boost` | `boost-devel` | NO | C++ libraries |
|
||||
| OpenSSL | basically any | NO | `libssl-dev` | `openssl` | `openssl-devel` | NO | sha256 sum |
|
||||
| libzmq | 4.3.0 | YES | `libzmq3-dev` | `zeromq` | `zeromq-devel` | NO | ZeroMQ library |
|
||||
| sqlite3 | ? | YES | `libsqlite3-dev` | `sqlite` | `sqlite-devel` | NO | Oxen Name System |
|
||||
| libunbound | 1.4.16 | NO | `libunbound-dev` | `unbound` | `unbound-devel` | NO | DNS resolver |
|
||||
| libsodium | 1.0.9 | YES | `libsodium-dev` | `libsodium` | `libsodium-devel` | NO | cryptography |
|
||||
| libcurl | 4.0 | NO | `libcurl4-openssl-dev` | `curl` | `curl-devel` | NO | HTTP RPC |
|
||||
| libcurl | 4.0 | NO | `libcurl4-dev` | `curl` | `curl-devel` | NO | HTTP RPC |
|
||||
| libuv (Win) | any | NO | (Windows only) | -- | -- | NO | RPC event loop |
|
||||
| libunwind | any | NO | `libunwind8-dev` | `libunwind` | `libunwind-devel` | YES | Stack traces |
|
||||
| liblzma | any | NO | `liblzma-dev` | `xz` | `xz-devel` | YES | For libunwind |
|
||||
| libreadline | 6.3.0 | NO | `libreadline-dev` | `readline` | `readline-devel` | YES | Input editing |
|
||||
| ldns | 1.6.17 | NO | `libldns-dev` | `ldns` | `ldns-devel` | YES | SSL toolkit |
|
||||
| expat | 1.1 | NO | `libexpat1-dev` | `expat` | `expat-devel` | YES | XML parsing |
|
||||
| Doxygen | any | NO | `doxygen` | `doxygen` | `doxygen` | YES | Documentation |
|
||||
| Graphviz | any | NO | `graphviz` | `graphviz` | `graphviz` | YES | Documentation |
|
||||
| Qt tools | 5.x | NO | `qttools5-dev` | `qt5-tools` | `qt5-linguist` | YES | Translations |
|
||||
|
@ -73,14 +69,14 @@ breakdown of the minimum set of required boost packages.
|
|||
Install all dependencies at once on Debian/Ubuntu:
|
||||
|
||||
```
|
||||
sudo apt update && sudo apt install build-essential cmake pkg-config libboost-all-dev libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libldns-dev libexpat1-dev doxygen graphviz libpgm-dev libsqlite3-dev libcurl4-openssl-dev
|
||||
sudo apt update && sudo apt install build-essential cmake pkg-config libboost-all-dev libzmq3-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev doxygen graphviz libpgm-dev libsqlite3-dev libcurl4-dev
|
||||
```
|
||||
|
||||
Install all dependencies at once on macOS with the provided Brewfile:
|
||||
``` brew update && brew bundle --file=contrib/brew/Brewfile ```
|
||||
|
||||
FreeBSD one liner for required to build dependencies
|
||||
```pkg install git gmake cmake pkgconf boost-libs libzmq4 libsodium sqlite3 openssl unbound miniupnpc```
|
||||
```pkg install git gmake cmake pkgconf boost-libs libzmq4 libsodium sqlite3```
|
||||
|
||||
### Build instructions
|
||||
|
||||
|
@ -190,13 +186,13 @@ application.
|
|||
To build for 64-bit Windows:
|
||||
|
||||
```bash
|
||||
pacman -S git mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-sqlite3 mingw-w64-x86_64-unbound
|
||||
pacman -S git mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-sqlite3
|
||||
```
|
||||
|
||||
To build for 32-bit Windows:
|
||||
|
||||
```bash
|
||||
pacman -S git mingw-w64-i686-toolchain make mingw-w64-i686-cmake mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-zeromq mingw-w64-i686-libsodium mingw-w64-i686-hidapi mingw-w64-i686-sqlite3 mingw-w64-i686-unbound
|
||||
pacman -S git mingw-w64-i686-toolchain make mingw-w64-i686-cmake mingw-w64-i686-boost mingw-w64-i686-zeromq mingw-w64-i686-libsodium mingw-w64-i686-hidapi mingw-w64-i686-sqlite3
|
||||
```
|
||||
|
||||
* Close and reopen the MSYS MinGW shell via `MSYS2 MinGW 64-bit` shortcut on
|
||||
|
@ -403,54 +399,6 @@ oxen-wallet-cli, and possibly oxend, if you get crashes refreshing.
|
|||
|
||||
See [README.i18n.md](README.i18n.md).
|
||||
|
||||
## Using Tor
|
||||
|
||||
> There is a new, still experimental, [integration with Tor](ANONYMITY_NETWORKS.md). The
|
||||
> feature allows connecting over IPv4 and Tor simulatenously - IPv4 is used for
|
||||
> relaying blocks and relaying transactions received by peers whereas Tor is
|
||||
> used solely for relaying transactions received over local RPC. This provides
|
||||
> privacy and better protection against surrounding node (sybil) attacks.
|
||||
|
||||
While Oxen isn't made to integrate with Tor, it can be used wrapped with torsocks, by
|
||||
setting the following configuration parameters and environment variables:
|
||||
|
||||
* `--p2p-bind-ip 127.0.0.1` on the command line or `p2p-bind-ip=127.0.0.1` in
|
||||
oxend.conf to disable listening for connections on external interfaces.
|
||||
* `--no-igd` on the command line or `no-igd=1` in oxend.conf to disable IGD
|
||||
(UPnP port forwarding negotiation), which is pointless with Tor.
|
||||
* `DNS_PUBLIC=tcp` or `DNS_PUBLIC=tcp://x.x.x.x` where x.x.x.x is the IP of the
|
||||
desired DNS server, for DNS requests to go over TCP, so that they are routed
|
||||
through Tor. When IP is not specified, oxend uses the default list of
|
||||
servers defined in [src/common/dns_utils.cpp](src/common/dns_utils.cpp).
|
||||
* `TORSOCKS_ALLOW_INBOUND=1` to tell torsocks to allow oxend to bind to interfaces
|
||||
to accept connections from the wallet. On some Linux systems, torsocks
|
||||
allows binding to localhost by default, so setting this variable is only
|
||||
necessary to allow binding to local LAN/VPN interfaces to allow wallets to
|
||||
connect from remote hosts. On other systems, it may be needed for local wallets
|
||||
as well.
|
||||
* Do NOT pass `--detach` when running through torsocks with systemd, (see
|
||||
[utils/systemd/oxend.service](utils/systemd/oxend.service) for details).
|
||||
* If you use the wallet with a Tor daemon via the loopback IP (eg, 127.0.0.1:9050),
|
||||
then use `--untrusted-daemon` unless it is your own hidden service.
|
||||
|
||||
Example command line to start oxend through Tor:
|
||||
|
||||
```bash
|
||||
DNS_PUBLIC=tcp torsocks oxend --p2p-bind-ip 127.0.0.1 --no-igd
|
||||
```
|
||||
|
||||
### Using Tor on Tails
|
||||
|
||||
TAILS ships with a very restrictive set of firewall rules. Therefore, you need
|
||||
to add a rule to allow this connection too, in addition to telling torsocks to
|
||||
allow inbound connections. Full example:
|
||||
|
||||
```bash
|
||||
sudo iptables -I OUTPUT 2 -p tcp -d 127.0.0.1 -m tcp --dport 22023 -j ACCEPT
|
||||
DNS_PUBLIC=tcp torsocks ./oxend --p2p-bind-ip 127.0.0.1 --no-igd --rpc-bind-ip 127.0.0.1 \
|
||||
--data-dir /home/amnesia/Persistent/your/directory/to/the/blockchain
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
This section contains general instructions for debugging failed installs or problems encountered with Oxen. First ensure you are running the latest version built from the Github repo.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# Copyright (c) 2014-2018, The Monero Project
|
||||
# Copyright (c) 2019-2022, The Oxen Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
|
@ -33,32 +34,27 @@ execute_process(COMMAND "${GIT}" rev-parse --short=9 HEAD RESULT_VARIABLE RET OU
|
|||
|
||||
if(RET)
|
||||
# Something went wrong, set the version tag to -unknown
|
||||
|
||||
message(WARNING "Cannot determine current commit. Make sure that you are building either from a Git working tree or from a source archive.")
|
||||
set(VERSIONTAG "unknown")
|
||||
configure_file("version.cpp.in" "version.cpp")
|
||||
else()
|
||||
string(SUBSTRING ${COMMIT} 0 9 COMMIT)
|
||||
message(STATUS "You are currently on commit ${COMMIT}")
|
||||
|
||||
|
||||
# Get all the tags
|
||||
execute_process(COMMAND "${GIT}" rev-list --tags --max-count=1 --abbrev-commit RESULT_VARIABLE RET OUTPUT_VARIABLE TAGGEDCOMMIT OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
|
||||
if(NOT TAGGEDCOMMIT)
|
||||
message(WARNING "Cannot determine most recent tag. Make sure that you are building either from a Git working tree or from a source archive.")
|
||||
set(VERSIONTAG "${COMMIT}")
|
||||
else()
|
||||
message(STATUS "The most recent tag was at ${TAGGEDCOMMIT}")
|
||||
|
||||
# Check if we're building that tagged commit or a different one
|
||||
if(COMMIT STREQUAL TAGGEDCOMMIT)
|
||||
message(STATUS "You are building a tagged release")
|
||||
message(STATUS "${COMMIT} is a tagged release; setting version tag to 'release'")
|
||||
set(VERSIONTAG "release")
|
||||
else()
|
||||
message(STATUS "You are ahead of or behind a tagged release")
|
||||
message(STATUS "You are not building a tagged release; setting version tag to '${COMMIT}'")
|
||||
set(VERSIONTAG "${COMMIT}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
configure_file("version.cpp.in" "version.cpp")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
configure_file("${SRC}" "${DEST}" @ONLY)
|
||||
|
|
|
@ -5,39 +5,19 @@
|
|||
|
||||
set(LOCAL_MIRROR "" CACHE STRING "local mirror path/URL for lib downloads")
|
||||
|
||||
set(OPENSSL_VERSION 1.1.1k CACHE STRING "openssl version")
|
||||
set(OPENSSL_MIRROR ${LOCAL_MIRROR} https://www.openssl.org/source CACHE STRING "openssl download mirror(s)")
|
||||
set(OPENSSL_SOURCE openssl-${OPENSSL_VERSION}.tar.gz)
|
||||
set(OPENSSL_HASH SHA256=892a0875b9872acd04a9fde79b1f943075d5ea162415de3047c327df33fbaee5
|
||||
CACHE STRING "openssl source hash")
|
||||
|
||||
set(EXPAT_VERSION 2.3.0 CACHE STRING "expat version")
|
||||
string(REPLACE "." "_" EXPAT_TAG "R_${EXPAT_VERSION}")
|
||||
set(EXPAT_MIRROR ${LOCAL_MIRROR} https://github.com/libexpat/libexpat/releases/download/${EXPAT_TAG}
|
||||
CACHE STRING "expat download mirror(s)")
|
||||
set(EXPAT_SOURCE expat-${EXPAT_VERSION}.tar.xz)
|
||||
set(EXPAT_HASH SHA512=dde8a9a094b18d795a0e86ca4aa68488b352dc67019e0d669e8b910ed149628de4c2a49bc3a5b832f624319336a01f9e4debe03433a43e1c420f36356d886820
|
||||
CACHE STRING "expat source hash")
|
||||
|
||||
set(UNBOUND_VERSION 1.13.1 CACHE STRING "unbound version")
|
||||
set(UNBOUND_MIRROR ${LOCAL_MIRROR} https://nlnetlabs.nl/downloads/unbound CACHE STRING "unbound download mirror(s)")
|
||||
set(UNBOUND_SOURCE unbound-${UNBOUND_VERSION}.tar.gz)
|
||||
set(UNBOUND_HASH SHA256=8504d97b8fc5bd897345c95d116e0ee0ddf8c8ff99590ab2b4bd13278c9f50b8
|
||||
CACHE STRING "unbound source hash")
|
||||
|
||||
set(BOOST_VERSION 1.76.0 CACHE STRING "boost version")
|
||||
set(BOOST_VERSION 1.79.0 CACHE STRING "boost version")
|
||||
set(BOOST_MIRROR ${LOCAL_MIRROR} https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source
|
||||
CACHE STRING "boost download mirror(s)")
|
||||
string(REPLACE "." "_" BOOST_VERSION_ ${BOOST_VERSION})
|
||||
set(BOOST_SOURCE boost_${BOOST_VERSION_}.tar.bz2)
|
||||
set(BOOST_HASH SHA256=f0397ba6e982c4450f27bf32a2a83292aba035b827a5623a14636ea583318c41
|
||||
set(BOOST_HASH SHA256=475d589d51a7f8b3ba2ba4eda022b170e562ca3b760ee922c146b6c65856ef39
|
||||
CACHE STRING "boost source hash")
|
||||
|
||||
set(NCURSES_VERSION 6.2 CACHE STRING "ncurses version")
|
||||
set(NCURSES_VERSION 6.3 CACHE STRING "ncurses version")
|
||||
set(NCURSES_MIRROR ${LOCAL_MIRROR} http://ftpmirror.gnu.org/gnu/ncurses
|
||||
CACHE STRING "ncurses download mirror(s)")
|
||||
set(NCURSES_SOURCE ncurses-${NCURSES_VERSION}.tar.gz)
|
||||
set(NCURSES_HASH SHA512=4c1333dcc30e858e8a9525d4b9aefb60000cfc727bc4a1062bace06ffc4639ad9f6e54f6bdda0e3a0e5ea14de995f96b52b3327d9ec633608792c99a1e8d840d
|
||||
set(NCURSES_HASH SHA512=5373f228cba6b7869210384a607a2d7faecfcbfef6dbfcd7c513f4e84fbd8bcad53ac7db2e7e84b95582248c1039dcfc7c4db205a618f7da22a166db482f0105
|
||||
CACHE STRING "ncurses source hash")
|
||||
|
||||
set(READLINE_VERSION 8.1 CACHE STRING "readline version")
|
||||
|
@ -47,11 +27,11 @@ set(READLINE_SOURCE readline-${READLINE_VERSION}.tar.gz)
|
|||
set(READLINE_HASH SHA512=27790d0461da3093a7fee6e89a51dcab5dc61928ec42e9228ab36493b17220641d5e481ea3d8fee5ee0044c70bf960f55c7d3f1a704cf6b9c42e5c269b797e00
|
||||
CACHE STRING "readline source hash")
|
||||
|
||||
set(SQLITE3_VERSION 3350500 CACHE STRING "sqlite3 version")
|
||||
set(SQLITE3_MIRROR ${LOCAL_MIRROR} https://www.sqlite.org/2021
|
||||
set(SQLITE3_VERSION 3380200 CACHE STRING "sqlite3 version")
|
||||
set(SQLITE3_MIRROR ${LOCAL_MIRROR} https://www.sqlite.org/2022
|
||||
CACHE STRING "sqlite3 download mirror(s)")
|
||||
set(SQLITE3_SOURCE sqlite-autoconf-${SQLITE3_VERSION}.tar.gz)
|
||||
set(SQLITE3_HASH SHA512=039af796f79fc4517be0bd5ba37886264d49da309e234ae6fccdb488ef0109ed2b917fc3e6c1fc7224dff4f736824c653aaf8f0a37550c5ebc14d035cb8ac737
|
||||
set(SQLITE3_HASH SHA512=2192675d8638a933ec75ec78dc4185f005c9d37453bc2bbe590b72235066f68ba2cac1be3b491a47d6a7ca74d5b3bfe4e548d576a6b324383bb9bc7739d0b635
|
||||
CACHE STRING "sqlite3 source hash")
|
||||
|
||||
if(SQLITE3_VERSION MATCHES "^([0-9]+)(0([0-9])|([1-9][0-9]))(0([0-9])|([1-9][0-9]))[0-9][0-9]$")
|
||||
|
@ -63,25 +43,25 @@ else()
|
|||
endif()
|
||||
|
||||
|
||||
set(EUDEV_VERSION 3.2.10 CACHE STRING "eudev version")
|
||||
set(EUDEV_MIRROR ${LOCAL_MIRROR} https://github.com/gentoo/eudev/archive/
|
||||
set(EUDEV_VERSION 3.2.11 CACHE STRING "eudev version")
|
||||
set(EUDEV_MIRROR ${LOCAL_MIRROR} https://github.com/eudev-project/eudev/archive/
|
||||
CACHE STRING "eudev download mirror(s)")
|
||||
set(EUDEV_SOURCE v${EUDEV_VERSION}.tar.gz)
|
||||
set(EUDEV_HASH SHA512=37fc5e7f960a843fa68269697882123af4515555788a9e856474f51dd8c330a4c8e52e7c897aeb5d3eb36c6ad66cc99f5a38a284a75620b7e6c275c703e25d42
|
||||
set(EUDEV_HASH SHA512=17b328365913af3e434abe667dd0498c3702a41c6cb66f3793ca2c195b05ac06397b0a401077f81df7dd25193e4eeea13657a221ca6cb3d237c4d91e31e30b33
|
||||
CACHE STRING "eudev source hash")
|
||||
|
||||
set(LIBUSB_VERSION 1.0.24 CACHE STRING "libusb version")
|
||||
set(LIBUSB_VERSION 1.0.26 CACHE STRING "libusb version")
|
||||
set(LIBUSB_MIRROR ${LOCAL_MIRROR} https://github.com/libusb/libusb/releases/download/v${LIBUSB_VERSION}
|
||||
CACHE STRING "libusb download mirror(s)")
|
||||
set(LIBUSB_SOURCE libusb-${LIBUSB_VERSION}.tar.bz2)
|
||||
set(LIBUSB_HASH SHA512=5aea36a530aaa15c6dd656d0ed3ce204522c9946d8d39ffbb290dab4a98cda388a2598da4995123d1032324056090bd429e702459626d3e8d7daeebc4e7ff3dc
|
||||
set(LIBUSB_HASH SHA512=fcdb85c98f21639668693c2fd522814d440972d65883984c4ae53d0555bdbdb7e8c7a32199cd4b01113556a1eb5be7841b750cc73c9f6bda79bfe1af80914e71
|
||||
CACHE STRING "libusb source hash")
|
||||
|
||||
set(HIDAPI_VERSION 0.9.0 CACHE STRING "hidapi version")
|
||||
set(HIDAPI_VERSION 0.11.2 CACHE STRING "hidapi version")
|
||||
set(HIDAPI_MIRROR ${LOCAL_MIRROR} https://github.com/libusb/hidapi/archive
|
||||
CACHE STRING "hidapi download mirror(s)")
|
||||
set(HIDAPI_SOURCE hidapi-${HIDAPI_VERSION}.tar.gz)
|
||||
set(HIDAPI_HASH SHA512=d9f28d394b78daece7d2dfb946e62349a56b388b3a06241585c6fad5a4e24dc914723de6c0f12a9e51cd23fb245f6b5ac9b3721319646d5ba5912bbe0a3f9a52
|
||||
set(HIDAPI_HASH SHA512=c4d04bf570aa98dd88d7ce08ef1abb0675d500c9aa2c22f0437fa30b700a94446779f77e1170267926d5f6f0d9cdb2bb81ad1fe20d158c18587fddbca59e9517
|
||||
CACHE STRING "hidapi source hash")
|
||||
|
||||
# NB: not currently built, used for (non-functional) trezor code
|
||||
|
@ -108,18 +88,18 @@ set(ZMQ_SOURCE zeromq-${ZMQ_VERSION}.tar.gz)
|
|||
set(ZMQ_HASH SHA512=e198ef9f82d392754caadd547537666d4fba0afd7d027749b3adae450516bcf284d241d4616cad3cb4ad9af8c10373d456de92dc6d115b037941659f141e7c0e
|
||||
CACHE STRING "libzmq source hash")
|
||||
|
||||
set(ZLIB_VERSION 1.2.11 CACHE STRING "zlib version")
|
||||
set(ZLIB_VERSION 1.2.12 CACHE STRING "zlib version")
|
||||
set(ZLIB_MIRROR ${LOCAL_MIRROR} https://zlib.net
|
||||
CACHE STRING "zlib mirror(s)")
|
||||
set(ZLIB_SOURCE zlib-${ZLIB_VERSION}.tar.gz)
|
||||
set(ZLIB_HASH SHA512=73fd3fff4adeccd4894084c15ddac89890cd10ef105dd5e1835e1e9bbb6a49ff229713bd197d203edfa17c2727700fce65a2a235f07568212d820dca88b528ae
|
||||
set(ZLIB_HASH SHA512=cc2366fa45d5dfee1f983c8c51515e0cff959b61471e2e8d24350dea22d3f6fcc50723615a911b046ffc95f51ba337d39ae402131a55e6d1541d3b095d6c0a14
|
||||
CACHE STRING "zlib source hash")
|
||||
|
||||
set(CURL_VERSION 7.76.1 CACHE STRING "curl version")
|
||||
set(CURL_MIRROR ${LOCAL_MIRROR} https://curl.haxx.se/download https://curl.askapache.com
|
||||
set(CURL_VERSION 7.82.0 CACHE STRING "curl version")
|
||||
set(CURL_MIRROR ${LOCAL_MIRROR} https://curl.se/download https://curl.askapache.com
|
||||
CACHE STRING "curl mirror(s)")
|
||||
set(CURL_SOURCE curl-${CURL_VERSION}.tar.xz)
|
||||
set(CURL_HASH SHA256=64bb5288c39f0840c07d077e30d9052e1cbb9fa6c2dc52523824cc859e679145
|
||||
set(CURL_HASH SHA256=0aaa12d7bd04b0966254f2703ce80dd5c38dbbd76af0297d3d690cdce58a583c
|
||||
CACHE STRING "curl source hash")
|
||||
|
||||
|
||||
|
@ -141,16 +121,12 @@ if (ANDROID)
|
|||
endif()
|
||||
if(CMAKE_ANDROID_ARCH_ABI MATCHES x86_64)
|
||||
set(android_clang x86_64-linux-android${ANDROID_PLATFORM_LEVEL}-clang)
|
||||
set(openssl_machine x86_64)
|
||||
elseif(CMAKE_ANDROID_ARCH_ABI MATCHES x86)
|
||||
set(android_clang i686-linux-android${ANDROID_PLATFORM_LEVEL}-clang)
|
||||
set(openssl_machine i686)
|
||||
elseif(CMAKE_ANDROID_ARCH_ABI MATCHES armeabi-v7a)
|
||||
set(android_clang armv7a-linux-androideabi${ANDROID_PLATFORM_LEVEL}-clang)
|
||||
set(openssl_machine armv7)
|
||||
elseif(CMAKE_ANDROID_ARCH_ABI MATCHES arm64-v8a)
|
||||
set(android_clang aarch64-linux-android${ANDROID_PLATFORM_LEVEL}-clang)
|
||||
set(openssl_machine aarch64)
|
||||
else()
|
||||
message(FATAL_ERROR "Don't know how to build for android arch abi ${CMAKE_ANDROID_ARCH_ABI}")
|
||||
endif()
|
||||
|
@ -276,74 +252,6 @@ add_static_target(zlib zlib_external libz.a)
|
|||
|
||||
|
||||
|
||||
set(openssl_configure ./config)
|
||||
set(openssl_system_env "")
|
||||
set(openssl_cc "${deps_cc}")
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
if(ARCH_TRIPLET STREQUAL x86_64-w64-mingw32)
|
||||
set(openssl_system_env SYSTEM=MINGW64 RC=${CMAKE_RC_COMPILER})
|
||||
elseif(ARCH_TRIPLET STREQUAL i686-w64-mingw32)
|
||||
set(openssl_system_env SYSTEM=MINGW64 RC=${CMAKE_RC_COMPILER})
|
||||
elseif(ANDROID)
|
||||
set(openssl_system_env SYSTEM=Linux MACHINE=${openssl_machine} ${cross_extra})
|
||||
set(openssl_extra_opts no-asm)
|
||||
elseif(IOS)
|
||||
get_filename_component(apple_toolchain "${CMAKE_C_COMPILER}" DIRECTORY)
|
||||
get_filename_component(apple_sdk "${CMAKE_OSX_SYSROOT}" NAME)
|
||||
if(NOT ${apple_toolchain} MATCHES Xcode OR NOT ${apple_sdk} MATCHES "iPhone(OS|Simulator)")
|
||||
message(FATAL_ERROR "didn't find your toolchain and sdk correctly from ${CMAKE_C_COMPILER}/${CMAKE_OSX_SYSROOT}: found toolchain=${apple_toolchain}, sdk=${apple_sdk}")
|
||||
endif()
|
||||
set(openssl_system_env CROSS_COMPILE=${apple_toolchain}/ CROSS_TOP=${CMAKE_DEVELOPER_ROOT} CROSS_SDK=${apple_sdk})
|
||||
set(openssl_configure ./Configure iphoneos-cross)
|
||||
set(openssl_cc "clang")
|
||||
endif()
|
||||
endif()
|
||||
build_external(openssl
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env CC=${openssl_cc} ${openssl_system_env} ${openssl_configure}
|
||||
--prefix=${DEPS_DESTDIR} ${openssl_extra_opts} no-shared no-capieng no-dso no-dtls1 no-ec_nistp_64_gcc_128 no-gost
|
||||
no-heartbeats no-md2 no-rc5 no-rdrand no-rfc3779 no-sctp no-ssl-trace no-ssl2 no-ssl3
|
||||
no-static-engine no-tests no-weak-ssl-ciphers no-zlib-dynamic "CFLAGS=${deps_CFLAGS}"
|
||||
INSTALL_COMMAND make install_sw
|
||||
BUILD_BYPRODUCTS
|
||||
${DEPS_DESTDIR}/lib/libssl.a ${DEPS_DESTDIR}/lib/libcrypto.a
|
||||
${DEPS_DESTDIR}/include/openssl/ssl.h ${DEPS_DESTDIR}/include/openssl/crypto.h
|
||||
)
|
||||
add_static_target(OpenSSL::SSL openssl_external libssl.a)
|
||||
add_static_target(OpenSSL::Crypto openssl_external libcrypto.a)
|
||||
set(OPENSSL_INCLUDE_DIR ${DEPS_DESTDIR}/include)
|
||||
set(OPENSSL_VERSION 1.1.1)
|
||||
|
||||
|
||||
|
||||
build_external(expat
|
||||
CONFIGURE_COMMAND ./configure ${cross_host} --prefix=${DEPS_DESTDIR} --enable-static
|
||||
--disable-shared --with-pic --without-examples --without-tests --without-docbook --without-xmlwf
|
||||
"CC=${deps_cc}" "CFLAGS=${deps_CFLAGS}"
|
||||
)
|
||||
add_static_target(expat expat_external libexpat.a)
|
||||
|
||||
|
||||
set(unbound_extra)
|
||||
if(APPLE AND IOS)
|
||||
# I have no idea why this is necessary: without this it runs `clang -E` which should work, but
|
||||
# doesn't because... hurray ios is wonderful?
|
||||
set(unbound_extra CPP=cpp)
|
||||
endif()
|
||||
build_external(unbound
|
||||
DEPENDS openssl_external expat_external
|
||||
CONFIGURE_COMMAND ./configure ${cross_host} ${cross_extra} --prefix=${DEPS_DESTDIR} --disable-shared
|
||||
--enable-static --with-libunbound-only --with-pic --disable-gost
|
||||
--$<IF:$<BOOL:${USE_LTO}>,enable,disable>-flto --with-ssl=${DEPS_DESTDIR}
|
||||
--with-libexpat=${DEPS_DESTDIR}
|
||||
"CC=${deps_cc}" "CFLAGS=${deps_CFLAGS}" ${unbound_extra}
|
||||
)
|
||||
add_static_target(libunbound unbound_external libunbound.a)
|
||||
if(WIN32)
|
||||
set_target_properties(libunbound PROPERTIES INTERFACE_LINK_LIBRARIES "ws2_32;crypt32;iphlpapi")
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
set(boost_threadapi "pthread")
|
||||
set(boost_bootstrap_cxx "--cxx=${deps_cxx}")
|
||||
set(boost_toolset "")
|
||||
|
@ -526,14 +434,21 @@ else()
|
|||
set(hidapi_libusb_lib libhidapi.a)
|
||||
set(hidapi_lib_byproducts ${DEPS_DESTDIR}/lib/libhidapi.a)
|
||||
endif()
|
||||
set(hidapi_cmake_toolchain)
|
||||
if(CMAKE_TOOLCHAIN_FILE)
|
||||
set(hidapi_cmake_toolchain "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}")
|
||||
endif()
|
||||
build_external(hidapi
|
||||
DEPENDS ${maybe_eudev} libusb_external
|
||||
PATCH_COMMAND patch -p1 -i ${PROJECT_SOURCE_DIR}/utils/build_scripts/hidapi-autoconf-duplicate-macro-dir.patch
|
||||
CONFIGURE_COMMAND autoreconf -ivf && ./configure ${cross_host} --prefix=${DEPS_DESTDIR} --disable-shared --enable-static --with-pic
|
||||
"CC=${deps_cc}" "CXX=${deps_cxx}" "CFLAGS=${deps_CFLAGS}" "CXXFLAGS=${deps_CXXFLAGS}"
|
||||
${cross_extra}
|
||||
"libudev_CFLAGS=-I${DEPS_DESTDIR}/include" "libudev_LIBS=-L${DEPS_DESTDIR}/lib -ludev"
|
||||
"libusb_CFLAGS=-I${DEPS_DESTDIR}/include/libusb-1.0" "libusb_LIBS=-L${DEPS_DESTDIR}/lib -lusb-1.0"
|
||||
CONFIGURE_COMMAND mkdir -p build && cd build && cmake .. "-DCMAKE_GENERATOR=Unix Makefiles"
|
||||
"-DCMAKE_PREFIX_PATH=${DEPS_DESTDIR}" "-DCMAKE_INSTALL_PREFIX=${DEPS_DESTDIR}"
|
||||
"-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
|
||||
"-DCMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER}"
|
||||
"-DCMAKE_C_FLAGS=${deps_CFLAGS}"
|
||||
${hidapi_cmake_toolchain}
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
BUILD_COMMAND cd build && make
|
||||
INSTALL_COMMAND cd build && make install
|
||||
BUILD_BYPRODUCTS
|
||||
${hidapi_lib_byproducts}
|
||||
${DEPS_DESTDIR}/include/hidapi
|
||||
|
@ -544,6 +459,8 @@ else()
|
|||
set(hidapi_links "libusb_vendor;libudev")
|
||||
if(WIN32)
|
||||
list(APPEND hidapi_links setupapi)
|
||||
elseif(APPLE)
|
||||
list(APPEND hidapi_links "-framework AppKit")
|
||||
endif()
|
||||
set_target_properties(hidapi_libusb PROPERTIES
|
||||
INTERFACE_LINK_LIBRARIES "${hidapi_links}"
|
||||
|
@ -595,6 +512,7 @@ build_external(zmq
|
|||
${zmq_patch}
|
||||
CONFIGURE_COMMAND ./configure ${zmq_cross_host} --prefix=${DEPS_DESTDIR} --enable-static --disable-shared
|
||||
--disable-curve-keygen --enable-curve --disable-drafts --disable-libunwind --with-libsodium
|
||||
--disable-libbsd --disable-perf
|
||||
--without-pgm --without-norm --without-vmci --without-docs --with-pic --disable-Werror
|
||||
"CC=${deps_cc}" "CXX=${deps_cxx}" "CFLAGS=-fstack-protector ${deps_CFLAGS}" "CXXFLAGS=-fstack-protector ${deps_CXXFLAGS}"
|
||||
${cross_extra}
|
||||
|
@ -604,7 +522,7 @@ add_static_target(libzmq zmq_external libzmq.a)
|
|||
|
||||
set(libzmq_link_libs "sodium")
|
||||
if(CMAKE_CROSSCOMPILING AND ARCH_TRIPLET MATCHES mingw)
|
||||
list(APPEND libzmq_link_libs iphlpapi)
|
||||
list(APPEND libzmq_link_libs iphlpapi ws2_32)
|
||||
endif()
|
||||
|
||||
set_target_properties(libzmq PROPERTIES
|
||||
|
@ -614,16 +532,12 @@ set_target_properties(libzmq PROPERTIES
|
|||
|
||||
|
||||
set(curl_extra)
|
||||
if(WIN32)
|
||||
set(curl_ssl_opts --without-ssl --with-schannel)
|
||||
elseif(APPLE)
|
||||
set(curl_ssl_opts --without-ssl --with-secure-transport)
|
||||
if(APPLE)
|
||||
if(IOS)
|
||||
# This CPP crap shouldn't be necessary but is because Apple's toolchain is trash
|
||||
set(curl_extra "LDFLAGS=-L${DEPS_DESTDIR}/lib -isysroot ${CMAKE_OSX_SYSROOT}" CPP=cpp)
|
||||
endif()
|
||||
else()
|
||||
set(curl_ssl_opts --with-ssl=${DEPS_DESTDIR})
|
||||
set(curl_extra "LIBS=-pthread")
|
||||
endif()
|
||||
|
||||
|
@ -655,7 +569,7 @@ foreach(curl_arch ${curl_arches})
|
|||
|
||||
build_external(curl
|
||||
TARGET_SUFFIX ${curl_target_suffix}
|
||||
DEPENDS openssl_external zlib_external
|
||||
DEPENDS zlib_external
|
||||
CONFIGURE_COMMAND ./configure ${cross_host} ${cross_extra} --prefix=${curl_prefix} --disable-shared
|
||||
--enable-static --disable-ares --disable-ftp --disable-ldap --disable-laps --disable-rtsp
|
||||
--disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb
|
||||
|
@ -663,8 +577,9 @@ foreach(curl_arch ${curl_arches})
|
|||
--enable-ipv6 --disable-threaded-resolver --disable-pthreads --disable-verbose --disable-sspi
|
||||
--enable-crypto-auth --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --disable-cookies
|
||||
--enable-http-auth --enable-doh --disable-mime --enable-dateparse --disable-netrc --without-libidn2
|
||||
--disable-progress-meter --without-brotli --with-zlib=${DEPS_DESTDIR} ${curl_ssl_opts}
|
||||
--without-libmetalink --without-librtmp --disable-versioned-symbols --enable-hidden-symbols
|
||||
--disable-progress-meter --without-brotli --with-zlib=${DEPS_DESTDIR}
|
||||
--without-ssl --without-schannel --without-secure-transport
|
||||
--without-librtmp --disable-versioned-symbols --enable-hidden-symbols
|
||||
--without-zsh-functions-dir --without-fish-functions-dir
|
||||
"CC=${deps_cc}" "CFLAGS=${deps_noarch_CFLAGS}${cflags_extra}" ${curl_extra}
|
||||
BUILD_COMMAND true
|
||||
|
@ -693,9 +608,9 @@ endif()
|
|||
add_static_target(CURL::libcurl curl_external libcurl.a)
|
||||
set(libcurl_link_libs zlib)
|
||||
if(CMAKE_CROSSCOMPILING AND ARCH_TRIPLET MATCHES mingw)
|
||||
list(APPEND libcurl_link_libs crypt32)
|
||||
list(APPEND libcurl_link_libs ws2_32)
|
||||
elseif(APPLE)
|
||||
list(APPEND libcurl_link_libs "-framework Security")
|
||||
list(APPEND libcurl_link_libs "-framework SystemConfiguration")
|
||||
endif()
|
||||
set_target_properties(CURL::libcurl PROPERTIES
|
||||
INTERFACE_LINK_LIBRARIES "${libcurl_link_libs}"
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
# 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.
|
||||
|
||||
function (write_static_version_header hash)
|
||||
set(VERSIONTAG "${hash}")
|
||||
configure_file("${CMAKE_SOURCE_DIR}/src/version.cpp.in" "${CMAKE_BINARY_DIR}/version.cpp")
|
||||
endfunction ()
|
||||
|
||||
find_package(Git QUIET)
|
||||
if (GIT_FOUND OR Git_FOUND)
|
||||
message(STATUS "Found Git: ${GIT_EXECUTABLE}")
|
||||
set(VERSIONTAG "@VERSIONTAG@") # Will be replaced again by GenVersion.cmake, below.
|
||||
configure_file("${CMAKE_SOURCE_DIR}/src/version.cpp.in" "${CMAKE_BINARY_DIR}/version.cpp.in")
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_BINARY_DIR}/version.cpp"
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
"-D" "GIT=${GIT_EXECUTABLE}"
|
||||
"-P" "${CMAKE_SOURCE_DIR}/cmake/GenVersion.cmake"
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||
DEPENDS "${CMAKE_BINARY_DIR}/version.cpp.in")
|
||||
else()
|
||||
message(WARNING "Git was not found; setting release tag to 'unknown'")
|
||||
write_static_version_header("unknown")
|
||||
endif ()
|
||||
add_custom_target(genversion ALL
|
||||
DEPENDS "${CMAKE_BINARY_DIR}/version.cpp")
|
|
@ -23,7 +23,6 @@ brew "zmq"
|
|||
brew "libpgm"
|
||||
brew "unbound"
|
||||
brew "libsodium"
|
||||
brew "miniupnpc"
|
||||
brew "readline"
|
||||
brew "ldns"
|
||||
brew "expat"
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <iostream>
|
||||
#include <any>
|
||||
#include <unordered_map>
|
||||
#include <optional>
|
||||
#ifdef __OpenBSD__
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright (c) 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace epee
|
||||
{
|
||||
|
||||
namespace fnv
|
||||
{
|
||||
inline uint64_t FNV1a(const char *ptr, size_t sz)
|
||||
{
|
||||
uint64_t h = 0xcbf29ce484222325;
|
||||
for (size_t i = 0; i < sz; ++i)
|
||||
h = (h ^ *(const uint8_t*)ptr++) * 0x100000001b3;
|
||||
return h;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,227 +0,0 @@
|
|||
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the Andrey N. Sabelnikov nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef _GZIP_ENCODING_H_
|
||||
#define _GZIP_ENCODING_H_
|
||||
#include "net/http_client_base.h"
|
||||
#include "zlib/zlib.h"
|
||||
//#include "http.h"
|
||||
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace net_utils
|
||||
{
|
||||
|
||||
|
||||
|
||||
class content_encoding_gzip: public i_sub_handler
|
||||
{
|
||||
public:
|
||||
/*! \brief
|
||||
* Function content_encoding_gzip : Constructor
|
||||
*
|
||||
*/
|
||||
inline
|
||||
content_encoding_gzip(i_target_handler* powner_filter, bool is_deflate_mode = false):m_powner_filter(powner_filter),
|
||||
m_is_stream_ended(false),
|
||||
m_is_deflate_mode(is_deflate_mode),
|
||||
m_is_first_update_in(true)
|
||||
{
|
||||
memset(&m_zstream_in, 0, sizeof(m_zstream_in));
|
||||
memset(&m_zstream_out, 0, sizeof(m_zstream_out));
|
||||
int ret = 0;
|
||||
if(is_deflate_mode)
|
||||
{
|
||||
ret = inflateInit(&m_zstream_in);
|
||||
ret = deflateInit(&m_zstream_out, Z_DEFAULT_COMPRESSION);
|
||||
}else
|
||||
{
|
||||
ret = inflateInit2(&m_zstream_in, 0x1F);
|
||||
ret = deflateInit2(&m_zstream_out, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 0x1F, 8, Z_DEFAULT_STRATEGY);
|
||||
}
|
||||
}
|
||||
/*! \brief
|
||||
* Function content_encoding_gzip : Destructor
|
||||
*
|
||||
*/
|
||||
inline
|
||||
~content_encoding_gzip()
|
||||
{
|
||||
inflateEnd(& m_zstream_in );
|
||||
deflateEnd(& m_zstream_out );
|
||||
}
|
||||
/*! \brief
|
||||
* Function update_in : Entry point for income data
|
||||
*
|
||||
*/
|
||||
inline
|
||||
virtual bool update_in( std::string& piece_of_transfer)
|
||||
{
|
||||
|
||||
bool is_first_time_here = m_is_first_update_in;
|
||||
m_is_first_update_in = false;
|
||||
|
||||
if(m_pre_decode.size())
|
||||
m_pre_decode += piece_of_transfer;
|
||||
else
|
||||
m_pre_decode.swap(piece_of_transfer);
|
||||
piece_of_transfer.clear();
|
||||
|
||||
std::string decode_summary_buff;
|
||||
|
||||
size_t ungzip_size = m_pre_decode.size() * 0x30;
|
||||
std::string current_decode_buff(ungzip_size, 'X');
|
||||
|
||||
//Here the cycle is introduced where we unpack the buffer, the cycle is required
|
||||
//because of the case where if after unpacking the data will exceed the awaited size, we will not halt with error
|
||||
bool continue_unpacking = true;
|
||||
bool first_step = true;
|
||||
while(m_pre_decode.size() && continue_unpacking)
|
||||
{
|
||||
|
||||
//fill buffers
|
||||
m_zstream_in.next_in = (Bytef*)m_pre_decode.data();
|
||||
m_zstream_in.avail_in = (uInt)m_pre_decode.size();
|
||||
m_zstream_in.next_out = (Bytef*)current_decode_buff.data();
|
||||
m_zstream_in.avail_out = (uInt)ungzip_size;
|
||||
|
||||
int flag = Z_SYNC_FLUSH;
|
||||
int ret = inflate(&m_zstream_in, flag);
|
||||
CHECK_AND_ASSERT_MES(ret>=0 || m_zstream_in.avail_out ||m_is_deflate_mode, false, "content_encoding_gzip::update_in() Failed to inflate. err = " << ret);
|
||||
|
||||
if(Z_STREAM_END == ret)
|
||||
m_is_stream_ended = true;
|
||||
else if(Z_DATA_ERROR == ret && is_first_time_here && m_is_deflate_mode&& first_step)
|
||||
{
|
||||
// some servers (notably Apache with mod_deflate) don't generate zlib headers
|
||||
// insert a dummy header and try again
|
||||
static char dummy_head[2] =
|
||||
{
|
||||
0x8 + 0x7 * 0x10,
|
||||
(((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
|
||||
};
|
||||
inflateReset(&m_zstream_in);
|
||||
m_zstream_in.next_in = (Bytef*) dummy_head;
|
||||
m_zstream_in.avail_in = sizeof(dummy_head);
|
||||
|
||||
ret = inflate(&m_zstream_in, Z_NO_FLUSH);
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
LOCAL_ASSERT(0);
|
||||
m_pre_decode.swap(piece_of_transfer);
|
||||
return false;
|
||||
}
|
||||
m_zstream_in.next_in = (Bytef*)m_pre_decode.data();
|
||||
m_zstream_in.avail_in = (uInt)m_pre_decode.size();
|
||||
|
||||
ret = inflate(&m_zstream_in, Z_NO_FLUSH);
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
LOCAL_ASSERT(0);
|
||||
m_pre_decode.swap(piece_of_transfer);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//leave only unpacked part in the output buffer to start with it the next time
|
||||
m_pre_decode.erase(0, m_pre_decode.size()-m_zstream_in.avail_in);
|
||||
//if decoder gave nothing to return, then everything is ahead, now simply break
|
||||
if(ungzip_size == m_zstream_in.avail_out)
|
||||
break;
|
||||
|
||||
//decode_buff currently stores data parts that were unpacked, fix this size
|
||||
current_decode_buff.resize(ungzip_size - m_zstream_in.avail_out);
|
||||
if(decode_summary_buff.size())
|
||||
decode_summary_buff += current_decode_buff;
|
||||
else
|
||||
current_decode_buff.swap(decode_summary_buff);
|
||||
|
||||
current_decode_buff.resize(ungzip_size);
|
||||
first_step = false;
|
||||
}
|
||||
|
||||
//Process these data if required
|
||||
bool res = true;
|
||||
|
||||
res = m_powner_filter->handle_target_data(decode_summary_buff);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
/*! \brief
|
||||
* Function stop : Entry point for stop signal and flushing cached data buffer.
|
||||
*
|
||||
*/
|
||||
inline
|
||||
virtual void stop(std::string& collect_remains)
|
||||
{
|
||||
}
|
||||
protected:
|
||||
private:
|
||||
/*! \brief
|
||||
* Pointer to parent HTTP-parser
|
||||
*/
|
||||
i_target_handler* m_powner_filter;
|
||||
/*! \brief
|
||||
* ZLIB object for income stream
|
||||
*/
|
||||
z_stream m_zstream_in;
|
||||
/*! \brief
|
||||
* ZLIB object for outcome stream
|
||||
*/
|
||||
z_stream m_zstream_out;
|
||||
/*! \brief
|
||||
* Data that could not be unpacked immediately, left to wait for the next packet of data
|
||||
*/
|
||||
std::string m_pre_decode;
|
||||
/*! \brief
|
||||
* The data are accumulated for a package in the buffer to send the web client
|
||||
*/
|
||||
std::string m_pre_encode;
|
||||
/*! \brief
|
||||
* Signals that stream looks like ended
|
||||
*/
|
||||
bool m_is_stream_ended;
|
||||
/*! \brief
|
||||
* If this flag is set, income data is in HTTP-deflate mode
|
||||
*/
|
||||
bool m_is_deflate_mode;
|
||||
/*! \brief
|
||||
* Marks that it is a first data packet
|
||||
*/
|
||||
bool m_is_first_update_in;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif //_GZIP_ENCODING_H_
|
|
@ -1,76 +0,0 @@
|
|||
// Copyright (c) 2017-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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "wipeable_string.h"
|
||||
#include "span.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
struct to_hex
|
||||
{
|
||||
//! \return A std::string containing hex of `src`.
|
||||
static std::string string(const span<const std::uint8_t> src);
|
||||
//! \return A epee::wipeable_string containing hex of `src`.
|
||||
static epee::wipeable_string wipeable_string(const span<const std::uint8_t> src);
|
||||
template<typename T> static epee::wipeable_string wipeable_string(const T &pod) { return wipeable_string(span<const uint8_t>((const uint8_t*)&pod, sizeof(pod))); }
|
||||
|
||||
//! \return An array containing hex of `src`.
|
||||
template<std::size_t N>
|
||||
static std::array<char, N * 2> array(const std::array<std::uint8_t, N>& src) noexcept
|
||||
{
|
||||
std::array<char, N * 2> out{{}};
|
||||
static_assert(N <= 128, "keep the stack size down");
|
||||
buffer_unchecked(out.data(), {src.data(), src.size()});
|
||||
return out;
|
||||
}
|
||||
|
||||
//! Append `src` as hex to `out`.
|
||||
static void buffer(std::ostream& out, const span<const std::uint8_t> src);
|
||||
|
||||
private:
|
||||
template<typename T> T static convert(const span<const std::uint8_t> src);
|
||||
|
||||
//! Write `src` bytes as hex to `out`. `out` must be twice the length
|
||||
static void buffer_unchecked(char* out, const span<const std::uint8_t> src) noexcept;
|
||||
};
|
||||
|
||||
struct from_hex
|
||||
{
|
||||
//! \return An std::vector of unsigned integers from the `src`
|
||||
static std::vector<uint8_t> vector(std::string_view src);
|
||||
};
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2005 - DINH Viet Hoa
|
||||
* 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 libEtPan! project 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 AUTHORS 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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
/* hmac-md5.h -- HMAC_MD5 functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: hmac-md5.h,v 1.1.1.1 2005/03/18 20:17:28 zautrix Exp $
|
||||
*/
|
||||
|
||||
#ifndef HMAC_MD5_H
|
||||
#define HMAC_MD5_H 1
|
||||
|
||||
namespace md5
|
||||
{
|
||||
|
||||
|
||||
|
||||
#define HMAC_MD5_SIZE 16
|
||||
|
||||
/* intermediate MD5 context */
|
||||
typedef struct HMAC_MD5_CTX_s {
|
||||
MD5_CTX ictx, octx;
|
||||
} HMAC_MD5_CTX;
|
||||
|
||||
/* intermediate HMAC state
|
||||
* values stored in network byte order (Big Endian)
|
||||
*/
|
||||
typedef struct HMAC_MD5_STATE_s {
|
||||
UINT4 istate[4];
|
||||
UINT4 ostate[4];
|
||||
} HMAC_MD5_STATE;
|
||||
|
||||
/* One step hmac computation
|
||||
*
|
||||
* digest may be same as text or key
|
||||
*/
|
||||
void hmac_md5(const unsigned char *text, int text_len,
|
||||
const unsigned char *key, int key_len,
|
||||
unsigned char digest[HMAC_MD5_SIZE]);
|
||||
|
||||
/* create context from key
|
||||
*/
|
||||
void hmac_md5_init(HMAC_MD5_CTX *hmac,
|
||||
const unsigned char *key, int key_len);
|
||||
|
||||
/* precalculate intermediate state from key
|
||||
*/
|
||||
void hmac_md5_precalc(HMAC_MD5_STATE *hmac,
|
||||
const unsigned char *key, int key_len);
|
||||
|
||||
/* initialize context from intermediate state
|
||||
*/
|
||||
void hmac_md5_import(HMAC_MD5_CTX *hmac, HMAC_MD5_STATE *state);
|
||||
|
||||
#define hmac_md5_update(hmac, text, text_len) MD5Update(&(hmac)->ictx, (text), (text_len))
|
||||
|
||||
/* finish hmac from intermediate result. Intermediate result is zeroed.
|
||||
*/
|
||||
void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE],
|
||||
HMAC_MD5_CTX *hmac);
|
||||
|
||||
}
|
||||
|
||||
#endif /* HMAC_MD5_H */
|
|
@ -155,6 +155,18 @@ static inline uint64_t div128_64(uint64_t dividend_hi, uint64_t dividend_lo, uin
|
|||
return remainder;
|
||||
}
|
||||
|
||||
// Calculates a*b/c, using 128-bit precision to avoid overflow. This assumes that the result is
|
||||
// 64-bits, but only checks it (via assertion) in debug builds. As such you should only call this
|
||||
// when this is true: for instance, when c is known to be greater than either a or b.
|
||||
static inline uint64_t mul128_div64(uint64_t a, uint64_t b, uint64_t c) {
|
||||
uint64_t hi;
|
||||
uint64_t lo = mul128(a, b, &hi);
|
||||
uint64_t resulthi, resultlo;
|
||||
div128_64(hi, lo, c, &resulthi, &resultlo);
|
||||
assert(resulthi == 0);
|
||||
return resultlo;
|
||||
}
|
||||
|
||||
#define IDENT16(x) ((uint16_t) (x))
|
||||
#define IDENT32(x) ((uint32_t) (x))
|
||||
#define IDENT64(x) ((uint64_t) (x))
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2005 - DINH Viet Hoa
|
||||
* 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 libEtPan! project 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 AUTHORS 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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: md5.h,v 1.1.1.1 2005/03/18 20:17:27 zautrix Exp $
|
||||
*/
|
||||
|
||||
/* MD5.H - header file for MD5C.C
|
||||
*/
|
||||
|
||||
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
|
||||
rights reserved.
|
||||
|
||||
License to copy and use this software is granted provided that it
|
||||
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
|
||||
Algorithm" in all material mentioning or referencing this software
|
||||
or this function.
|
||||
|
||||
License is also granted to make and use derivative works provided
|
||||
that such works are identified as "derived from the RSA Data
|
||||
Security, Inc. MD5 Message-Digest Algorithm" in all material
|
||||
mentioning or referencing the derived work.
|
||||
|
||||
RSA Data Security, Inc. makes no representations concerning either
|
||||
the merchantability of this software or the suitability of this
|
||||
software for any particular purpose. It is provided "as is"
|
||||
without express or implied warranty of any kind.
|
||||
These notices must be retained in any copies of any part of this
|
||||
documentation and/or software.
|
||||
*/
|
||||
#ifndef MD5_H
|
||||
#define MD5_H
|
||||
|
||||
|
||||
#include "md5global.h"
|
||||
|
||||
namespace md5
|
||||
{
|
||||
/* MD5 context. */
|
||||
typedef struct {
|
||||
UINT4 state[4]; /* state (ABCD) */
|
||||
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
|
||||
unsigned char buffer[64]; /* input buffer */
|
||||
} MD5_CTX;
|
||||
|
||||
static void MD5Init(MD5_CTX * context);
|
||||
static void MD5Update( MD5_CTX *context, const unsigned char *input, unsigned int inputLen );
|
||||
static void MD5Final ( unsigned char digest[16], MD5_CTX *context );
|
||||
static inline void hmac_md5(const unsigned char* text, int text_len, const unsigned char* key, int key_len, unsigned char *digest);
|
||||
|
||||
|
||||
inline bool md5( unsigned char *input, int ilen, unsigned char output[16] )
|
||||
{
|
||||
MD5_CTX ctx;
|
||||
|
||||
MD5Init( &ctx );
|
||||
MD5Update( &ctx, input, ilen );
|
||||
MD5Final( output, &ctx);
|
||||
|
||||
memwipe( &ctx, sizeof( MD5_CTX ));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#include "md5_l.inl"
|
||||
|
||||
#endif
|
|
@ -1,560 +0,0 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2005 - DINH Viet Hoa
|
||||
* 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 libEtPan! project 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 AUTHORS 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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: md5.c,v 1.1.1.1 2005/03/18 20:17:27 zautrix Exp $
|
||||
*/
|
||||
|
||||
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
|
||||
*/
|
||||
|
||||
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
|
||||
rights reserved.
|
||||
|
||||
License to copy and use this software is granted provided that it
|
||||
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
|
||||
Algorithm" in all material mentioning or referencing this software
|
||||
or this function.
|
||||
|
||||
License is also granted to make and use derivative works provided
|
||||
that such works are identified as "derived from the RSA Data
|
||||
Security, Inc. MD5 Message-Digest Algorithm" in all material
|
||||
mentioning or referencing the derived work.
|
||||
|
||||
RSA Data Security, Inc. makes no representations concerning either
|
||||
the merchantability of this software or the suitability of this
|
||||
software for any particular purpose. It is provided "as is"
|
||||
without express or implied warranty of any kind.
|
||||
|
||||
These notices must be retained in any copies of any part of this
|
||||
documentation and/or software.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <winsock2.h>
|
||||
#else
|
||||
# include <arpa/inet.h>
|
||||
#endif
|
||||
#include "md5global.h"
|
||||
#include "md5_l.h"
|
||||
#include "hmac-md5.h"
|
||||
|
||||
namespace md5
|
||||
{
|
||||
/* Constants for MD5Transform routine.
|
||||
*/
|
||||
|
||||
#define S11 7
|
||||
#define S12 12
|
||||
#define S13 17
|
||||
#define S14 22
|
||||
#define S21 5
|
||||
#define S22 9
|
||||
#define S23 14
|
||||
#define S24 20
|
||||
#define S31 4
|
||||
#define S32 11
|
||||
#define S33 16
|
||||
#define S34 23
|
||||
#define S41 6
|
||||
#define S42 10
|
||||
#define S43 15
|
||||
#define S44 21
|
||||
|
||||
/*
|
||||
static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
|
||||
static void Encode PROTO_LIST
|
||||
((unsigned char *, UINT4 *, unsigned int));
|
||||
static void Decode PROTO_LIST
|
||||
((UINT4 *, unsigned char *, unsigned int));
|
||||
static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
|
||||
static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
|
||||
*/
|
||||
|
||||
static void MD5_memcpy (POINTER output, POINTER input, unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
output[i] = input[i];
|
||||
}
|
||||
|
||||
/* Note: Replace "for loop" with standard memset if possible.
|
||||
*/
|
||||
|
||||
static void MD5_memset (POINTER output, int value, unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
((char *)output)[i] = (char)value;
|
||||
}
|
||||
|
||||
static void MD5Transform (UINT4 state[4], unsigned char block[64]);
|
||||
|
||||
static unsigned char* PADDING()
|
||||
{
|
||||
static unsigned char local_PADDING[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
return local_PADDING;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* F, G, H and I are basic MD5 functions.
|
||||
|
||||
*/
|
||||
#ifdef I
|
||||
/* This might be defined via NANA */
|
||||
#undef I
|
||||
#endif
|
||||
|
||||
#define MD5_M_F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||
#define MD5_M_G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||
#define MD5_M_H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define MD5_M_I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||
|
||||
/* ROTATE_LEFT rotates x left n bits.
|
||||
|
||||
*/
|
||||
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
|
||||
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
|
||||
Rotation is separate from addition to prevent recomputation.
|
||||
*/
|
||||
|
||||
#define FF(a, b, c, d, x, s, ac) { (a) += MD5_M_F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
|
||||
#define GG(a, b, c, d, x, s, ac) { (a) += MD5_M_G ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
|
||||
#define HH(a, b, c, d, x, s, ac) { (a) += MD5_M_H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
|
||||
#define II(a, b, c, d, x, s, ac) { (a) += MD5_M_I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
|
||||
|
||||
/* MD5 initialization. Begins an MD5 operation, writing a new context.
|
||||
*/
|
||||
|
||||
static void MD5Init(MD5_CTX * context)
|
||||
{
|
||||
context->count[0] = context->count[1] = 0;
|
||||
|
||||
/* Load magic initialization constants.
|
||||
|
||||
*/
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xefcdab89;
|
||||
context->state[2] = 0x98badcfe;
|
||||
context->state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
/* MD5 block update operation. Continues an MD5 message-digest
|
||||
operation, processing another message block, and updating the context.
|
||||
*/
|
||||
|
||||
static void MD5Update( MD5_CTX *context, const unsigned char *input, unsigned int inputLen )
|
||||
{
|
||||
unsigned int i, index, partLen;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
|
||||
|
||||
/* Update number of bits */
|
||||
if ((context->count[0] += ((UINT4)inputLen << 3))
|
||||
< ((UINT4)inputLen << 3))
|
||||
context->count[1]++;
|
||||
context->count[1] += ((UINT4)inputLen >> 29);
|
||||
|
||||
partLen = 64 - index;
|
||||
|
||||
/* Transform as many times as possible.
|
||||
|
||||
*/
|
||||
if (inputLen >= partLen)
|
||||
{
|
||||
MD5_memcpy( (POINTER)&context->buffer[index], (POINTER)input, partLen );
|
||||
MD5Transform( context->state, context->buffer );
|
||||
|
||||
for (i = partLen; i + 63 < inputLen; i += 64)
|
||||
MD5Transform (context->state, (unsigned char*)&input[i]);
|
||||
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
i = 0;
|
||||
|
||||
/* Buffer remaining input */
|
||||
MD5_memcpy( (POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i );
|
||||
|
||||
}
|
||||
|
||||
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
|
||||
a multiple of 4.
|
||||
|
||||
*/
|
||||
|
||||
static void Encode (unsigned char *output, UINT4 *input, unsigned int len)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4) {
|
||||
output[j] = (unsigned char)(input[i] & 0xff);
|
||||
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
|
||||
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
|
||||
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
|
||||
a multiple of 4.
|
||||
|
||||
*/
|
||||
|
||||
static void Decode (UINT4 *output, unsigned char *input, unsigned int len)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16)
|
||||
| (((UINT4)input[j+3]) << 24);
|
||||
}
|
||||
|
||||
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
|
||||
the message digest and zeroizing the context.
|
||||
|
||||
*/
|
||||
|
||||
static void MD5Final ( unsigned char digest[16], MD5_CTX *context )
|
||||
{
|
||||
unsigned char bits[8];
|
||||
unsigned int index, padLen;
|
||||
|
||||
/* Save number of bits */
|
||||
Encode (bits, context->count, 8);
|
||||
|
||||
/* Pad out to 56 mod 64.
|
||||
|
||||
*/
|
||||
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
|
||||
padLen = (index < 56) ? (56 - index) : (120 - index);
|
||||
MD5Update (context, PADDING(), padLen);
|
||||
|
||||
/* Append length (before padding) */
|
||||
MD5Update (context, bits, 8);
|
||||
|
||||
/* Store state in digest */
|
||||
Encode (digest, context->state, 16);
|
||||
|
||||
/* Zeroize sensitive information.
|
||||
|
||||
*/
|
||||
MD5_memset ((POINTER)context, 0, sizeof (*context));
|
||||
}
|
||||
|
||||
/* MD5 basic transformation. Transforms state based on block.
|
||||
|
||||
*/
|
||||
|
||||
static void MD5Transform (UINT4 state[4], unsigned char block[64])
|
||||
{
|
||||
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||
|
||||
Decode (x, block, 64);
|
||||
|
||||
/* Round 1 */
|
||||
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
|
||||
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
|
||||
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
|
||||
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
|
||||
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
|
||||
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
|
||||
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
|
||||
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
|
||||
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
|
||||
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
|
||||
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
|
||||
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
|
||||
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
|
||||
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
|
||||
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
|
||||
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
|
||||
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
|
||||
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
|
||||
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
|
||||
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
|
||||
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
|
||||
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
|
||||
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
|
||||
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
|
||||
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
|
||||
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
|
||||
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
|
||||
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
|
||||
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
|
||||
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
|
||||
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
|
||||
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
|
||||
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
|
||||
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
|
||||
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
|
||||
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
|
||||
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
|
||||
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
|
||||
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
|
||||
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
|
||||
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
|
||||
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
|
||||
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
|
||||
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
|
||||
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
|
||||
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
|
||||
|
||||
/* Round 4 */
|
||||
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
|
||||
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
|
||||
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
|
||||
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
|
||||
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
|
||||
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
|
||||
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
|
||||
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
|
||||
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
|
||||
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
|
||||
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
|
||||
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
|
||||
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
|
||||
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
|
||||
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
|
||||
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
|
||||
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
|
||||
/* Zeroize sensitive information.
|
||||
*/
|
||||
MD5_memset ((POINTER)x, 0, sizeof (x));
|
||||
}
|
||||
|
||||
/* Note: Replace "for loop" with standard memcpy if possible.
|
||||
|
||||
*/
|
||||
inline
|
||||
void hmac_md5_init(HMAC_MD5_CTX *hmac,
|
||||
const unsigned char *key,
|
||||
int key_len)
|
||||
{
|
||||
unsigned char k_ipad[65]; /* inner padding -
|
||||
* key XORd with ipad
|
||||
*/
|
||||
unsigned char k_opad[65]; /* outer padding -
|
||||
* key XORd with opad
|
||||
*/
|
||||
unsigned char tk[16];
|
||||
int i;
|
||||
/* if key is longer than 64 bytes reset it to key=MD5(key) */
|
||||
if (key_len > 64) {
|
||||
|
||||
MD5_CTX tctx;
|
||||
|
||||
MD5Init(&tctx);
|
||||
MD5Update(&tctx, key, key_len);
|
||||
MD5Final(tk, &tctx);
|
||||
|
||||
key = tk;
|
||||
key_len = 16;
|
||||
}
|
||||
|
||||
/*
|
||||
* the HMAC_MD5 transform looks like:
|
||||
*
|
||||
* MD5(K XOR opad, MD5(K XOR ipad, text))
|
||||
*
|
||||
* where K is an n byte key
|
||||
* ipad is the byte 0x36 repeated 64 times
|
||||
* opad is the byte 0x5c repeated 64 times
|
||||
* and text is the data being protected
|
||||
*/
|
||||
|
||||
/* start out by storing key in pads */
|
||||
MD5_memset(k_ipad, '\0', sizeof k_ipad);
|
||||
MD5_memset(k_opad, '\0', sizeof k_opad);
|
||||
MD5_memcpy( k_ipad, (POINTER)key, key_len);
|
||||
MD5_memcpy( k_opad, (POINTER)key, key_len);
|
||||
|
||||
/* XOR key with ipad and opad values */
|
||||
for (i=0; i<64; i++) {
|
||||
k_ipad[i] ^= 0x36;
|
||||
k_opad[i] ^= 0x5c;
|
||||
}
|
||||
|
||||
MD5Init(&hmac->ictx); /* init inner context */
|
||||
MD5Update(&hmac->ictx, k_ipad, 64); /* apply inner pad */
|
||||
|
||||
MD5Init(&hmac->octx); /* init outer context */
|
||||
MD5Update(&hmac->octx, k_opad, 64); /* apply outer pad */
|
||||
|
||||
/* scrub the pads and key context (if used) */
|
||||
MD5_memset( (POINTER)&k_ipad, 0, sizeof(k_ipad));
|
||||
MD5_memset( (POINTER)&k_opad, 0, sizeof(k_opad));
|
||||
MD5_memset( (POINTER)&tk, 0, sizeof(tk));
|
||||
|
||||
/* and we're done. */
|
||||
}
|
||||
|
||||
/* The precalc and import routines here rely on the fact that we pad
|
||||
* the key out to 64 bytes and use that to initialize the md5
|
||||
* contexts, and that updating an md5 context with 64 bytes of data
|
||||
* leaves nothing left over; all of the interesting state is contained
|
||||
* in the state field, and none of it is left over in the count and
|
||||
* buffer fields. So all we have to do is save the state field; we
|
||||
* can zero the others when we reload it. Which is why the decision
|
||||
* was made to pad the key out to 64 bytes in the first place. */
|
||||
inline
|
||||
void hmac_md5_precalc(HMAC_MD5_STATE *state,
|
||||
const unsigned char *key,
|
||||
int key_len)
|
||||
{
|
||||
HMAC_MD5_CTX hmac;
|
||||
unsigned lupe;
|
||||
|
||||
hmac_md5_init(&hmac, key, key_len);
|
||||
for (lupe = 0; lupe < 4; lupe++) {
|
||||
state->istate[lupe] = htonl(hmac.ictx.state[lupe]);
|
||||
state->ostate[lupe] = htonl(hmac.octx.state[lupe]);
|
||||
}
|
||||
MD5_memset( (POINTER)&hmac, 0, sizeof(hmac));
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
void hmac_md5_import(HMAC_MD5_CTX *hmac,
|
||||
HMAC_MD5_STATE *state)
|
||||
{
|
||||
unsigned lupe;
|
||||
MD5_memset( (POINTER)hmac, 0, sizeof(HMAC_MD5_CTX));
|
||||
for (lupe = 0; lupe < 4; lupe++) {
|
||||
hmac->ictx.state[lupe] = ntohl(state->istate[lupe]);
|
||||
hmac->octx.state[lupe] = ntohl(state->ostate[lupe]);
|
||||
}
|
||||
/* Init the counts to account for our having applied
|
||||
* 64 bytes of key; this works out to 0x200 (64 << 3; see
|
||||
* MD5Update above...) */
|
||||
hmac->ictx.count[0] = hmac->octx.count[0] = 0x200;
|
||||
}
|
||||
|
||||
inline
|
||||
void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE],
|
||||
HMAC_MD5_CTX *hmac)
|
||||
{
|
||||
MD5Final(digest, &hmac->ictx); /* Finalize inner md5 */
|
||||
MD5Update(&hmac->octx, digest, 16); /* Update outer ctx */
|
||||
MD5Final(digest, &hmac->octx); /* Finalize outer md5 */
|
||||
}
|
||||
|
||||
|
||||
void hmac_md5(const unsigned char* text, int text_len, const unsigned char* key, int key_len, unsigned char *digest)
|
||||
{
|
||||
MD5_CTX context;
|
||||
|
||||
unsigned char k_ipad[65]; /* inner padding -
|
||||
* key XORd with ipad
|
||||
*/
|
||||
unsigned char k_opad[65]; /* outer padding -
|
||||
* key XORd with opad
|
||||
*/
|
||||
unsigned char tk[16];
|
||||
int i;
|
||||
/* if key is longer than 64 bytes reset it to key=MD5(key) */
|
||||
if (key_len > 64) {
|
||||
|
||||
MD5_CTX tctx;
|
||||
|
||||
MD5Init(&tctx);
|
||||
MD5Update(&tctx, key, key_len);
|
||||
MD5Final(tk, &tctx);
|
||||
|
||||
key = tk;
|
||||
key_len = 16;
|
||||
}
|
||||
|
||||
/*
|
||||
* the HMAC_MD5 transform looks like:
|
||||
*
|
||||
* MD5(K XOR opad, MD5(K XOR ipad, text))
|
||||
*
|
||||
* where K is an n byte key
|
||||
* ipad is the byte 0x36 repeated 64 times
|
||||
* opad is the byte 0x5c repeated 64 times
|
||||
* and text is the data being protected
|
||||
*/
|
||||
|
||||
/* start out by storing key in pads */
|
||||
MD5_memset(k_ipad, '\0', sizeof k_ipad);
|
||||
MD5_memset(k_opad, '\0', sizeof k_opad);
|
||||
MD5_memcpy( k_ipad, (POINTER)key, key_len);
|
||||
MD5_memcpy( k_opad, (POINTER)key, key_len);
|
||||
|
||||
/* XOR key with ipad and opad values */
|
||||
for (i=0; i<64; i++) {
|
||||
k_ipad[i] ^= 0x36;
|
||||
k_opad[i] ^= 0x5c;
|
||||
}
|
||||
/*
|
||||
* perform inner MD5
|
||||
*/
|
||||
|
||||
MD5Init(&context); /* init context for 1st
|
||||
* pass */
|
||||
MD5Update(&context, k_ipad, 64); /* start with inner pad */
|
||||
MD5Update(&context, text, text_len); /* then text of datagram */
|
||||
MD5Final(digest, &context); /* finish up 1st pass */
|
||||
|
||||
/*
|
||||
* perform outer MD5
|
||||
*/
|
||||
MD5Init(&context); /* init context for 2nd
|
||||
* pass */
|
||||
MD5Update(&context, k_opad, 64); /* start with outer pad */
|
||||
MD5Update(&context, digest, 16); /* then results of 1st
|
||||
* hash */
|
||||
MD5Final(digest, &context); /* finish up 2nd pass */
|
||||
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* libEtPan! -- a mail stuff library
|
||||
*
|
||||
* Copyright (C) 2001, 2005 - DINH Viet Hoa
|
||||
* 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 libEtPan! project 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 AUTHORS 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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: md5global.h,v 1.1.1.1 2005/03/18 20:17:28 zautrix Exp $
|
||||
*/
|
||||
|
||||
/* GLOBAL.H - RSAREF types and constants
|
||||
*/
|
||||
|
||||
#ifndef MD5GLOBAL_H
|
||||
#define MD5GLOBAL_H
|
||||
|
||||
namespace md5
|
||||
{
|
||||
|
||||
|
||||
/* PROTOTYPES should be set to one if and only if the compiler supports
|
||||
function argument prototyping.
|
||||
The following makes PROTOTYPES default to 0 if it has not already
|
||||
been defined with C compiler flags.
|
||||
*/
|
||||
#ifndef PROTOTYPES
|
||||
#define PROTOTYPES 0
|
||||
#endif
|
||||
|
||||
/* POINTER defines a generic pointer type */
|
||||
typedef unsigned char *POINTER;
|
||||
|
||||
/* UINT2 defines a two byte word */
|
||||
typedef unsigned short int UINT2;
|
||||
|
||||
/* UINT4 defines a four byte word */
|
||||
//typedef unsigned long int UINT4;
|
||||
typedef unsigned int UINT4;
|
||||
|
||||
/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
|
||||
If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
|
||||
returns an empty list.
|
||||
*/
|
||||
#if PROTOTYPES
|
||||
#define PROTO_LIST(list) list
|
||||
#else
|
||||
#define PROTO_LIST(list) ()
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,161 +0,0 @@
|
|||
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the Andrey N. Sabelnikov nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace epee
|
||||
{
|
||||
#define STD_TRY_BEGIN() try {
|
||||
|
||||
#define STD_TRY_CATCH(where_, ret_val) \
|
||||
} \
|
||||
catch (const std::exception &e) \
|
||||
{ \
|
||||
LOG_ERROR("EXCEPTION: " << where_ << ", mes: "<< e.what()); \
|
||||
return ret_val; \
|
||||
} \
|
||||
catch (...) \
|
||||
{ \
|
||||
LOG_ERROR("EXCEPTION: " << where_ ); \
|
||||
return ret_val; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace misc_utils
|
||||
{
|
||||
template<typename t_type>
|
||||
t_type get_max_t_val(t_type t)
|
||||
{
|
||||
return (std::numeric_limits<t_type>::max)();
|
||||
}
|
||||
|
||||
|
||||
template<typename t_iterator>
|
||||
t_iterator move_it_forward(t_iterator it, size_t count)
|
||||
{
|
||||
while(count--)
|
||||
it++;
|
||||
return it;
|
||||
}
|
||||
|
||||
template<typename t_iterator>
|
||||
t_iterator move_it_backward(t_iterator it, size_t count)
|
||||
{
|
||||
while(count--)
|
||||
it--;
|
||||
return it;
|
||||
}
|
||||
|
||||
|
||||
// TEMPLATE STRUCT less
|
||||
template<class _Ty>
|
||||
struct less_as_pod
|
||||
: public std::binary_function<_Ty, _Ty, bool>
|
||||
{ // functor for operator<
|
||||
bool operator()(const _Ty& _Left, const _Ty& _Right) const
|
||||
{ // apply operator< to operands
|
||||
return memcmp(&_Left, &_Right, sizeof(_Left)) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<class _Ty>
|
||||
bool is_less_as_pod(const _Ty& _Left, const _Ty& _Right)
|
||||
{ // apply operator< to operands
|
||||
return memcmp(&_Left, &_Right, sizeof(_Left)) < 0;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
void sleep_no_w(long ms)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds{ms});
|
||||
}
|
||||
|
||||
template<class type_vec_type>
|
||||
type_vec_type median(std::vector<type_vec_type> &v)
|
||||
{
|
||||
if(v.empty())
|
||||
return type_vec_type{};
|
||||
if(v.size() == 1)
|
||||
return v[0];
|
||||
|
||||
size_t n = (v.size()) / 2;
|
||||
std::sort(v.begin(), v.end());
|
||||
//nth_element(v.begin(), v.begin()+n-1, v.end());
|
||||
if(v.size()%2)
|
||||
{//1, 3, 5...
|
||||
return v[n];
|
||||
}else
|
||||
{//2, 4, 6...
|
||||
return (v[n-1] + v[n])/2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
|
||||
struct call_befor_die_base
|
||||
{
|
||||
virtual ~call_befor_die_base(){}
|
||||
};
|
||||
|
||||
using auto_scope_leave_caller = std::shared_ptr<call_befor_die_base>;
|
||||
|
||||
|
||||
template<class t_scope_leave_handler>
|
||||
struct call_befor_die: public call_befor_die_base
|
||||
{
|
||||
t_scope_leave_handler m_func;
|
||||
call_befor_die(t_scope_leave_handler f):m_func(f)
|
||||
{}
|
||||
~call_befor_die()
|
||||
{
|
||||
try { m_func(); }
|
||||
catch (...) { /* ignore */ }
|
||||
}
|
||||
};
|
||||
|
||||
template<class t_scope_leave_handler>
|
||||
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
|
||||
{
|
||||
auto_scope_leave_caller slc(new call_befor_die<t_scope_leave_handler>(f));
|
||||
return slc;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -37,7 +37,7 @@
|
|||
#include <boost/asio/steady_timer.hpp>
|
||||
#include "../warnings.h"
|
||||
#include "../string_tools.h"
|
||||
#include "../misc_language.h"
|
||||
#include "../scope_leaver.h"
|
||||
#include "local_ip.h"
|
||||
#include "../pragma_comp_defs.h"
|
||||
|
||||
|
@ -431,7 +431,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
|
|||
//ask it inside(!) critical region if we still able to go in event wait...
|
||||
size_t cnt = GET_IO_SERVICE(socket()).poll_one();
|
||||
if(!cnt)
|
||||
misc_utils::sleep_no_w(1);
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1200,7 +1200,7 @@ POP_WARNINGS
|
|||
// error path, if e or exception
|
||||
assert(m_state != nullptr); // always set in constructor
|
||||
MERROR("Some problems at accept: " << e.message() << ", connections_count = " << m_state->sock_count);
|
||||
misc_utils::sleep_no_w(100);
|
||||
std::this_thread::sleep_for(100ms);
|
||||
(*current_new_connection).reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type));
|
||||
current_acceptor->async_accept((*current_new_connection)->socket(),
|
||||
boost::bind(accept_function_pointer, this,
|
||||
|
@ -1315,7 +1315,7 @@ POP_WARNINGS
|
|||
connections_.insert(new_connection_l);
|
||||
MDEBUG("connections_ size now " << connections_.size());
|
||||
connections_mutex.unlock();
|
||||
epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ std::lock_guard lock{connections_mutex}; connections_.erase(new_connection_l); });
|
||||
auto scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ std::lock_guard lock{connections_mutex}; connections_.erase(new_connection_l); });
|
||||
boost::asio::ip::tcp::socket& sock_ = new_connection_l->socket();
|
||||
|
||||
bool try_ipv6 = false;
|
||||
|
@ -1431,7 +1431,7 @@ POP_WARNINGS
|
|||
connections_.insert(new_connection_l);
|
||||
MDEBUG("connections_ size now " << connections_.size());
|
||||
connections_mutex.unlock();
|
||||
epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ std::lock_guard lock{connections_mutex}; connections_.erase(new_connection_l); });
|
||||
auto scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ std::lock_guard lock{connections_mutex}; connections_.erase(new_connection_l); });
|
||||
boost::asio::ip::tcp::socket& sock_ = new_connection_l->socket();
|
||||
|
||||
bool try_ipv6 = false;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "levin_base.h"
|
||||
#include "buffer.h"
|
||||
#include "../misc_language.h"
|
||||
#include "../scope_leaver.h"
|
||||
#include "../int-util.h"
|
||||
|
||||
#include <random>
|
||||
|
@ -323,7 +324,7 @@ public:
|
|||
|
||||
for (size_t i = 0; i < 60 * 1000 / 100 && 0 != m_wait_count; ++i)
|
||||
{
|
||||
misc_utils::sleep_no_w(100);
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
CHECK_AND_ASSERT_MES_NO_RET(0 == m_wait_count, "Failed to wait for operation completion. m_wait_count = " << m_wait_count);
|
||||
|
||||
|
@ -385,7 +386,7 @@ public:
|
|||
|
||||
void request_callback()
|
||||
{
|
||||
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
auto scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
[this] { return finish_outer_call(); });
|
||||
|
||||
m_pservice_endpoint->request_callback();
|
||||
|
@ -616,7 +617,7 @@ public:
|
|||
template<class callback_t>
|
||||
bool async_invoke(int command, const epee::span<const uint8_t> in_buff, const callback_t &cb, std::chrono::nanoseconds timeout = 0ns)
|
||||
{
|
||||
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
auto scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
[this] { return finish_outer_call(); });
|
||||
|
||||
if(timeout == 0ns)
|
||||
|
@ -671,7 +672,7 @@ public:
|
|||
|
||||
int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out)
|
||||
{
|
||||
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
auto scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
[this] { return finish_outer_call(); });
|
||||
|
||||
if(m_deletion_initiated)
|
||||
|
@ -722,7 +723,7 @@ public:
|
|||
|
||||
int notify(int command, const epee::span<const uint8_t> in_buff)
|
||||
{
|
||||
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
auto scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
[this] { return finish_outer_call(); });
|
||||
|
||||
if(m_deletion_initiated)
|
||||
|
@ -750,7 +751,7 @@ public:
|
|||
\return 1 on success */
|
||||
int send(shared_sv message)
|
||||
{
|
||||
const misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
auto scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
[this] { return finish_outer_call(); });
|
||||
|
||||
if(m_deletion_initiated)
|
||||
|
|
|
@ -24,59 +24,40 @@
|
|||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "misc_language.h"
|
||||
|
||||
namespace epee
|
||||
namespace epee::misc_utils
|
||||
{
|
||||
namespace tests
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
|
||||
template <typename Callback>
|
||||
class scope_leave_handler_impl
|
||||
{
|
||||
bool test_median()
|
||||
Callback m_func;
|
||||
|
||||
public:
|
||||
scope_leave_handler_impl(Callback f) : m_func(std::move(f)) {}
|
||||
|
||||
~scope_leave_handler_impl()
|
||||
{
|
||||
LOG_PRINT_L0("Testing median");
|
||||
std::vector<size_t> sz;
|
||||
size_t m = misc_utils::median(sz);
|
||||
CHECK_AND_ASSERT_MES(m == 0, false, "test failed");
|
||||
sz.push_back(1);
|
||||
m = misc_utils::median(sz);
|
||||
CHECK_AND_ASSERT_MES(m == 1, false, "test failed");
|
||||
sz.push_back(10);
|
||||
m = misc_utils::median(sz);
|
||||
CHECK_AND_ASSERT_MES(m == 5, false, "test failed");
|
||||
|
||||
sz.clear();
|
||||
sz.resize(3);
|
||||
sz[0] = 0;
|
||||
sz[1] = 9;
|
||||
sz[2] = 3;
|
||||
m = misc_utils::median(sz);
|
||||
CHECK_AND_ASSERT_MES(m == 3, false, "test failed");
|
||||
|
||||
sz.clear();
|
||||
sz.resize(4);
|
||||
sz[0] = 77;
|
||||
sz[1] = 9;
|
||||
sz[2] = 22;
|
||||
sz[3] = 60;
|
||||
m = misc_utils::median(sz);
|
||||
CHECK_AND_ASSERT_MES(m == 41, false, "test failed");
|
||||
|
||||
|
||||
|
||||
sz.clear();
|
||||
sz.resize(5);
|
||||
sz[0] = 77;
|
||||
sz[1] = 9;
|
||||
sz[2] = 22;
|
||||
sz[3] = 60;
|
||||
sz[4] = 11;
|
||||
m = misc_utils::median(sz);
|
||||
CHECK_AND_ASSERT_MES(m == 22, false, "test failed");
|
||||
return true;
|
||||
try { m_func(); }
|
||||
catch (...) { /* ignore */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Moveable, Non-copyable
|
||||
scope_leave_handler_impl(const scope_leave_handler_impl&) = delete;
|
||||
scope_leave_handler_impl& operator=(const scope_leave_handler_impl&) = delete;
|
||||
scope_leave_handler_impl(scope_leave_handler_impl&&) = default;
|
||||
scope_leave_handler_impl& operator=(scope_leave_handler_impl&&) = default;
|
||||
};
|
||||
|
||||
template <typename Callback>
|
||||
auto create_scope_leave_handler(Callback f)
|
||||
{
|
||||
return scope_leave_handler_impl(std::move(f));
|
||||
}
|
||||
|
||||
}
|
|
@ -158,8 +158,8 @@ public: \
|
|||
using int_t = std::underlying_type_t<enum_t>; \
|
||||
int_t int_value = is_store ? static_cast<int_t>(this_ref.enum_) : 0; \
|
||||
epee::serialization::perform_serialize<is_store>(int_value, stg, parent_section, #enum_); \
|
||||
if (!is_store) \
|
||||
const_cast<enum_t&>(this_ref.enum_) = static_cast<enum_t>(int_value); \
|
||||
if constexpr (!is_store) \
|
||||
this_ref.enum_ = static_cast<enum_t>(int_value); \
|
||||
} while(0);
|
||||
|
||||
// Stashes `this` in the storage object's context for a dependent type that needs to access it.
|
||||
|
|
|
@ -82,19 +82,19 @@ namespace epee
|
|||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
template<class t_type, class t_storage>
|
||||
static bool serialize_t_val(const t_type& d, t_storage& stg, section* parent_section, const char* pname)
|
||||
bool serialize_t_val(const t_type& d, t_storage& stg, section* parent_section, const char* pname)
|
||||
{
|
||||
return stg.set_value(pname, d, parent_section);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
template<class t_type, class t_storage>
|
||||
static bool unserialize_t_val(t_type& d, t_storage& stg, section* parent_section, const char* pname)
|
||||
bool unserialize_t_val(t_type& d, t_storage& stg, section* parent_section, const char* pname)
|
||||
{
|
||||
return stg.get_value(pname, d, parent_section);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
template<class t_type, class t_storage>
|
||||
static bool serialize_t_val_as_blob(const t_type& d, t_storage& stg, section* parent_section, const char* pname)
|
||||
bool serialize_t_val_as_blob(const t_type& d, t_storage& stg, section* parent_section, const char* pname)
|
||||
{
|
||||
assert_blob_serializable<t_type>();
|
||||
std::string blob((const char *)&d, sizeof(d));
|
||||
|
@ -102,7 +102,7 @@ namespace epee
|
|||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
template<class t_type, class t_storage>
|
||||
static bool unserialize_t_val_as_blob(t_type& d, t_storage& stg, section* parent_section, const char* pname)
|
||||
bool unserialize_t_val_as_blob(t_type& d, t_storage& stg, section* parent_section, const char* pname)
|
||||
{
|
||||
assert_blob_serializable<t_type>();
|
||||
std::string blob;
|
||||
|
@ -114,7 +114,7 @@ namespace epee
|
|||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
template<class serializible_type, class t_storage>
|
||||
static bool serialize_t_obj(const serializible_type& obj, t_storage& stg, section* parent_section, const char* pname)
|
||||
bool serialize_t_obj(const serializible_type& obj, t_storage& stg, section* parent_section, const char* pname)
|
||||
{
|
||||
section* child_section = stg.open_section(pname, parent_section, true);
|
||||
CHECK_AND_ASSERT_MES(child_section, false, "serialize_t_obj: failed to open/create section " << pname);
|
||||
|
@ -122,7 +122,7 @@ namespace epee
|
|||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
template<class serializible_type, class t_storage>
|
||||
static bool unserialize_t_obj(serializible_type& obj, t_storage& stg, section* parent_section, const char* pname)
|
||||
bool unserialize_t_obj(serializible_type& obj, t_storage& stg, section* parent_section, const char* pname)
|
||||
{
|
||||
section* child_section = stg.open_section(pname, parent_section, false);
|
||||
if(!child_section) return false;
|
||||
|
@ -130,7 +130,7 @@ namespace epee
|
|||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
template<class stl_container, class t_storage>
|
||||
static bool serialize_stl_container_t_val(const stl_container& container, t_storage& stg, section* parent_section, const char* pname)
|
||||
bool serialize_stl_container_t_val(const stl_container& container, t_storage& stg, section* parent_section, const char* pname)
|
||||
{
|
||||
using T = typename stl_container::value_type;
|
||||
if(!container.size()) return true;
|
||||
|
@ -142,7 +142,7 @@ namespace epee
|
|||
}
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
template<class stl_container, class t_storage>
|
||||
static bool unserialize_stl_container_t_val(stl_container& container, t_storage& stg, section* parent_section, const char* pname)
|
||||
bool unserialize_stl_container_t_val(stl_container& container, t_storage& stg, section* parent_section, const char* pname)
|
||||
{
|
||||
using T = typename stl_container::value_type;
|
||||
container.clear();
|
||||
|
@ -158,7 +158,7 @@ namespace epee
|
|||
}
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
template<typename T, size_t Size, class t_storage>
|
||||
static bool unserialize_stl_container_t_val(std::array<T, Size>& array, t_storage& stg, section* parent_section, const char* pname)
|
||||
bool unserialize_stl_container_t_val(std::array<T, Size>& array, t_storage& stg, section* parent_section, const char* pname)
|
||||
{
|
||||
static_assert(Size > 0, "cannot deserialize empty std::array");
|
||||
size_t next_i = 0;
|
||||
|
@ -171,7 +171,7 @@ namespace epee
|
|||
}
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
template<class stl_container, class t_storage>
|
||||
static bool serialize_stl_container_pod_val_as_blob(const stl_container& container, t_storage& stg, section* parent_section, const char* pname)
|
||||
bool serialize_stl_container_pod_val_as_blob(const stl_container& container, t_storage& stg, section* parent_section, const char* pname)
|
||||
{
|
||||
using T = typename stl_container::value_type;
|
||||
assert_blob_serializable<T>();
|
||||
|
@ -190,7 +190,7 @@ namespace epee
|
|||
}
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
template<class stl_container, class t_storage>
|
||||
static bool unserialize_stl_container_pod_val_as_blob(stl_container& container, t_storage& stg, section* parent_section, const char* pname)
|
||||
bool unserialize_stl_container_pod_val_as_blob(stl_container& container, t_storage& stg, section* parent_section, const char* pname)
|
||||
{
|
||||
using T = typename stl_container::value_type;
|
||||
assert_blob_serializable<T>();
|
||||
|
@ -220,7 +220,7 @@ namespace epee
|
|||
}
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
template<class stl_container, class t_storage>
|
||||
static bool serialize_stl_container_t_obj(const stl_container& container, t_storage& stg, section* parent_section, const char* pname)
|
||||
bool serialize_stl_container_t_obj(const stl_container& container, t_storage& stg, section* parent_section, const char* pname)
|
||||
{
|
||||
if (container.empty()) return true;
|
||||
auto* sec_array = stg.template make_array_t<section>(pname, parent_section);
|
||||
|
@ -233,7 +233,7 @@ namespace epee
|
|||
}
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
template<class stl_container, class t_storage>
|
||||
static bool unserialize_stl_container_t_obj(stl_container& container, t_storage& stg, section* parent_section, const char* pname)
|
||||
bool unserialize_stl_container_t_obj(stl_container& container, t_storage& stg, section* parent_section, const char* pname)
|
||||
{
|
||||
container.clear();
|
||||
auto* arr = stg.template get_array<section>(pname, parent_section);
|
||||
|
@ -245,7 +245,7 @@ namespace epee
|
|||
}
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
template<typename T, size_t Size, class t_storage>
|
||||
static bool unserialize_stl_container_t_obj(std::array<T, Size>& out, t_storage& stg, section* parent_section, const char* pname)
|
||||
bool unserialize_stl_container_t_obj(std::array<T, Size>& out, t_storage& stg, section* parent_section, const char* pname)
|
||||
{
|
||||
static_assert(Size > 0, "cannot deserialize empty std::array");
|
||||
auto* arr = stg.template get_array<section>(pname, parent_section);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
template<typename T, typename Tpod = T>
|
||||
class Stats
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include <math.h>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
#include "stats.h"
|
||||
|
@ -15,13 +15,13 @@ enum
|
|||
bit_kurtosis,
|
||||
};
|
||||
|
||||
static inline double square(double x)
|
||||
inline double square(double x)
|
||||
{
|
||||
return x * x;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline double interpolate(T v, T v0, double i0, T v1, double i1)
|
||||
double interpolate(T v, T v0, double i0, T v1, double i1)
|
||||
{
|
||||
return i0 + (i1 - i0) * (v - v0) / (v1 - v0);
|
||||
}
|
||||
|
@ -109,20 +109,30 @@ double Stats<T, Tpod>::get_mean() const
|
|||
return mean;
|
||||
}
|
||||
|
||||
inline constexpr double T_DIST_CRITICAL_975[101] = {
|
||||
-1, 12.706, 4.3027, 3.1824, 2.7765, 2.5706, 2.4469, 2.3646, 2.3060, 2.2622, 2.2281, 2.2010, 2.1788, 2.1604, 2.1448, 2.1315,
|
||||
2.1199, 2.1098, 2.1009, 2.0930, 2.0860, 2.0796, 2.0739, 2.0687, 2.0639, 2.0595, 2.0555, 2.0518, 2.0484, 2.0452, 2.0423, 2.0395,
|
||||
2.0369, 2.0345, 2.0322, 2.0301, 2.0281, 2.0262, 2.0244, 2.0227, 2.0211, 2.0195, 2.0181, 2.0167, 2.0154, 2.0141, 2.0129, 2.0117,
|
||||
2.0106, 2.0096, 2.0086, 2.0076, 2.0066, 2.0057, 2.0049, 2.0040, 2.0032, 2.0025, 2.0017, 2.0010, 2.0003, 1.9996, 1.9990, 1.9983,
|
||||
1.9977, 1.9971, 1.9966, 1.9960, 1.9955, 1.9949, 1.9944, 1.9939, 1.9935, 1.9930, 1.9925, 1.9921, 1.9917, 1.9913, 1.9908, 1.9905,
|
||||
1.9901, 1.9897, 1.9893, 1.9890, 1.9886, 1.9883, 1.9879, 1.9876, 1.9873, 1.9870, 1.9867, 1.9864, 1.9861, 1.9858, 1.9855, 1.9852,
|
||||
1.9850, 1.9847, 1.9845, 1.9842, 1.9840,
|
||||
};
|
||||
inline constexpr double T_DIST_CRITICAL_995[101] = {
|
||||
-1, 9.9250, 5.8408, 4.6041, 4.0321, 3.7074, 3.4995, 3.3554, 3.2498, 3.1693, 3.1058, 3.0545, 3.0123, 2.9768, 2.9467, 2.9208, 2.8982,
|
||||
2.8784, 2.8609, 2.8453, 2.8314, 2.8188, 2.8073, 2.7970, 2.7874, 2.7787, 2.7707, 2.7633, 2.7564, 2.7500, 2.7440, 2.7385, 2.7333,
|
||||
2.7284, 2.7238, 2.7195, 2.7154, 2.7116, 2.7079, 2.7045, 2.7012, 2.6981, 2.6951, 2.6923, 2.6896, 2.6870, 2.6846, 2.6822, 2.6800,
|
||||
2.6778, 2.6757, 2.6737, 2.6718, 2.6700, 2.6682, 2.6665, 2.6649, 2.6633, 2.6618, 2.6603, 2.6589, 2.6575, 2.6561, 2.6549, 2.6536,
|
||||
2.6524, 2.6512, 2.6501, 2.6490, 2.6479, 2.6469, 2.6458, 2.6449, 2.6439, 2.6430, 2.6421, 2.6412, 2.6403, 2.6395, 2.6387, 2.6379,
|
||||
2.6371, 2.6364, 2.6356, 2.6349, 2.6342, 2.6335, 2.6329, 2.6322, 2.6316, 2.6309, 2.6303, 2.6297, 2.6291, 2.6286, 2.6280, 2.6275,
|
||||
2.6269, 2.6264, 2.6259,
|
||||
};
|
||||
|
||||
template<typename T, typename Tpod>
|
||||
double Stats<T, Tpod>::get_cdf95(size_t df) const
|
||||
{
|
||||
static const double p[101] = {
|
||||
-1, 12.706, 4.3027, 3.1824, 2.7765, 2.5706, 2.4469, 2.3646, 2.3060, 2.2622, 2.2281, 2.2010, 2.1788, 2.1604, 2.1448, 2.1315,
|
||||
2.1199, 2.1098, 2.1009, 2.0930, 2.0860, 2.0796, 2.0739, 2.0687, 2.0639, 2.0595, 2.0555, 2.0518, 2.0484, 2.0452, 2.0423, 2.0395,
|
||||
2.0369, 2.0345, 2.0322, 2.0301, 2.0281, 2.0262, 2.0244, 2.0227, 2.0211, 2.0195, 2.0181, 2.0167, 2.0154, 2.0141, 2.0129, 2.0117,
|
||||
2.0106, 2.0096, 2.0086, 2.0076, 2.0066, 2.0057, 2.0049, 2.0040, 2.0032, 2.0025, 2.0017, 2.0010, 2.0003, 1.9996, 1.9990, 1.9983,
|
||||
1.9977, 1.9971, 1.9966, 1.9960, 1.9955, 1.9949, 1.9944, 1.9939, 1.9935, 1.9930, 1.9925, 1.9921, 1.9917, 1.9913, 1.9908, 1.9905,
|
||||
1.9901, 1.9897, 1.9893, 1.9890, 1.9886, 1.9883, 1.9879, 1.9876, 1.9873, 1.9870, 1.9867, 1.9864, 1.9861, 1.9858, 1.9855, 1.9852,
|
||||
1.9850, 1.9847, 1.9845, 1.9842, 1.9840,
|
||||
};
|
||||
if (df <= 100)
|
||||
return p[df];
|
||||
return T_DIST_CRITICAL_975[df];
|
||||
if (df <= 120)
|
||||
return interpolate<size_t>(df, 100, 1.9840, 120, 1.98);
|
||||
return 1.96;
|
||||
|
@ -137,17 +147,8 @@ double Stats<T, Tpod>::get_cdf95(const Stats<T> &other) const
|
|||
template<typename T, typename Tpod>
|
||||
double Stats<T, Tpod>::get_cdf99(size_t df) const
|
||||
{
|
||||
static const double p[101] = {
|
||||
-1, 9.9250, 5.8408, 4.6041, 4.0321, 3.7074, 3.4995, 3.3554, 3.2498, 3.1693, 3.1058, 3.0545, 3.0123, 2.9768, 2.9467, 2.9208, 2.8982,
|
||||
2.8784, 2.8609, 2.8453, 2.8314, 2.8188, 2.8073, 2.7970, 2.7874, 2.7787, 2.7707, 2.7633, 2.7564, 2.7500, 2.7440, 2.7385, 2.7333,
|
||||
2.7284, 2.7238, 2.7195, 2.7154, 2.7116, 2.7079, 2.7045, 2.7012, 2.6981, 2.6951, 2.6923, 2.6896, 2.6870, 2.6846, 2.6822, 2.6800,
|
||||
2.6778, 2.6757, 2.6737, 2.6718, 2.6700, 2.6682, 2.6665, 2.6649, 2.6633, 2.6618, 2.6603, 2.6589, 2.6575, 2.6561, 2.6549, 2.6536,
|
||||
2.6524, 2.6512, 2.6501, 2.6490, 2.6479, 2.6469, 2.6458, 2.6449, 2.6439, 2.6430, 2.6421, 2.6412, 2.6403, 2.6395, 2.6387, 2.6379,
|
||||
2.6371, 2.6364, 2.6356, 2.6349, 2.6342, 2.6335, 2.6329, 2.6322, 2.6316, 2.6309, 2.6303, 2.6297, 2.6291, 2.6286, 2.6280, 2.6275,
|
||||
2.6269, 2.6264, 2.6259,
|
||||
};
|
||||
if (df <= 100)
|
||||
return p[df];
|
||||
return T_DIST_CRITICAL_995[df];
|
||||
if (df <= 120)
|
||||
return interpolate<size_t>(df, 100, 2.6529, 120, 2.617);
|
||||
return 2.576;
|
||||
|
|
|
@ -24,31 +24,21 @@
|
|||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include "../misc_log_ex.h"
|
||||
|
||||
#undef OXEN_DEFAULT_LOG_CATEGORY
|
||||
#define OXEN_DEFAULT_LOG_CATEGORY "serialization"
|
||||
|
||||
namespace epee
|
||||
namespace epee::misc_utils::parse
|
||||
{
|
||||
namespace misc_utils
|
||||
{
|
||||
namespace parse
|
||||
{
|
||||
namespace detail {
|
||||
// 1: digit
|
||||
// 2: .eE (floating point)
|
||||
// 4: alpha
|
||||
// 8: whitespace
|
||||
// 16: allowed in float but doesn't necessarily mean it's a float
|
||||
// 32: \ and " (end of verbatim string)
|
||||
static const constexpr uint8_t lut[256]={
|
||||
inline constexpr uint8_t lut[256]={
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 0, 0, // 16
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32
|
||||
8, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 16, 18, 0, // 48
|
||||
|
@ -66,322 +56,12 @@ namespace misc_utils
|
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
static const constexpr unsigned char isx[256] =
|
||||
{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 10, 11, 12, 13, 14, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 10, 11, 12, 13, 14, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
};
|
||||
|
||||
inline bool isspace(char c)
|
||||
{
|
||||
return lut[(uint8_t)c] & 8;
|
||||
}
|
||||
|
||||
inline bool isdigit(char c)
|
||||
{
|
||||
return lut[(uint8_t)c] & 1;
|
||||
}
|
||||
|
||||
inline std::string transform_to_escape_sequence(const std::string& src)
|
||||
{
|
||||
static const char escaped[] = "\b\f\n\r\t\v\"\\/";
|
||||
auto it = std::find_first_of(src.begin(), src.end(), escaped, escaped + sizeof(escaped));
|
||||
if (it == src.end())
|
||||
return src;
|
||||
|
||||
std::string res;
|
||||
res.reserve(2 * src.size());
|
||||
res.assign(src.begin(), it);
|
||||
for(; it!=src.end(); ++it)
|
||||
{
|
||||
switch(*it)
|
||||
{
|
||||
case '\b': //Backspace (ascii code 08)
|
||||
res+="\\b"; break;
|
||||
case '\f': //Form feed (ascii code 0C)
|
||||
res+="\\f"; break;
|
||||
case '\n': //New line
|
||||
res+="\\n"; break;
|
||||
case '\r': //Carriage return
|
||||
res+="\\r"; break;
|
||||
case '\t': //Tab
|
||||
res+="\\t"; break;
|
||||
case '\v': //Vertical tab
|
||||
res+="\\v"; break;
|
||||
//case '\'': //Apostrophe or single quote
|
||||
// res+="\\'"; break;
|
||||
case '"': //Double quote
|
||||
res+="\\\""; break;
|
||||
case '\\': //Backslash caracter
|
||||
res+="\\\\"; break;
|
||||
case '/': //Backslash caracter
|
||||
res+="\\/"; break;
|
||||
default:
|
||||
res.push_back(*it);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
/*
|
||||
|
||||
\b Backspace (ascii code 08)
|
||||
\f Form feed (ascii code 0C)
|
||||
\n New line
|
||||
\r Carriage return
|
||||
\t Tab
|
||||
\v Vertical tab
|
||||
\' Apostrophe or single quote
|
||||
\" Double quote
|
||||
\\ Backslash character
|
||||
|
||||
*/
|
||||
template <typename It>
|
||||
inline void match_string2(It& star_end_string, It buf_end, std::string& val)
|
||||
{
|
||||
bool escape_mode = false;
|
||||
auto it = star_end_string;
|
||||
++it;
|
||||
auto fi = it;
|
||||
while (fi != buf_end && ((lut[(uint8_t)*fi] & 32)) == 0)
|
||||
++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 == '\\'*/)
|
||||
{
|
||||
switch(*it)
|
||||
{
|
||||
case 'b': //Backspace (ascii code 08)
|
||||
val.push_back(0x08);break;
|
||||
case 'f': //Form feed (ascii code 0C)
|
||||
val.push_back(0x0C);break;
|
||||
case 'n': //New line
|
||||
val.push_back('\n');break;
|
||||
case 'r': //Carriage return
|
||||
val.push_back('\r');break;
|
||||
case 't': //Tab
|
||||
val.push_back('\t');break;
|
||||
case 'v': //Vertical tab
|
||||
val.push_back('\v');break;
|
||||
case '\'': //Apostrophe or single quote
|
||||
val.push_back('\'');break;
|
||||
case '"': //Double quote
|
||||
val.push_back('"');break;
|
||||
case '\\': //Backslash character
|
||||
val.push_back('\\');break;
|
||||
case '/': //Slash character
|
||||
val.push_back('/');break;
|
||||
case 'u': //Unicode code point
|
||||
if (buf_end - it < 4)
|
||||
{
|
||||
ASSERT_MES_AND_THROW("Invalid Unicode escape sequence");
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t dst = 0;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
const unsigned char tmp = isx[(int)*++it];
|
||||
CHECK_AND_ASSERT_THROW_MES(tmp != 0xff, "Bad Unicode encoding");
|
||||
dst = dst << 4 | tmp;
|
||||
}
|
||||
// encode as UTF-8
|
||||
if (dst <= 0x7f)
|
||||
{
|
||||
val.push_back(dst);
|
||||
}
|
||||
else if (dst <= 0x7ff)
|
||||
{
|
||||
val.push_back(0xc0 | (dst >> 6));
|
||||
val.push_back(0x80 | (dst & 0x3f));
|
||||
}
|
||||
else if (dst <= 0xffff)
|
||||
{
|
||||
val.push_back(0xe0 | (dst >> 12));
|
||||
val.push_back(0x80 | ((dst >> 6) & 0x3f));
|
||||
val.push_back(0x80 | (dst & 0x3f));
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_MES_AND_THROW("Unicode code point is out or range");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
val.push_back(*it);
|
||||
LOG_PRINT_L0("Unknown escape sequence :\"\\" << *it << "\"");
|
||||
}
|
||||
escape_mode = false;
|
||||
}else if(*it == '"')
|
||||
{
|
||||
star_end_string = it;
|
||||
return;
|
||||
}else if(*it == '\\')
|
||||
{
|
||||
escape_mode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
val.push_back(*it);
|
||||
}
|
||||
}
|
||||
ASSERT_MES_AND_THROW("Failed to match string in json entry: " << std::string(star_end_string, buf_end));
|
||||
}
|
||||
template <typename It>
|
||||
bool match_string(It& star_end_string, It buf_end, std::string& val)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
match_string2(star_end_string, buf_end, val);
|
||||
return true;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
template <typename It>
|
||||
void match_number2(It& star_end_string, It buf_end, std::string_view& val, bool& is_float_val, bool& is_signed_val)
|
||||
{
|
||||
val = {};
|
||||
uint8_t float_flag = 0;
|
||||
is_signed_val = false;
|
||||
size_t chars = 0;
|
||||
auto it = star_end_string;
|
||||
if (it != buf_end && *it == '-')
|
||||
{
|
||||
is_signed_val = true;
|
||||
++chars;
|
||||
++it;
|
||||
}
|
||||
for(;it != buf_end;it++)
|
||||
{
|
||||
const uint8_t flags = lut[(uint8_t)*it];
|
||||
if (flags & 16)
|
||||
{
|
||||
float_flag |= flags;
|
||||
++chars;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = std::string_view(&*star_end_string, chars);
|
||||
if(val.size())
|
||||
{
|
||||
star_end_string = --it;
|
||||
is_float_val = !!(float_flag & 2);
|
||||
return;
|
||||
}
|
||||
else
|
||||
ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end));
|
||||
}
|
||||
}
|
||||
ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end));
|
||||
}
|
||||
template <typename It>
|
||||
bool match_number(It& star_end_string, It buf_end, std::string_view& val)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool is_v_float = false;bool is_signed_val = false;
|
||||
match_number2(star_end_string, buf_end, val, is_v_float, is_signed_val);
|
||||
return !is_v_float;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
template <typename It>
|
||||
void match_word2(It& star_end_string, It buf_end, std::string_view& val)
|
||||
{
|
||||
val = {};
|
||||
|
||||
for(auto it = star_end_string;it != buf_end;it++)
|
||||
{
|
||||
if (!(lut[(uint8_t)*it] & 4))
|
||||
{
|
||||
val = std::string_view(&*star_end_string, std::distance(star_end_string, it));
|
||||
if(val.size())
|
||||
{
|
||||
star_end_string = --it;
|
||||
return;
|
||||
}else
|
||||
ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end));
|
||||
}
|
||||
}
|
||||
ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end));
|
||||
}
|
||||
template <typename It>
|
||||
bool match_word(It& star_end_string, It buf_end, std::string_view& val)
|
||||
{
|
||||
try
|
||||
{
|
||||
match_word2(star_end_string, buf_end, val);
|
||||
return true;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
template <typename It>
|
||||
bool match_word_with_extrasymb(It& star_end_string, It buf_end, std::string& val)
|
||||
{
|
||||
val = {};
|
||||
|
||||
for(auto it = star_end_string;it != buf_end;it++)
|
||||
{
|
||||
if(!isalnum(*it) && *it != '-' && *it != '_')
|
||||
{
|
||||
val.assign(star_end_string, it);
|
||||
if(val.size())
|
||||
{
|
||||
star_end_string = --it;
|
||||
return true;
|
||||
}else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template <typename It>
|
||||
bool match_word_til_equal_mark(It& star_end_string, It buf_end, It& word_end)
|
||||
{
|
||||
word_end = star_end_string;
|
||||
|
||||
for(auto it = star_end_string;it != buf_end;it++)
|
||||
{
|
||||
if(isspace(*it))
|
||||
{
|
||||
|
||||
continue;
|
||||
}else if( *it == '=' )
|
||||
{
|
||||
star_end_string = it;
|
||||
word_end = it;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool isspace(char c) { return detail::lut[static_cast<uint8_t>(c)] & 8; }
|
||||
inline bool isdigit(char c) { return detail::lut[static_cast<uint8_t>(c)] & 1; }
|
||||
|
||||
void match_string2(const char*& star_end_string, const char* buf_end, std::string& val);
|
||||
void match_number2(const char*& star_end_string, const char* buf_end, std::string_view& val, bool& is_float_val, bool& is_negative_val);
|
||||
void match_word2(const char*& star_end_string, const char* buf_end, std::string_view& val);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../misc_language.h"
|
||||
#include "portable_storage_base.h"
|
||||
#include "portable_storage_to_bin.h"
|
||||
#include "portable_storage_from_bin.h"
|
||||
|
|
|
@ -28,9 +28,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../misc_language.h"
|
||||
#include "portable_storage_base.h"
|
||||
#include <boost/endian/conversion.hpp>
|
||||
#include <oxenc/endian.h>
|
||||
#include <oxenc/variant.h>
|
||||
|
||||
namespace epee
|
||||
{
|
||||
|
@ -111,7 +111,7 @@ namespace epee
|
|||
static_assert(std::is_integral_v<T>);
|
||||
read(&v, sizeof(T));
|
||||
if constexpr (sizeof(T) > 1)
|
||||
boost::endian::little_to_native(v);
|
||||
oxenc::little_to_host(v);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#pragma once
|
||||
#include <string_view>
|
||||
#include <charconv>
|
||||
#include <oxenc/variant.h>
|
||||
#include "portable_storage_base.h"
|
||||
#include "parserse_base_utils.h"
|
||||
|
||||
#define EPEE_JSON_RECURSION_LIMIT_INTERNAL 100
|
||||
|
|
|
@ -29,9 +29,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "../pragma_comp_defs.h"
|
||||
#include "../misc_language.h"
|
||||
#include "portable_storage_base.h"
|
||||
#include <boost/endian/conversion.hpp>
|
||||
#include <oxenc/endian.h>
|
||||
#include <oxenmq/variant.h>
|
||||
|
||||
namespace epee
|
||||
|
@ -72,16 +71,15 @@ namespace epee
|
|||
void pack_entry_to_buff(std::ostream& strm, T v)
|
||||
{
|
||||
if constexpr (sizeof(T) > 1)
|
||||
boost::endian::native_to_little_inplace(v);
|
||||
oxenc::host_to_little_inplace(v);
|
||||
strm.write(reinterpret_cast<const char*>(&v), sizeof(v));
|
||||
}
|
||||
|
||||
inline void pack_entry_to_buff(std::ostream& strm, double v)
|
||||
{
|
||||
static_assert(std::numeric_limits<double>::is_iec559 && sizeof(double) == 8 &&
|
||||
(boost::endian::order::native == boost::endian::order::big || boost::endian::order::native == boost::endian::order::little));
|
||||
static_assert(std::numeric_limits<double>::is_iec559 && sizeof(double) == 8 && (oxenc::little_endian || oxenc::big_endian));
|
||||
char* buff = reinterpret_cast<char*>(&v);
|
||||
if constexpr (boost::endian::order::native == boost::endian::order::big) {
|
||||
if constexpr (oxenc::big_endian) {
|
||||
size_t i = 8;
|
||||
while (i) strm.put(buff[--i]);
|
||||
} else {
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <type_traits>
|
||||
#include <charconv>
|
||||
|
||||
#include "../misc_language.h"
|
||||
#include "portable_storage_base.h"
|
||||
#include "parserse_base_utils.h"
|
||||
#include "../warnings.h"
|
||||
|
|
|
@ -1,243 +0,0 @@
|
|||
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the Andrey N. Sabelnikov nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
#ifndef _STRING_CODING_H_
|
||||
#define _STRING_CODING_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace string_encoding
|
||||
{
|
||||
inline std::string convert_to_ansii(const std::wstring& str_from)
|
||||
{
|
||||
|
||||
std::string res(str_from.begin(), str_from.end());
|
||||
return res;
|
||||
/*
|
||||
std::string result;
|
||||
std::locale loc;
|
||||
for(unsigned int i= 0; i < str_from.size(); ++i)
|
||||
{
|
||||
result += std::use_facet<std::ctype<wchar_t> >(loc).narrow(str_from[i]);
|
||||
}
|
||||
return result;
|
||||
*/
|
||||
|
||||
//return boost::lexical_cast<std::string>(str_from);
|
||||
/*
|
||||
std::string str_trgt;
|
||||
if(!str_from.size())
|
||||
return str_trgt;
|
||||
int cb = ::WideCharToMultiByte( code_page, 0, str_from.data(), (__int32)str_from.size(), 0, 0, 0, 0 );
|
||||
if(!cb)
|
||||
return str_trgt;
|
||||
str_trgt.resize(cb);
|
||||
::WideCharToMultiByte( code_page, 0, str_from.data(), (int)str_from.size(),
|
||||
(char*)str_trgt.data(), (int)str_trgt.size(), 0, 0);
|
||||
return str_trgt;*/
|
||||
}
|
||||
|
||||
inline std::string convert_to_ansii(const std::string& str_from)
|
||||
{
|
||||
return str_from;
|
||||
}
|
||||
|
||||
inline std::wstring convert_to_unicode(const std::string& str_from)
|
||||
{
|
||||
std::wstring result;
|
||||
std::locale loc;
|
||||
for(unsigned int i= 0; i < str_from.size(); ++i)
|
||||
{
|
||||
result += std::use_facet<std::ctype<wchar_t> >(loc).widen(str_from[i]);
|
||||
}
|
||||
return result;
|
||||
|
||||
//return boost::lexical_cast<std::wstring>(str_from);
|
||||
/*
|
||||
std::wstring str_trgt;
|
||||
if(!str_from.size())
|
||||
return str_trgt;
|
||||
|
||||
int cb = ::MultiByteToWideChar( code_page, 0, str_from.data(), (int)str_from.size(), 0, 0 );
|
||||
if(!cb)
|
||||
return str_trgt;
|
||||
|
||||
str_trgt.resize(cb);
|
||||
::MultiByteToWideChar( code_page, 0, str_from.data(),(int)str_from.size(),
|
||||
(wchar_t*)str_trgt.data(),(int)str_trgt.size());
|
||||
return str_trgt;*/
|
||||
}
|
||||
inline std::wstring convert_to_unicode(const std::wstring& str_from)
|
||||
{
|
||||
return str_from;
|
||||
}
|
||||
|
||||
template<class target_string>
|
||||
inline target_string convert_to_t(const std::wstring& str_from);
|
||||
|
||||
template<>
|
||||
inline std::string convert_to_t<std::string>(const std::wstring& str_from)
|
||||
{
|
||||
return convert_to_ansii(str_from);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline std::wstring convert_to_t<std::wstring>(const std::wstring& str_from)
|
||||
{
|
||||
return str_from;
|
||||
}
|
||||
|
||||
template<class target_string>
|
||||
inline target_string convert_to_t(const std::string& str_from);
|
||||
|
||||
template<>
|
||||
inline std::string convert_to_t<std::string>(const std::string& str_from)
|
||||
{
|
||||
return str_from;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline std::wstring convert_to_t<std::wstring>(const std::string& str_from)
|
||||
{
|
||||
return convert_to_unicode(str_from);
|
||||
}
|
||||
|
||||
inline
|
||||
std::string& base64_chars()
|
||||
{
|
||||
|
||||
static std::string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
|
||||
return chars;
|
||||
|
||||
}
|
||||
|
||||
inline
|
||||
std::string base64_encode(unsigned char const* bytes_to_encode, size_t in_len) {
|
||||
std::string ret;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
unsigned char char_array_3[3];
|
||||
unsigned char char_array_4[4];
|
||||
|
||||
while (in_len--) {
|
||||
char_array_3[i++] = *(bytes_to_encode++);
|
||||
if (i == 3) {
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for(i = 0; (i <4) ; i++)
|
||||
ret += base64_chars()[char_array_4[i]];
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i)
|
||||
{
|
||||
for(j = i; j < 3; j++)
|
||||
char_array_3[j] = '\0';
|
||||
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for (j = 0; (j < i + 1); j++)
|
||||
ret += base64_chars()[char_array_4[j]];
|
||||
|
||||
while((i++ < 3))
|
||||
ret += '=';
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
inline
|
||||
std::string base64_encode(const std::string& str)
|
||||
{
|
||||
return base64_encode((unsigned char const* )str.data(), str.size());
|
||||
}
|
||||
|
||||
inline bool is_base64(unsigned char c) {
|
||||
return (isalnum(c) || (c == '+') || (c == '/'));
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
std::string base64_decode(std::string const& encoded_string) {
|
||||
size_t in_len = encoded_string.size();
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
size_t in_ = 0;
|
||||
unsigned char char_array_4[4], char_array_3[3];
|
||||
std::string ret;
|
||||
|
||||
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
|
||||
char_array_4[i++] = encoded_string[in_]; in_++;
|
||||
if (i ==4) {
|
||||
for (i = 0; i <4; i++)
|
||||
char_array_4[i] = (unsigned char)base64_chars().find(char_array_4[i]);
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for (i = 0; (i < 3); i++)
|
||||
ret += char_array_3[i];
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i) {
|
||||
for (j = i; j <4; j++)
|
||||
char_array_4[j] = 0;
|
||||
|
||||
for (j = 0; j <4; j++)
|
||||
char_array_4[j] = (unsigned char)base64_chars().find(char_array_4[j]);
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //_STRING_CODING_H_
|
|
@ -43,7 +43,6 @@
|
|||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include "storages/parserse_base_utils.h"
|
||||
#include "hex.h"
|
||||
#include "mlocker.h"
|
||||
#include "span.h"
|
||||
#include "warnings.h"
|
||||
|
@ -60,37 +59,6 @@ using namespace std::literals;
|
|||
|
||||
namespace string_tools
|
||||
{
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool parse_hexstr_to_binbuff(const epee::span<const char> s, epee::span<char>& res)
|
||||
{
|
||||
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)
|
||||
{
|
||||
int tmp = *src++;
|
||||
tmp = epee::misc_utils::parse::isx[tmp];
|
||||
if (tmp == 0xff) return false;
|
||||
int t2 = *src++;
|
||||
t2 = epee::misc_utils::parse::isx[t2];
|
||||
if (t2 == 0xff) return false;
|
||||
*dst++ = (tmp << 4) | t2;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool parse_hexstr_to_binbuff(const std::string& s, std::string& res)
|
||||
{
|
||||
if (s.size() & 1)
|
||||
return false;
|
||||
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
|
||||
DISABLE_GCC_WARNING(maybe-uninitialized)
|
||||
template<class XType>
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include "memwipe.h"
|
||||
#include "fnv1.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
|
@ -105,7 +104,7 @@ namespace std
|
|||
{
|
||||
size_t operator()(const epee::wipeable_string &s) const
|
||||
{
|
||||
return epee::fnv::FNV1a(s.data(), s.size());
|
||||
return hash<std::string_view>{}(s.view());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
add_library(epee
|
||||
buffer.cpp
|
||||
connection_basic.cpp
|
||||
hex.cpp
|
||||
levin_base.cpp
|
||||
memwipe.c
|
||||
mlocker.cpp
|
||||
|
@ -37,6 +36,7 @@ add_library(epee
|
|||
net_utils_base.cpp
|
||||
network_throttle.cpp
|
||||
network_throttle-detail.cpp
|
||||
parserse_base_utils.cpp
|
||||
portable_storage.cpp
|
||||
string_tools.cpp
|
||||
time_helper.cpp
|
||||
|
@ -65,6 +65,7 @@ target_link_libraries(epee
|
|||
PUBLIC
|
||||
easylogging
|
||||
oxenmq::oxenmq
|
||||
oxenc::oxenc
|
||||
PRIVATE
|
||||
filesystem
|
||||
Boost::thread
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include "epee/misc_log_ex.h"
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include "epee/misc_language.h"
|
||||
#include "epee/pragma_comp_defs.h"
|
||||
#include <iomanip>
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
|
||||
#include "epee/net/net_utils_base.h"
|
||||
#include "epee/misc_log_ex.h"
|
||||
#include "epee/misc_language.h"
|
||||
#include "epee/pragma_comp_defs.h"
|
||||
|
||||
#include "epee/net/abstract_tcp_server2.h"
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
#include "epee/storages/parserse_base_utils.h"
|
||||
#undef OXEN_DEFAULT_LOG_CATEGORY
|
||||
#define OXEN_DEFAULT_LOG_CATEGORY "serialization"
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <oxenc/hex.h>
|
||||
#include "epee/misc_log_ex.h"
|
||||
|
||||
namespace epee::misc_utils::parse {
|
||||
|
||||
/*
|
||||
|
||||
\b Backspace (ascii code 08)
|
||||
\f Form feed (ascii code 0C)
|
||||
\n New line
|
||||
\r Carriage return
|
||||
\t Tab
|
||||
\v Vertical tab
|
||||
\' Apostrophe or single quote
|
||||
\" Double quote
|
||||
\\ Backslash character
|
||||
|
||||
*/
|
||||
void match_string2(const char*& star_end_string, const char* buf_end, std::string& val)
|
||||
{
|
||||
bool escape_mode = false;
|
||||
auto it = star_end_string;
|
||||
++it;
|
||||
auto fi = it;
|
||||
while (fi != buf_end && ((detail::lut[(uint8_t)*fi] & 32)) == 0)
|
||||
++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 == '\\'*/)
|
||||
{
|
||||
switch(*it)
|
||||
{
|
||||
case 'b': //Backspace (ascii code 08)
|
||||
val.push_back(0x08);break;
|
||||
case 'f': //Form feed (ascii code 0C)
|
||||
val.push_back(0x0C);break;
|
||||
case 'n': //New line
|
||||
val.push_back('\n');break;
|
||||
case 'r': //Carriage return
|
||||
val.push_back('\r');break;
|
||||
case 't': //Tab
|
||||
val.push_back('\t');break;
|
||||
case 'v': //Vertical tab
|
||||
val.push_back('\v');break;
|
||||
case '\'': //Apostrophe or single quote
|
||||
val.push_back('\'');break;
|
||||
case '"': //Double quote
|
||||
val.push_back('"');break;
|
||||
case '\\': //Backslash character
|
||||
val.push_back('\\');break;
|
||||
case '/': //Slash character
|
||||
val.push_back('/');break;
|
||||
case 'u': //Unicode code point
|
||||
if (buf_end - it < 4)
|
||||
{
|
||||
ASSERT_MES_AND_THROW("Invalid Unicode escape sequence");
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t dst = 0;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
const auto c = *++it;
|
||||
CHECK_AND_ASSERT_THROW_MES(oxenc::is_hex_digit(c), "Bad Unicode encoding: " + std::to_string(c));
|
||||
dst = dst << 4 | oxenc::from_hex_digit(c);
|
||||
}
|
||||
// encode as UTF-8
|
||||
if (dst <= 0x7f)
|
||||
{
|
||||
val.push_back(dst);
|
||||
}
|
||||
else if (dst <= 0x7ff)
|
||||
{
|
||||
val.push_back(0xc0 | (dst >> 6));
|
||||
val.push_back(0x80 | (dst & 0x3f));
|
||||
}
|
||||
else if (dst <= 0xffff)
|
||||
{
|
||||
val.push_back(0xe0 | (dst >> 12));
|
||||
val.push_back(0x80 | ((dst >> 6) & 0x3f));
|
||||
val.push_back(0x80 | (dst & 0x3f));
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_MES_AND_THROW("Unicode code point is out or range");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
val.push_back(*it);
|
||||
LOG_PRINT_L0("Unknown escape sequence :\"\\" << *it << "\"");
|
||||
}
|
||||
escape_mode = false;
|
||||
}else if(*it == '"')
|
||||
{
|
||||
star_end_string = it;
|
||||
return;
|
||||
}else if(*it == '\\')
|
||||
{
|
||||
escape_mode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
val.push_back(*it);
|
||||
}
|
||||
}
|
||||
ASSERT_MES_AND_THROW("Failed to match string in json entry: " << std::string(star_end_string, buf_end));
|
||||
}
|
||||
// The only conclusive thing that can be said about this function is that it does indeed
|
||||
// closely match a "number 2". 💩
|
||||
void match_number2(const char*& star_end_string, const char* buf_end, std::string_view& val, bool& is_float_val, bool& is_negative_val)
|
||||
{
|
||||
val = {};
|
||||
uint8_t float_flag = 0;
|
||||
is_negative_val = false;
|
||||
is_float_val = false;
|
||||
size_t chars = 0;
|
||||
auto it = star_end_string;
|
||||
if (it != buf_end && *it == '-')
|
||||
{
|
||||
is_negative_val = true;
|
||||
++chars;
|
||||
++it;
|
||||
}
|
||||
for(;it != buf_end;it++)
|
||||
{
|
||||
const uint8_t flags = detail::lut[(uint8_t)*it];
|
||||
if (flags & 16)
|
||||
{
|
||||
float_flag |= flags;
|
||||
++chars;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = std::string_view(&*star_end_string, chars);
|
||||
if(val.size())
|
||||
{
|
||||
star_end_string = --it;
|
||||
is_float_val = !!(float_flag & 2);
|
||||
return;
|
||||
}
|
||||
else
|
||||
ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end));
|
||||
}
|
||||
}
|
||||
ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end));
|
||||
}
|
||||
void match_word2(const char*& star_end_string, const char* buf_end, std::string_view& val)
|
||||
{
|
||||
val = {};
|
||||
|
||||
for(auto it = star_end_string;it != buf_end;it++)
|
||||
{
|
||||
if (!(detail::lut[(uint8_t)*it] & 4))
|
||||
{
|
||||
val = std::string_view(&*star_end_string, std::distance(star_end_string, it));
|
||||
if(val.size())
|
||||
{
|
||||
star_end_string = --it;
|
||||
return;
|
||||
}else
|
||||
ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end));
|
||||
}
|
||||
}
|
||||
ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end));
|
||||
}
|
||||
|
||||
} // namespace epee::misc_utils::parse
|
|
@ -229,7 +229,6 @@ namespace tests
|
|||
{
|
||||
LOG_PRINT_L0("on_command_2: id "<< arg.example_id_data);
|
||||
rsp.example_id_data = arg.example_id_data;
|
||||
//misc_utils::sleep_no_w(6000);
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -266,7 +265,7 @@ namespace tests
|
|||
std::thread th2{[&srv2] { srv2.run(); }};
|
||||
|
||||
LOG_PRINT_L0("Initialized servers, waiting for worker threads started...");
|
||||
misc_utils::sleep_no_w(1000);
|
||||
std::this_thread::sleep_for(1s);
|
||||
|
||||
|
||||
LOG_PRINT_L0("Connecting to each other...");
|
||||
|
@ -369,7 +368,7 @@ namespace tests
|
|||
std::thread thmain2{ [&srv2] { srv2.run(); } };
|
||||
|
||||
LOG_PRINT_L0("Initalized servers, waiting for worker threads started...");
|
||||
misc_utils::sleep_no_w(1000);
|
||||
std::this_thread::sleep_for(1s);
|
||||
|
||||
|
||||
LOG_PRINT_L0("Connecting to each other...");
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
#include "include_base_utils.h"
|
||||
#include "storages/storage_tests.h"
|
||||
#include "misc/test_math.h"
|
||||
#include "storages/portable_storages_test.h"
|
||||
#include "net/test_net.h"
|
||||
|
||||
|
@ -39,13 +38,6 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
}else if(string_tools::have_in_command_line(start_params, std::string("/run_unit_tests")))
|
||||
{
|
||||
if(!tests::test_median())
|
||||
{
|
||||
LOG_ERROR("median test failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if(!tests::test_storages(tests_data_path))
|
||||
{
|
||||
LOG_ERROR("storage test failed");
|
||||
|
|
|
@ -33,60 +33,44 @@
|
|||
# ...except for FreeBSD, because FreeBSD is a special case that doesn't play well with
|
||||
# others.
|
||||
|
||||
set(DEFAULT_WITH_MINIUPNPC ON)
|
||||
if(ANDROID OR IOS)
|
||||
set(DEFAULT_WITH_MINIUPNPC OFF)
|
||||
endif()
|
||||
|
||||
option(WITH_MINIUPNPC "Enable miniupnpc support for IGD NAT hole punching" ${DEFAULT_WITH_MINIUPNPC})
|
||||
|
||||
if(NOT STATIC AND NOT BUILD_STATIC_DEPS)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
if(WITH_MINIUPNPC)
|
||||
pkg_check_modules(MINIUPNPC miniupnpc>=2.1 IMPORTED_TARGET)
|
||||
endif()
|
||||
pkg_check_modules(OXENMQ liboxenmq>=1.2.7 IMPORTED_TARGET)
|
||||
endif()
|
||||
|
||||
if(NOT WITH_MINIUPNPC)
|
||||
message(STATUS "miniupnpc support disabled")
|
||||
target_compile_definitions(miniupnpc INTERFACE WITHOUT_MINIUPNPC)
|
||||
elseif(MINIUPNPC_FOUND)
|
||||
message(STATUS "Found miniupnpc")
|
||||
target_link_libraries(miniupnpc INTERFACE PkgConfig::MINIUPNPC)
|
||||
else()
|
||||
message(STATUS "Using in-tree miniupnpc")
|
||||
add_subdirectory(miniupnp/miniupnpc)
|
||||
if(MSVC)
|
||||
target_compile_options(libminiupnpc-static PRIVATE -wd4244 -wd4267)
|
||||
macro(system_or_submodule BIGNAME smallname pkgconf subdir)
|
||||
option(FORCE_${BIGNAME}_SUBMODULE "force using ${smallname} submodule" OFF)
|
||||
if(NOT STATIC AND NOT FORCE_${BIGNAME}_SUBMODULE)
|
||||
pkg_check_modules(${BIGNAME} ${pkgconf} IMPORTED_TARGET)
|
||||
endif()
|
||||
if(${BIGNAME}_FOUND)
|
||||
add_library(${smallname} INTERFACE)
|
||||
if(NOT TARGET PkgConfig::${BIGNAME} AND CMAKE_VERSION VERSION_LESS "3.21")
|
||||
# Work around cmake bug 22180 (PkgConfig::THING not set if no flags needed)
|
||||
else()
|
||||
target_link_libraries(${smallname} INTERFACE PkgConfig::${BIGNAME})
|
||||
endif()
|
||||
message(STATUS "Found system ${smallname} ${${BIGNAME}_VERSION}")
|
||||
else()
|
||||
target_compile_options(libminiupnpc-static PRIVATE -Wno-undef -Wno-unused-result -Wno-unused-value)
|
||||
message(STATUS "using ${smallname} submodule")
|
||||
add_subdirectory(${subdir})
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "NetBSD")
|
||||
target_compile_definitions(libminiupnpc-static PRIVATE _NETBSD_SOURCE)
|
||||
if(NOT TARGET ${smallname}::${smallname})
|
||||
add_library(${smallname}::${smallname} ALIAS ${smallname})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
target_link_libraries(miniupnpc INTERFACE libminiupnpc-static)
|
||||
endif()
|
||||
system_or_submodule(OXENC oxenc liboxenc>=1.0.3 oxen-encoding)
|
||||
system_or_submodule(OXENMQ oxenmq liboxenmq>=1.2.12 oxen-mq)
|
||||
system_or_submodule(FMT fmt fmt>=8.0.0 fmt)
|
||||
|
||||
|
||||
if(NOT OXENMQ_FOUND)
|
||||
message(STATUS "Using in-tree oxenmq")
|
||||
add_subdirectory(loki-mq)
|
||||
else()
|
||||
add_library(oxenmq INTERFACE)
|
||||
target_link_libraries(oxenmq INTERFACE PkgConfig::OXENMQ)
|
||||
add_library(oxenmq::oxenmq ALIAS oxenmq)
|
||||
message(STATUS "Found liboxenmq ${OXENMQ_VERSION}")
|
||||
endif()
|
||||
|
||||
add_subdirectory(oxenc)
|
||||
system_or_submodule(OXENC oxenc liboxenc>=1.0.3 oxen-encoding)
|
||||
system_or_submodule(OXENMQ oxenmq liboxenmq>=1.2.12 oxen-mq)
|
||||
system_or_submodule(FMT fmt fmt>=8.0.0 fmt)
|
||||
|
||||
add_subdirectory(db_drivers)
|
||||
add_subdirectory(easylogging++ easyloggingpp)
|
||||
add_subdirectory(randomx EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(date EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(fmt)
|
||||
|
||||
set(JSON_BuildTests OFF CACHE INTERNAL "")
|
||||
set(JSON_MultipleHeaders ON CACHE BOOL "") # Allows multi-header nlohmann use
|
||||
|
@ -152,6 +136,21 @@ target_include_directories(cpr PUBLIC cpr/include)
|
|||
target_compile_definitions(cpr PUBLIC CPR_CURL_NOSIGNAL)
|
||||
add_library(cpr::cpr ALIAS cpr)
|
||||
|
||||
file(READ cpr/CMakeLists.txt cpr_cmake_head LIMIT 1000)
|
||||
if(cpr_cmake_head MATCHES "project\\(cpr VERSION ([0-9]+)\.([0-9]+)\.([0-9]+) LANGUAGES CXX\\)")
|
||||
set(cpr_VERSION_MAJOR ${CMAKE_MATCH_1})
|
||||
set(cpr_VERSION_MINOR ${CMAKE_MATCH_2})
|
||||
set(cpr_VERSION_PATCH ${CMAKE_MATCH_3})
|
||||
set(cpr_VERSION "${cpr_VERSION_MAJOR}.${cpr_VERSION_MINOR}.${cpr_VERSION_PATCH}")
|
||||
set(cpr_VERSION_NUM "(${cpr_VERSION_MAJOR} * 0x10000 + ${cpr_VERSION_MINOR} * 0x100 + ${cpr_VERSION_PATCH})")
|
||||
|
||||
configure_file(cpr/cmake/cprver.h.in "${CMAKE_CURRENT_BINARY_DIR}/cpr_generated_includes/cpr/cprver.h")
|
||||
target_include_directories(cpr PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/cpr_generated_includes")
|
||||
else()
|
||||
message(FATAL_ERROR "Could not identify cpr submodule version!")
|
||||
endif()
|
||||
|
||||
|
||||
# Hack around SQLiteCpp's attempts to locate sqlite3 because we *don't* want to link against the
|
||||
# system one, but don't download and build the embedded one until build time. Thankfully it
|
||||
# actually links against the SQLite::SQLite3 cmake target if it already exists, so all we have to do
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Subproject commit e1b1a84c4bddc344eb99182ef5d667bcfaf02ca1
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 81029a860baf1f727903e5b85307903b3f40cbc8
|
|
@ -0,0 +1 @@
|
|||
Subproject commit a0912ab4bf3b5e83b42715eff6f632c8912b21e4
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 5c72a57eca120750ecf557ce5a668fb38242956b
|
|
@ -47,10 +47,6 @@ function (oxen_add_executable target binary)
|
|||
set_property(GLOBAL PROPERTY oxen_executable_targets "${exec_tgt}")
|
||||
endfunction ()
|
||||
|
||||
include(Version)
|
||||
add_library(version ${CMAKE_BINARY_DIR}/version.cpp)
|
||||
add_dependencies(version genversion)
|
||||
|
||||
add_subdirectory(common)
|
||||
add_subdirectory(crypto)
|
||||
add_subdirectory(ringct)
|
||||
|
@ -71,6 +67,7 @@ add_subdirectory(p2p)
|
|||
add_subdirectory(daemonizer)
|
||||
add_subdirectory(daemon)
|
||||
add_subdirectory(simplewallet)
|
||||
add_subdirectory(sqlitedb)
|
||||
|
||||
add_subdirectory(gen_multisig)
|
||||
add_subdirectory(blockchain_utilities)
|
||||
|
@ -92,3 +89,38 @@ endif()
|
|||
|
||||
add_subdirectory(device)
|
||||
add_subdirectory(device_trezor)
|
||||
|
||||
|
||||
if(OXEN_VERSIONTAG)
|
||||
set(VERSIONTAG "${OXEN_VERSIONTAG}")
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/version.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/version.cpp")
|
||||
else()
|
||||
set(GIT_INDEX_FILE "${PROJECT_SOURCE_DIR}/.git/index")
|
||||
find_package(Git)
|
||||
if(EXISTS ${GIT_INDEX_FILE} AND ( GIT_FOUND OR Git_FOUND) )
|
||||
message(STATUS "Found Git: ${GIT_EXECUTABLE}")
|
||||
|
||||
set(genversion_args "-DGIT=${GIT_EXECUTABLE}")
|
||||
foreach(v oxen_VERSION oxen_VERSION_MAJOR oxen_VERSION_MINOR oxen_VERSION_PATCH OXEN_RELEASE_CODENAME OXEN_RELEASE_SUFFIX)
|
||||
list(APPEND genversion_args "-D${v}=${${v}}")
|
||||
endforeach()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/version.cpp"
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}"
|
||||
${genversion_args}
|
||||
"-DSRC=${CMAKE_CURRENT_SOURCE_DIR}/version.cpp.in"
|
||||
"-DDEST=${CMAKE_CURRENT_BINARY_DIR}/version.cpp"
|
||||
"-P" "${PROJECT_SOURCE_DIR}/cmake/GenVersion.cmake"
|
||||
DEPENDS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/version.cpp.in"
|
||||
"${GIT_INDEX_FILE}")
|
||||
else()
|
||||
message(STATUS "Git was not found! Setting version tag to to nogit")
|
||||
set(VERSIONTAG "nogit")
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/version.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/version.cpp")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_library(version "${CMAKE_CURRENT_BINARY_DIR}/version.cpp")
|
||||
|
|
|
@ -30,9 +30,12 @@
|
|||
add_library(blockchain_db
|
||||
blockchain_db.cpp
|
||||
lmdb/db_lmdb.cpp
|
||||
sqlite/db_sqlite.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(blockchain_db
|
||||
PUBLIC
|
||||
sqlitedb
|
||||
PRIVATE
|
||||
common
|
||||
ringct
|
||||
|
|
|
@ -75,7 +75,7 @@ void BlockchainDB::pop_block()
|
|||
pop_block(blk, txs);
|
||||
}
|
||||
|
||||
void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, blobdata>& txp, const crypto::hash* tx_hash_ptr, const crypto::hash* tx_prunable_hash_ptr)
|
||||
void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, std::string>& txp, const crypto::hash* tx_hash_ptr, const crypto::hash* tx_prunable_hash_ptr)
|
||||
{
|
||||
const transaction &tx = txp.first;
|
||||
|
||||
|
@ -172,12 +172,12 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair
|
|||
add_tx_amount_output_indices(tx_id, amount_output_indices);
|
||||
}
|
||||
|
||||
uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
|
||||
uint64_t BlockchainDB::add_block( const std::pair<block, std::string>& blck
|
||||
, size_t block_weight
|
||||
, uint64_t long_term_block_weight
|
||||
, const difficulty_type& cumulative_difficulty
|
||||
, const uint64_t& coins_generated
|
||||
, const std::vector<std::pair<transaction, blobdata>>& txs
|
||||
, const std::vector<std::pair<transaction, std::string>>& txs
|
||||
)
|
||||
{
|
||||
const block &blk = blck.first;
|
||||
|
@ -203,7 +203,7 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
|
|||
|
||||
int tx_i = 0;
|
||||
crypto::hash tx_hash = crypto::null_hash;
|
||||
for (const std::pair<transaction, blobdata>& tx : txs)
|
||||
for (const std::pair<transaction, std::string>& tx : txs)
|
||||
{
|
||||
tx_hash = blk.tx_hashes[tx_i];
|
||||
add_transaction(blk_hash, tx, &tx_hash);
|
||||
|
@ -274,7 +274,7 @@ block BlockchainDB::get_block(const crypto::hash& h) const
|
|||
|
||||
bool BlockchainDB::get_tx(const crypto::hash& h, cryptonote::transaction &tx) const
|
||||
{
|
||||
blobdata bd;
|
||||
std::string bd;
|
||||
if (!get_tx_blob(h, bd))
|
||||
return false;
|
||||
if (!parse_and_validate_tx_from_blob(bd, tx))
|
||||
|
@ -285,11 +285,13 @@ bool BlockchainDB::get_tx(const crypto::hash& h, cryptonote::transaction &tx) co
|
|||
|
||||
bool BlockchainDB::get_pruned_tx(const crypto::hash& h, cryptonote::transaction &tx) const
|
||||
{
|
||||
blobdata bd;
|
||||
std::string bd;
|
||||
if (!get_pruned_tx_blob(h, bd))
|
||||
return false;
|
||||
if (!parse_and_validate_tx_base_from_blob(bd, tx))
|
||||
{
|
||||
throw DB_ERROR("Failed to parse transaction base from blob retrieved from the db");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -397,9 +399,9 @@ uint64_t BlockchainDB::get_tx_block_height(const crypto::hash &h) const
|
|||
return result;
|
||||
}
|
||||
|
||||
bool BlockchainDB::get_alt_block_header(const crypto::hash &blkid, alt_block_data_t *data, cryptonote::block_header *header, cryptonote::blobdata *checkpoint) const
|
||||
bool BlockchainDB::get_alt_block_header(const crypto::hash &blkid, alt_block_data_t *data, cryptonote::block_header *header, std::string *checkpoint) const
|
||||
{
|
||||
cryptonote::blobdata blob;
|
||||
std::string blob;
|
||||
if (!get_alt_block(blkid, data, &blob, checkpoint))
|
||||
{
|
||||
throw BLOCK_DNE("Alt-block with hash " + tools::type_to_hex(blkid) + " not found in db");
|
||||
|
@ -430,8 +432,8 @@ void BlockchainDB::fill_timestamps_and_difficulties_for_pow(cryptonote::network_
|
|||
return;
|
||||
|
||||
uint64_t const top_block_height = chain_height - 1;
|
||||
bool const before_hf16 = !is_hard_fork_at_least(nettype, network_version_16_pulse, chain_height);
|
||||
uint64_t const block_count = DIFFICULTY_BLOCKS_COUNT(before_hf16);
|
||||
bool const before_hf16 = !is_hard_fork_at_least(nettype, hf::hf16_pulse, chain_height);
|
||||
uint64_t const block_count = old::DIFFICULTY_BLOCKS_COUNT(before_hf16);
|
||||
|
||||
timestamps.reserve(block_count);
|
||||
difficulties.reserve(block_count);
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include "common/command_line.h"
|
||||
#include "common/fs.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "cryptonote_basic/blobdatatype.h"
|
||||
#include "cryptonote_basic/cryptonote_basic.h"
|
||||
#include "cryptonote_basic/difficulty.h"
|
||||
|
||||
|
@ -414,7 +413,7 @@ private:
|
|||
* @param tx_prunable_hash the hash of the prunable part of the transaction
|
||||
* @return the transaction ID
|
||||
*/
|
||||
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) = 0;
|
||||
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, std::string>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) = 0;
|
||||
|
||||
/**
|
||||
* @brief remove data about a transaction
|
||||
|
@ -542,7 +541,7 @@ protected:
|
|||
* @param tx_hash_ptr the hash of the transaction, if already calculated
|
||||
* @param tx_prunable_hash_ptr the hash of the prunable part of the transaction, if already calculated
|
||||
*/
|
||||
void add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, blobdata>& tx, const crypto::hash* tx_hash_ptr = NULL, const crypto::hash* tx_prunable_hash_ptr = NULL);
|
||||
void add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, std::string>& tx, const crypto::hash* tx_hash_ptr = NULL, const crypto::hash* tx_prunable_hash_ptr = NULL);
|
||||
|
||||
mutable std::chrono::nanoseconds time_tx_exists = 0ns; //!< a performance metric
|
||||
std::chrono::nanoseconds time_commit1 = 0ns; //!< a performance metric
|
||||
|
@ -815,12 +814,12 @@ public:
|
|||
*
|
||||
* @return the height of the chain post-addition
|
||||
*/
|
||||
virtual uint64_t add_block( const std::pair<block, blobdata>& blk
|
||||
virtual uint64_t add_block( const std::pair<block, std::string>& blk
|
||||
, size_t block_weight
|
||||
, uint64_t long_term_block_weight
|
||||
, const difficulty_type& cumulative_difficulty
|
||||
, const uint64_t& coins_generated
|
||||
, const std::vector<std::pair<transaction, blobdata>>& txs
|
||||
, const std::vector<std::pair<transaction, std::string>>& txs
|
||||
);
|
||||
|
||||
virtual void update_block_checkpoint(checkpoint_t const &checkpoint) = 0;
|
||||
|
@ -854,7 +853,7 @@ public:
|
|||
*
|
||||
* @return the block requested
|
||||
*/
|
||||
virtual cryptonote::blobdata get_block_blob(const crypto::hash& h) const = 0;
|
||||
virtual std::string get_block_blob(const crypto::hash& h) const = 0;
|
||||
|
||||
/**
|
||||
* @brief fetches the block with the given hash
|
||||
|
@ -922,7 +921,7 @@ public:
|
|||
*
|
||||
* @return the block blob
|
||||
*/
|
||||
virtual cryptonote::blobdata get_block_blob_from_height(uint64_t height) const = 0;
|
||||
virtual std::string get_block_blob_from_height(uint64_t height) const = 0;
|
||||
|
||||
/**
|
||||
* @brief fetch a block by height
|
||||
|
@ -1266,7 +1265,7 @@ public:
|
|||
*
|
||||
* @return true iff the transaction was found
|
||||
*/
|
||||
virtual bool get_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const = 0;
|
||||
virtual bool get_tx_blob(const crypto::hash& h, std::string &tx) const = 0;
|
||||
|
||||
/**
|
||||
* @brief fetches the pruned transaction blob with the given hash
|
||||
|
@ -1280,7 +1279,7 @@ public:
|
|||
*
|
||||
* @return true iff the transaction was found
|
||||
*/
|
||||
virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const = 0;
|
||||
virtual bool get_pruned_tx_blob(const crypto::hash& h, std::string &tx) const = 0;
|
||||
|
||||
/**
|
||||
* @brief fetches a number of pruned transaction blob from the given hash, in canonical blockchain order
|
||||
|
@ -1296,7 +1295,7 @@ public:
|
|||
*
|
||||
* @return true iff the transactions were found
|
||||
*/
|
||||
virtual bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const = 0;
|
||||
virtual bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<std::string> &bd) const = 0;
|
||||
|
||||
/**
|
||||
* @brief fetches the prunable transaction blob with the given hash
|
||||
|
@ -1311,7 +1310,7 @@ public:
|
|||
*
|
||||
* @return true iff the transaction was found and we have its prunable data
|
||||
*/
|
||||
virtual bool get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const = 0;
|
||||
virtual bool get_prunable_tx_blob(const crypto::hash& h, std::string &tx) const = 0;
|
||||
|
||||
/**
|
||||
* @brief fetches the prunable transaction hash
|
||||
|
@ -1512,7 +1511,7 @@ public:
|
|||
*
|
||||
* @param details the details of the transaction to add
|
||||
*/
|
||||
virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t& details) = 0;
|
||||
virtual void add_txpool_tx(const crypto::hash &txid, const std::string &blob, const txpool_tx_meta_t& details) = 0;
|
||||
|
||||
/**
|
||||
* @brief update a txpool transaction's metadata
|
||||
|
@ -1557,7 +1556,7 @@ public:
|
|||
*
|
||||
* @return true if the txid was in the txpool, false otherwise
|
||||
*/
|
||||
virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const = 0;
|
||||
virtual bool get_txpool_tx_blob(const crypto::hash& txid, std::string &bd) const = 0;
|
||||
|
||||
/**
|
||||
* @brief get a txpool transaction's blob
|
||||
|
@ -1566,7 +1565,7 @@ public:
|
|||
*
|
||||
* @return the blob for that transaction
|
||||
*/
|
||||
virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const = 0;
|
||||
virtual std::string get_txpool_tx_blob(const crypto::hash& txid) const = 0;
|
||||
|
||||
/**
|
||||
* @brief prune output data for the given amount
|
||||
|
@ -1621,7 +1620,7 @@ public:
|
|||
* @param: data: the metadata for the block
|
||||
* @param: blob: the block's blob
|
||||
*/
|
||||
virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata &blob, const cryptonote::blobdata *checkpoint) = 0;
|
||||
virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const std::string &blob, const std::string *checkpoint) = 0;
|
||||
|
||||
/**
|
||||
* @brief get an alternative block by hash
|
||||
|
@ -1632,7 +1631,7 @@ public:
|
|||
*
|
||||
* @return true if the block was found in the alternative blocks list, false otherwise
|
||||
*/
|
||||
virtual bool get_alt_block(const crypto::hash &blkid, alt_block_data_t *data, cryptonote::blobdata *blob, cryptonote::blobdata *checkpoint) const = 0;
|
||||
virtual bool get_alt_block(const crypto::hash &blkid, alt_block_data_t *data, std::string *blob, std::string *checkpoint) const = 0;
|
||||
|
||||
/**
|
||||
* @brief get the block header from the alternative block db
|
||||
|
@ -1644,7 +1643,7 @@ public:
|
|||
*
|
||||
* @return true if the block was found in the alternative blocks list, false otherwise
|
||||
*/
|
||||
bool get_alt_block_header(const crypto::hash &blkid, alt_block_data_t *data, cryptonote::block_header *header, cryptonote::blobdata *checkpoint) const;
|
||||
bool get_alt_block_header(const crypto::hash &blkid, alt_block_data_t *data, cryptonote::block_header *header, std::string *checkpoint) const;
|
||||
|
||||
/**
|
||||
* @brief remove an alternative block
|
||||
|
@ -1676,7 +1675,7 @@ public:
|
|||
*
|
||||
* @return false if the function returns false for any transaction, otherwise true
|
||||
*/
|
||||
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, bool include_unrelayed_txes = true) const = 0;
|
||||
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const std::string*)>, bool include_blob = false, bool include_unrelayed_txes = true) const = 0;
|
||||
|
||||
/**
|
||||
* @brief runs a function over all key images stored
|
||||
|
@ -1768,7 +1767,7 @@ public:
|
|||
*
|
||||
* @return false if the function returns false for any output, otherwise true
|
||||
*/
|
||||
virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata *block_blob, const cryptonote::blobdata *checkpoint_blob)> f, bool include_blob = false) const = 0;
|
||||
virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const std::string *block_blob, const std::string *checkpoint_blob)> f, bool include_blob = false) const = 0;
|
||||
|
||||
/**
|
||||
* @brief return a histogram of outputs on the blockchain
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
#include "db_lmdb.h"
|
||||
|
||||
#include <boost/circular_buffer.hpp>
|
||||
#include <boost/endian/conversion.hpp>
|
||||
#include <chrono>
|
||||
#include <oxenc/endian.h>
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
@ -42,6 +42,7 @@
|
|||
#include "common/file.h"
|
||||
#include "common/pruning.h"
|
||||
#include "common/hex.h"
|
||||
#include "common/median.h"
|
||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "ringct/rctOps.h"
|
||||
|
@ -56,7 +57,6 @@
|
|||
|
||||
|
||||
using namespace crypto;
|
||||
using namespace boost::endian;
|
||||
|
||||
enum struct lmdb_version
|
||||
{
|
||||
|
@ -115,9 +115,9 @@ private:
|
|||
};
|
||||
|
||||
template<>
|
||||
struct MDB_val_copy<cryptonote::blobdata>: public MDB_val
|
||||
struct MDB_val_copy<std::string>: public MDB_val
|
||||
{
|
||||
MDB_val_copy(const cryptonote::blobdata &bd) :
|
||||
MDB_val_copy(const std::string &bd) :
|
||||
data(new char[bd.size()])
|
||||
{
|
||||
memcpy(data.get(), bd.data(), bd.size());
|
||||
|
@ -880,7 +880,7 @@ void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t l
|
|||
CURSOR(block_info)
|
||||
|
||||
// this call to mdb_cursor_put will change height()
|
||||
cryptonote::blobdata block_blob(block_to_blob(blk));
|
||||
std::string block_blob(block_to_blob(blk));
|
||||
MDB_val_sized(blob, block_blob);
|
||||
result = mdb_cursor_put(m_cur_blocks, &key, &blob, MDB_APPEND);
|
||||
if (result)
|
||||
|
@ -894,12 +894,12 @@ void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t l
|
|||
bi.bi_diff = cumulative_difficulty;
|
||||
bi.bi_hash = blk_hash;
|
||||
bi.bi_cum_rct = num_rct_outs;
|
||||
if (blk.major_version >= 4 && m_height > 0)
|
||||
if (m_height > 0)
|
||||
{
|
||||
uint64_t last_height = m_height-1;
|
||||
MDB_val_set(h, last_height);
|
||||
if ((result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &h, MDB_GET_BOTH)))
|
||||
throw1(BLOCK_DNE(lmdb_error("Failed to get block info: ", result).c_str()));
|
||||
throw1(BLOCK_DNE(lmdb_error("Failed to get parent block info: ", result).c_str()));
|
||||
const mdb_block_info *bi_prev = (const mdb_block_info*)h.mv_data;
|
||||
bi.bi_cum_rct += bi_prev->bi_cum_rct;
|
||||
}
|
||||
|
@ -957,7 +957,7 @@ void BlockchainLMDB::remove_block()
|
|||
throw1(DB_ERROR(lmdb_error("Failed to add removal of block info to db transaction: ", result).c_str()));
|
||||
}
|
||||
|
||||
uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata>& txp, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash)
|
||||
uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, std::string>& txp, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
@ -997,7 +997,7 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons
|
|||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to add tx data to db transaction: ", result).c_str()));
|
||||
|
||||
const cryptonote::blobdata &blob = txp.second;
|
||||
const std::string &blob = txp.second;
|
||||
MDB_val_sized(blobval, blob);
|
||||
|
||||
unsigned int unprunable_size = tx.unprunable_size;
|
||||
|
@ -1417,11 +1417,11 @@ void BlockchainLMDB::open(const fs::path& filename, cryptonote::network_type net
|
|||
|
||||
// check for existing LMDB files in base directory
|
||||
auto old_files = filename.parent_path();
|
||||
if (fs::exists(old_files / CRYPTONOTE_BLOCKCHAINDATA_FILENAME)
|
||||
|| fs::exists(old_files / CRYPTONOTE_BLOCKCHAINDATA_LOCK_FILENAME))
|
||||
if (fs::exists(old_files / BLOCKCHAINDATA_FILENAME)
|
||||
|| fs::exists(old_files / BLOCKCHAINDATA_LOCK_FILENAME))
|
||||
{
|
||||
LOG_PRINT_L0("Found existing LMDB files in " << old_files.u8string());
|
||||
LOG_PRINT_L0("Move " << CRYPTONOTE_BLOCKCHAINDATA_FILENAME << " and/or " << CRYPTONOTE_BLOCKCHAINDATA_LOCK_FILENAME << " to " << filename << ", or delete them, and then restart");
|
||||
LOG_PRINT_L0("Move " << BLOCKCHAINDATA_FILENAME << " and/or " << BLOCKCHAINDATA_LOCK_FILENAME << " to " << filename << ", or delete them, and then restart");
|
||||
throw DB_ERROR("Database could not be opened");
|
||||
}
|
||||
|
||||
|
@ -1729,14 +1729,14 @@ std::vector<fs::path> BlockchainLMDB::get_filenames() const
|
|||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
std::vector<fs::path> paths;
|
||||
paths.push_back(m_folder / CRYPTONOTE_BLOCKCHAINDATA_FILENAME);
|
||||
paths.push_back(m_folder / CRYPTONOTE_BLOCKCHAINDATA_LOCK_FILENAME);
|
||||
paths.push_back(m_folder / BLOCKCHAINDATA_FILENAME);
|
||||
paths.push_back(m_folder / BLOCKCHAINDATA_LOCK_FILENAME);
|
||||
return paths;
|
||||
}
|
||||
|
||||
bool BlockchainLMDB::remove_data_file(const fs::path& folder) const
|
||||
{
|
||||
auto filename = folder / CRYPTONOTE_BLOCKCHAINDATA_FILENAME;
|
||||
auto filename = folder / BLOCKCHAINDATA_FILENAME;
|
||||
try
|
||||
{
|
||||
fs::remove(filename);
|
||||
|
@ -1822,7 +1822,7 @@ void BlockchainLMDB::unlock()
|
|||
auto_txn.commit(); \
|
||||
} while(0)
|
||||
|
||||
void BlockchainLMDB::add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &meta)
|
||||
void BlockchainLMDB::add_txpool_tx(const crypto::hash &txid, const std::string &blob, const txpool_tx_meta_t &meta)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
@ -1983,7 +1983,7 @@ bool BlockchainLMDB::get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const
|
||||
bool BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, std::string &bd) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
@ -2003,9 +2003,9 @@ bool BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::bl
|
|||
return true;
|
||||
}
|
||||
|
||||
cryptonote::blobdata BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid) const
|
||||
std::string BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid) const
|
||||
{
|
||||
cryptonote::blobdata bd;
|
||||
std::string bd;
|
||||
if (!get_txpool_tx_blob(txid, bd))
|
||||
throw1(DB_ERROR("Tx not found in txpool: "));
|
||||
return bd;
|
||||
|
@ -2049,10 +2049,10 @@ bool BlockchainLMDB::prune_worker(int mode, uint32_t pruning_seed)
|
|||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
const uint32_t log_stripes = tools::get_pruning_log_stripes(pruning_seed);
|
||||
if (log_stripes && log_stripes != CRYPTONOTE_PRUNING_LOG_STRIPES)
|
||||
if (log_stripes && log_stripes != PRUNING_LOG_STRIPES)
|
||||
throw0(DB_ERROR("Pruning seed not in range"));
|
||||
pruning_seed = tools::get_pruning_stripe(pruning_seed);
|
||||
if (pruning_seed > (1ul << CRYPTONOTE_PRUNING_LOG_STRIPES))
|
||||
if (pruning_seed > (1ul << PRUNING_LOG_STRIPES))
|
||||
throw0(DB_ERROR("Pruning seed not in range"));
|
||||
check_open();
|
||||
|
||||
|
@ -2086,7 +2086,7 @@ bool BlockchainLMDB::prune_worker(int mode, uint32_t pruning_seed)
|
|||
}
|
||||
if (pruning_seed == 0)
|
||||
pruning_seed = tools::get_random_stripe();
|
||||
pruning_seed = tools::make_pruning_seed(pruning_seed, CRYPTONOTE_PRUNING_LOG_STRIPES);
|
||||
pruning_seed = tools::make_pruning_seed(pruning_seed, PRUNING_LOG_STRIPES);
|
||||
v.mv_data = &pruning_seed;
|
||||
v.mv_size = sizeof(pruning_seed);
|
||||
result = mdb_put(txn, m_properties, &k, &v, 0);
|
||||
|
@ -2104,9 +2104,9 @@ bool BlockchainLMDB::prune_worker(int mode, uint32_t pruning_seed)
|
|||
pruning_seed = tools::get_pruning_stripe(data);
|
||||
if (tools::get_pruning_stripe(data) != pruning_seed)
|
||||
throw0(DB_ERROR("Blockchain already pruned with different seed"));
|
||||
if (tools::get_pruning_log_stripes(data) != CRYPTONOTE_PRUNING_LOG_STRIPES)
|
||||
if (tools::get_pruning_log_stripes(data) != PRUNING_LOG_STRIPES)
|
||||
throw0(DB_ERROR("Blockchain already pruned with different base"));
|
||||
pruning_seed = tools::make_pruning_seed(pruning_seed, CRYPTONOTE_PRUNING_LOG_STRIPES);
|
||||
pruning_seed = tools::make_pruning_seed(pruning_seed, PRUNING_LOG_STRIPES);
|
||||
prune_tip_table = (mode == prune_mode_update);
|
||||
}
|
||||
else
|
||||
|
@ -2145,7 +2145,7 @@ bool BlockchainLMDB::prune_worker(int mode, uint32_t pruning_seed)
|
|||
|
||||
uint64_t block_height;
|
||||
memcpy(&block_height, v.mv_data, sizeof(block_height));
|
||||
if (block_height + CRYPTONOTE_PRUNING_TIP_BLOCKS < blockchain_height)
|
||||
if (block_height + PRUNING_TIP_BLOCKS < blockchain_height)
|
||||
{
|
||||
++n_total_records;
|
||||
if (!tools::has_unpruned_block(block_height, blockchain_height, pruning_seed) && !is_v1_tx(c_txs_pruned, &k))
|
||||
|
@ -2213,7 +2213,7 @@ bool BlockchainLMDB::prune_worker(int mode, uint32_t pruning_seed)
|
|||
txindex ti;
|
||||
memcpy(&ti, v.mv_data, sizeof(ti));
|
||||
const uint64_t block_height = ti.data.block_id;
|
||||
if (block_height + CRYPTONOTE_PRUNING_TIP_BLOCKS >= blockchain_height)
|
||||
if (block_height + PRUNING_TIP_BLOCKS >= blockchain_height)
|
||||
{
|
||||
MDB_val_set(kp, ti.data.tx_id);
|
||||
MDB_val_set(vp, block_height);
|
||||
|
@ -2340,7 +2340,7 @@ bool BlockchainLMDB::check_pruning()
|
|||
return prune_worker(prune_mode_check, 0);
|
||||
}
|
||||
|
||||
bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob, bool include_unrelayed_txes) const
|
||||
bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const std::string*)> f, bool include_blob, bool include_unrelayed_txes) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
@ -2367,8 +2367,8 @@ bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&,
|
|||
if (!include_unrelayed_txes && meta.do_not_relay)
|
||||
// Skipping that tx
|
||||
continue;
|
||||
const cryptonote::blobdata *passed_bd = NULL;
|
||||
cryptonote::blobdata bd;
|
||||
const std::string *passed_bd = NULL;
|
||||
std::string bd;
|
||||
if (include_blob)
|
||||
{
|
||||
MDB_val b;
|
||||
|
@ -2407,18 +2407,18 @@ static_assert(sizeof(blob_header) == 8, "blob_header layout is unexpected, possi
|
|||
static blob_header write_little_endian_blob_header(blob_type type, uint32_t size)
|
||||
{
|
||||
blob_header result = {type, size};
|
||||
native_to_little_inplace(result.size);
|
||||
oxenc::host_to_little_inplace(result.size);
|
||||
return result;
|
||||
}
|
||||
|
||||
static blob_header native_endian_blob_header(const blob_header *header)
|
||||
static blob_header host_endian_blob_header(const blob_header *header)
|
||||
{
|
||||
blob_header result = {header->type, header->size};
|
||||
little_to_native_inplace(result.size);
|
||||
oxenc::little_to_host_inplace(result.size);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool read_alt_block_data_from_mdb_val(MDB_val const v, alt_block_data_t *data, cryptonote::blobdata *block, cryptonote::blobdata *checkpoint)
|
||||
static bool read_alt_block_data_from_mdb_val(MDB_val const v, alt_block_data_t *data, std::string *block, std::string *checkpoint)
|
||||
{
|
||||
size_t const conservative_min_size = sizeof(*data) + sizeof(blob_header);
|
||||
if (v.mv_size < conservative_min_size)
|
||||
|
@ -2433,7 +2433,7 @@ static bool read_alt_block_data_from_mdb_val(MDB_val const v, alt_block_data_t *
|
|||
src = reinterpret_cast<const char *>(alt_data + 1);
|
||||
while (src < end)
|
||||
{
|
||||
blob_header header = native_endian_blob_header(reinterpret_cast<const blob_header *>(src));
|
||||
blob_header header = host_endian_blob_header(reinterpret_cast<const blob_header *>(src));
|
||||
src += sizeof(header);
|
||||
if (header.type == blob_type::block)
|
||||
{
|
||||
|
@ -2453,7 +2453,7 @@ static bool read_alt_block_data_from_mdb_val(MDB_val const v, alt_block_data_t *
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainLMDB::for_all_alt_blocks(std::function<bool(const crypto::hash&, const alt_block_data_t&, const cryptonote::blobdata*, const cryptonote::blobdata *)> f, bool include_blob) const
|
||||
bool BlockchainLMDB::for_all_alt_blocks(std::function<bool(const crypto::hash&, const alt_block_data_t&, const std::string*, const std::string *)> f, bool include_blob) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
@ -2476,12 +2476,12 @@ bool BlockchainLMDB::for_all_alt_blocks(std::function<bool(const crypto::hash&,
|
|||
throw0(DB_ERROR(lmdb_error("Failed to enumerate alt blocks: ", result).c_str()));
|
||||
const crypto::hash &blkid = *(const crypto::hash*)k.mv_data;
|
||||
|
||||
cryptonote::blobdata block;
|
||||
cryptonote::blobdata checkpoint;
|
||||
std::string block;
|
||||
std::string checkpoint;
|
||||
|
||||
alt_block_data_t data = {};
|
||||
cryptonote::blobdata *block_ptr = (include_blob) ? &block : nullptr;
|
||||
cryptonote::blobdata *checkpoint_ptr = (include_blob) ? &checkpoint : nullptr;
|
||||
std::string *block_ptr = (include_blob) ? &block : nullptr;
|
||||
std::string *checkpoint_ptr = (include_blob) ? &checkpoint : nullptr;
|
||||
if (!read_alt_block_data_from_mdb_val(v, &data, block_ptr, checkpoint_ptr))
|
||||
throw0(DB_ERROR("Record size is less than expected"));
|
||||
|
||||
|
@ -2528,17 +2528,18 @@ bool BlockchainLMDB::block_exists(const crypto::hash& h, uint64_t *height) const
|
|||
template <typename T,
|
||||
std::enable_if_t<std::is_same_v<T, cryptonote::block> ||
|
||||
std::is_same_v<T, cryptonote::block_header> ||
|
||||
std::is_same_v<T, cryptonote::blobdata>, int>>
|
||||
std::is_same_v<T, std::string>, int>>
|
||||
T BlockchainLMDB::get_and_convert_block_blob_from_height(uint64_t height) const
|
||||
{
|
||||
// NOTE: Avoid any intermediary functions like taking a blob, then converting
|
||||
// to block which incurs a copy into blobdata then conversion, and prefer
|
||||
// to block which incurs a copy into std::string then conversion, and prefer
|
||||
// converting directly from the data initially fetched.
|
||||
|
||||
// Avoid casting block to block_header so we only have to deserialize the
|
||||
// header, not the full-block (of which a good chunk is thrown away because we
|
||||
// only want the header).
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
|
||||
check_open();
|
||||
|
||||
TXN_PREFIX_RDONLY();
|
||||
|
@ -2565,7 +2566,7 @@ T BlockchainLMDB::get_and_convert_block_blob_from_height(uint64_t height) const
|
|||
serialization::binary_string_unarchiver ba{blob};
|
||||
serialization::value(ba, result);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, cryptonote::blobdata>)
|
||||
else if constexpr (std::is_same_v<T, std::string>)
|
||||
{
|
||||
result = blob;
|
||||
}
|
||||
|
@ -2580,7 +2581,7 @@ block BlockchainLMDB::get_block_from_height(uint64_t height) const
|
|||
return result;
|
||||
}
|
||||
|
||||
cryptonote::blobdata BlockchainLMDB::get_block_blob(const crypto::hash& h) const
|
||||
std::string BlockchainLMDB::get_block_blob(const crypto::hash& h) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
@ -2614,10 +2615,10 @@ block_header BlockchainLMDB::get_block_header_from_height(uint64_t height) const
|
|||
return result;
|
||||
}
|
||||
|
||||
cryptonote::blobdata BlockchainLMDB::get_block_blob_from_height(uint64_t height) const
|
||||
std::string BlockchainLMDB::get_block_blob_from_height(uint64_t height) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
cryptonote::blobdata result = get_and_convert_block_blob_from_height<blobdata>(height);
|
||||
std::string result = get_and_convert_block_blob_from_height<std::string>(height);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -3134,7 +3135,7 @@ uint64_t BlockchainLMDB::get_tx_unlock_time(const crypto::hash& h) const
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool BlockchainLMDB::get_tx_blob(const crypto::hash& h, cryptonote::blobdata &bd) const
|
||||
bool BlockchainLMDB::get_tx_blob(const crypto::hash& h, std::string &bd) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
@ -3169,7 +3170,7 @@ bool BlockchainLMDB::get_tx_blob(const crypto::hash& h, cryptonote::blobdata &bd
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainLMDB::get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &bd) const
|
||||
bool BlockchainLMDB::get_pruned_tx_blob(const crypto::hash& h, std::string &bd) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
@ -3197,7 +3198,7 @@ bool BlockchainLMDB::get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobd
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainLMDB::get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const
|
||||
bool BlockchainLMDB::get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<std::string> &bd) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
@ -3237,7 +3238,7 @@ bool BlockchainLMDB::get_pruned_tx_blobs_from(const crypto::hash& h, size_t coun
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainLMDB::get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &bd) const
|
||||
bool BlockchainLMDB::get_prunable_tx_blob(const crypto::hash& h, std::string &bd) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
@ -3555,7 +3556,7 @@ bool BlockchainLMDB::for_blocks_range(const uint64_t& h1, const uint64_t& h2, st
|
|||
if (ret)
|
||||
throw0(DB_ERROR("Failed to enumerate blocks"));
|
||||
uint64_t height = *(const uint64_t*)k.mv_data;
|
||||
blobdata bd;
|
||||
std::string bd;
|
||||
bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
|
||||
block b;
|
||||
if (!parse_and_validate_block_from_blob(bd, b))
|
||||
|
@ -3609,12 +3610,14 @@ bool BlockchainLMDB::for_all_transactions(std::function<bool(const crypto::hash&
|
|||
if (ret)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to enumerate transactions: ", ret).c_str()));
|
||||
transaction tx;
|
||||
blobdata bd;
|
||||
std::string bd;
|
||||
bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
|
||||
if (pruned)
|
||||
{
|
||||
if (!parse_and_validate_tx_base_from_blob(bd, tx))
|
||||
{
|
||||
throw0(DB_ERROR("Failed to parse tx from blob retrieved from the db"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3976,8 +3979,8 @@ void BlockchainLMDB::block_rtxn_abort() const
|
|||
memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
|
||||
}
|
||||
|
||||
uint64_t BlockchainLMDB::add_block(const std::pair<block, blobdata>& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated,
|
||||
const std::vector<std::pair<transaction, blobdata>>& txs)
|
||||
uint64_t BlockchainLMDB::add_block(const std::pair<block, std::string>& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated,
|
||||
const std::vector<std::pair<transaction, std::string>>& txs)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
@ -4018,8 +4021,8 @@ static bool convert_checkpoint_into_buffer(checkpoint_t const &checkpoint, check
|
|||
header.block_hash = checkpoint.block_hash;
|
||||
header.num_signatures = checkpoint.signatures.size();
|
||||
|
||||
native_to_little_inplace(header.height);
|
||||
native_to_little_inplace(header.num_signatures);
|
||||
oxenc::host_to_little_inplace(header.height);
|
||||
oxenc::host_to_little_inplace(header.num_signatures);
|
||||
|
||||
size_t const bytes_for_signatures = sizeof(*checkpoint.signatures.data()) * checkpoint.signatures.size();
|
||||
result.len = sizeof(header) + bytes_for_signatures;
|
||||
|
@ -4102,8 +4105,8 @@ static checkpoint_t convert_mdb_val_to_checkpoint(MDB_val const value)
|
|||
auto const *signatures =
|
||||
reinterpret_cast<service_nodes::quorum_signature *>(static_cast<uint8_t *>(value.mv_data) + sizeof(*header));
|
||||
|
||||
auto num_sigs = little_to_native(header->num_signatures);
|
||||
result.height = little_to_native(header->height);
|
||||
auto num_sigs = oxenc::little_to_host(header->num_signatures);
|
||||
result.height = oxenc::little_to_host(header->height);
|
||||
result.type = (num_sigs > 0) ? checkpoint_type::service_node : checkpoint_type::hardcoded;
|
||||
result.block_hash = header->block_hash;
|
||||
result.signatures.insert(result.signatures.end(), signatures, signatures + num_sigs);
|
||||
|
@ -4428,7 +4431,7 @@ std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> BlockchainLMDB::get
|
|||
while (num_elems > 0) {
|
||||
const tx_out_index toi = get_output_tx_and_index(amount, num_elems - 1);
|
||||
const uint64_t height = get_tx_block_height(toi.first);
|
||||
if (height + CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE <= blockchain_height)
|
||||
if (height + DEFAULT_TX_SPENDABLE_AGE <= blockchain_height)
|
||||
break;
|
||||
--num_elems;
|
||||
}
|
||||
|
@ -4561,7 +4564,7 @@ void BlockchainLMDB::add_output_blacklist(std::vector<uint64_t> const &blacklist
|
|||
throw0(DB_ERROR(lmdb_error("Failed to add blacklisted output to db transaction: ", ret).c_str()));
|
||||
}
|
||||
|
||||
void BlockchainLMDB::add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata &block, cryptonote::blobdata const *checkpoint)
|
||||
void BlockchainLMDB::add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const std::string &block, std::string const *checkpoint)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
@ -4604,7 +4607,7 @@ void BlockchainLMDB::add_alt_block(const crypto::hash &blkid, const cryptonote::
|
|||
}
|
||||
}
|
||||
|
||||
bool BlockchainLMDB::get_alt_block(const crypto::hash &blkid, alt_block_data_t *data, cryptonote::blobdata *block, cryptonote::blobdata *checkpoint) const
|
||||
bool BlockchainLMDB::get_alt_block(const crypto::hash &blkid, alt_block_data_t *data, std::string *block, std::string *checkpoint) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB:: " << __func__);
|
||||
check_open();
|
||||
|
@ -4692,7 +4695,7 @@ bool BlockchainLMDB::is_read_only() const
|
|||
|
||||
uint64_t BlockchainLMDB::get_database_size() const
|
||||
{
|
||||
return fs::file_size(m_folder / CRYPTONOTE_BLOCKCHAINDATA_FILENAME);
|
||||
return fs::file_size(m_folder / BLOCKCHAINDATA_FILENAME);
|
||||
}
|
||||
|
||||
void BlockchainLMDB::fixup(cryptonote::network_type nettype)
|
||||
|
@ -4735,7 +4738,7 @@ void BlockchainLMDB::fixup(cryptonote::network_type nettype)
|
|||
add_timestamp_and_difficulty(nettype, curr_chain_height, timestamps, difficulties, curr_timestamp, curr_cumulative_diff);
|
||||
|
||||
// NOTE: Calculate next block difficulty
|
||||
if (is_hard_fork_at_least(nettype, cryptonote::network_version_16_pulse, curr_height)
|
||||
if (is_hard_fork_at_least(nettype, hf::hf16_pulse, curr_height)
|
||||
&& block_header_has_pulse_components(get_block_header_from_height(curr_height)))
|
||||
{
|
||||
diff = PULSE_FIXED_DIFFICULTY;
|
||||
|
@ -5241,7 +5244,7 @@ void BlockchainLMDB::migrate_0_1()
|
|||
}
|
||||
|
||||
MDB_dbi o_txs;
|
||||
blobdata bd;
|
||||
std::string bd;
|
||||
block b;
|
||||
MDB_val hk;
|
||||
|
||||
|
@ -5448,7 +5451,7 @@ void BlockchainLMDB::migrate_1_2()
|
|||
else if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to get a record from txs: ", result).c_str()));
|
||||
|
||||
cryptonote::blobdata bd;
|
||||
std::string bd;
|
||||
bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
|
||||
transaction tx;
|
||||
if (!parse_and_validate_tx_from_blob(bd, tx))
|
||||
|
@ -5648,7 +5651,7 @@ void BlockchainLMDB::migrate_3_4()
|
|||
|
||||
MDB_val key, val;
|
||||
uint64_t tx_count = 0;
|
||||
blobdata bd;
|
||||
std::string bd;
|
||||
for(MDB_cursor_op op = MDB_FIRST;; op = MDB_NEXT, bd.clear())
|
||||
{
|
||||
transaction tx;
|
||||
|
@ -5730,7 +5733,7 @@ void BlockchainLMDB::migrate_3_4()
|
|||
throw0(DB_ERROR(lmdb_error("Failed to query m_blocks: ", result).c_str()));
|
||||
const uint64_t blockchain_height = db_stats.ms_entries;
|
||||
|
||||
boost::circular_buffer<uint64_t> long_term_block_weights(CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE);
|
||||
boost::circular_buffer<uint64_t> long_term_block_weights(LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE);
|
||||
|
||||
/* the block_info table name is the same but the old version and new version
|
||||
* have incompatible data. Create a new table. We want the name to be similar
|
||||
|
@ -5796,16 +5799,17 @@ void BlockchainLMDB::migrate_3_4()
|
|||
throw0(DB_ERROR(lmdb_error("Failed to query m_blocks: ", result).c_str()));
|
||||
if (vb.mv_size == 0)
|
||||
throw0(DB_ERROR("Invalid data from m_blocks"));
|
||||
const uint8_t block_major_version = *((const uint8_t*)vb.mv_data);
|
||||
if (block_major_version >= HF_VERSION_LONG_TERM_BLOCK_WEIGHT)
|
||||
const hf block_major_version{*((const uint8_t*)vb.mv_data)};
|
||||
if (block_major_version >= feature::LONG_TERM_BLOCK_WEIGHT)
|
||||
past_long_term_weight = true;
|
||||
}
|
||||
|
||||
uint64_t long_term_block_weight;
|
||||
if (past_long_term_weight)
|
||||
{
|
||||
std::vector<uint64_t> weights(long_term_block_weights.begin(), long_term_block_weights.end());
|
||||
uint64_t long_term_effective_block_median_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, epee::misc_utils::median(weights));
|
||||
uint64_t long_term_effective_block_median_weight = std::max<uint64_t>(
|
||||
BLOCK_GRANTED_FULL_REWARD_ZONE_V5,
|
||||
tools::median(std::vector<uint64_t>{long_term_block_weights.begin(), long_term_block_weights.end()}));
|
||||
long_term_block_weight = std::min<uint64_t>(bi.bi_weight, long_term_effective_block_median_weight + long_term_effective_block_median_weight * 2 / 5);
|
||||
}
|
||||
else
|
||||
|
@ -5872,7 +5876,7 @@ void BlockchainLMDB::migrate_4_5(cryptonote::network_type nettype)
|
|||
{
|
||||
crypto::hash key;
|
||||
alt_block_data_t data;
|
||||
cryptonote::blobdata blob;
|
||||
std::string blob;
|
||||
};
|
||||
|
||||
std::vector<entry_t> new_entries;
|
||||
|
@ -5975,12 +5979,12 @@ void BlockchainLMDB::migrate_5_6()
|
|||
// unexpected padding
|
||||
|
||||
auto const *header = static_cast<blk_checkpoint_header const *>(val.mv_data);
|
||||
auto num_sigs = little_to_native(header->num_signatures);
|
||||
auto num_sigs = oxenc::little_to_host(header->num_signatures);
|
||||
auto const *aligned_signatures = reinterpret_cast<service_nodes::quorum_signature *>(static_cast<uint8_t *>(val.mv_data) + sizeof(*header));
|
||||
if (num_sigs == 0) continue; // NOTE: Hardcoded checkpoints
|
||||
|
||||
checkpoint_t checkpoint = {};
|
||||
checkpoint.height = little_to_native(header->height);
|
||||
checkpoint.height = oxenc::little_to_host(header->height);
|
||||
checkpoint.type = (num_sigs > 0) ? checkpoint_type::service_node : checkpoint_type::hardcoded;
|
||||
checkpoint.block_hash = header->block_hash;
|
||||
|
||||
|
@ -6196,15 +6200,15 @@ void BlockchainLMDB::clear_service_node_data()
|
|||
}
|
||||
|
||||
template <typename C>
|
||||
C native_to_little_container(const C& c) {
|
||||
C host_to_little_container(const C& c) {
|
||||
C result{c};
|
||||
for (auto& x : result) native_to_little_inplace(x);
|
||||
for (auto& x : result) oxenc::host_to_little_inplace(x);
|
||||
return result;
|
||||
}
|
||||
template <typename C>
|
||||
C little_to_native_container(const C& c) {
|
||||
C little_to_host_container(const C& c) {
|
||||
C result{c};
|
||||
for (auto& x : result) little_to_native_inplace(x);
|
||||
for (auto& x : result) oxenc::little_to_host_inplace(x);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -6212,25 +6216,25 @@ struct service_node_proof_serialized_old
|
|||
{
|
||||
service_node_proof_serialized_old() = default;
|
||||
service_node_proof_serialized_old(const service_nodes::proof_info &info)
|
||||
: timestamp{native_to_little(info.timestamp)},
|
||||
ip{native_to_little(info.proof->public_ip)},
|
||||
storage_https_port{native_to_little(info.proof->storage_https_port)},
|
||||
storage_omq_port{native_to_little(info.proof->storage_omq_port)},
|
||||
quorumnet_port{native_to_little(info.proof->qnet_port)},
|
||||
version{native_to_little_container(info.proof->version)},
|
||||
: timestamp{oxenc::host_to_little(info.timestamp)},
|
||||
ip{oxenc::host_to_little(info.proof->public_ip)},
|
||||
storage_https_port{oxenc::host_to_little(info.proof->storage_https_port)},
|
||||
storage_omq_port{oxenc::host_to_little(info.proof->storage_omq_port)},
|
||||
quorumnet_port{oxenc::host_to_little(info.proof->qnet_port)},
|
||||
version{host_to_little_container(info.proof->version)},
|
||||
pubkey_ed25519{info.proof->pubkey_ed25519}
|
||||
{}
|
||||
|
||||
void update(service_nodes::proof_info &info) const
|
||||
{
|
||||
info.timestamp = little_to_native(timestamp);
|
||||
info.timestamp = oxenc::little_to_host(timestamp);
|
||||
if (info.timestamp > info.effective_timestamp)
|
||||
info.effective_timestamp = info.timestamp;
|
||||
info.proof->public_ip = little_to_native(ip);
|
||||
info.proof->storage_https_port = little_to_native(storage_https_port);
|
||||
info.proof->storage_omq_port = little_to_native(storage_omq_port);
|
||||
info.proof->qnet_port = little_to_native(quorumnet_port);
|
||||
info.proof->version = little_to_native_container(version);
|
||||
info.proof->public_ip = oxenc::little_to_host(ip);
|
||||
info.proof->storage_https_port = oxenc::little_to_host(storage_https_port);
|
||||
info.proof->storage_omq_port = oxenc::little_to_host(storage_omq_port);
|
||||
info.proof->qnet_port = oxenc::little_to_host(quorumnet_port);
|
||||
info.proof->version = little_to_host_container(version);
|
||||
info.proof->storage_server_version = {0, 0, 0};
|
||||
info.proof->lokinet_version = {0, 0, 0};
|
||||
info.update_pubkey(pubkey_ed25519);
|
||||
|
@ -6257,8 +6261,8 @@ struct service_node_proof_serialized : service_node_proof_serialized_old {
|
|||
service_node_proof_serialized() = default;
|
||||
service_node_proof_serialized(const service_nodes::proof_info &info)
|
||||
: service_node_proof_serialized_old{info},
|
||||
storage_server_version{native_to_little_container(info.proof->storage_server_version)},
|
||||
lokinet_version{native_to_little_container(info.proof->lokinet_version)}
|
||||
storage_server_version{host_to_little_container(info.proof->storage_server_version)},
|
||||
lokinet_version{host_to_little_container(info.proof->lokinet_version)}
|
||||
{}
|
||||
std::array<uint16_t, 3> storage_server_version{};
|
||||
std::array<uint16_t, 3> lokinet_version{};
|
||||
|
@ -6267,8 +6271,8 @@ struct service_node_proof_serialized : service_node_proof_serialized_old {
|
|||
void update(service_nodes::proof_info& info) const {
|
||||
if (!info.proof) info.proof = std::unique_ptr<uptime_proof::Proof>(new uptime_proof::Proof());
|
||||
service_node_proof_serialized_old::update(info);
|
||||
info.proof->storage_server_version = little_to_native_container(storage_server_version);
|
||||
info.proof->lokinet_version = little_to_native_container(lokinet_version);
|
||||
info.proof->storage_server_version = little_to_host_container(storage_server_version);
|
||||
info.proof->lokinet_version = little_to_host_container(lokinet_version);
|
||||
}
|
||||
|
||||
operator service_nodes::proof_info() const
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <atomic>
|
||||
|
||||
#include "blockchain_db/blockchain_db.h"
|
||||
#include "cryptonote_basic/blobdatatype.h" // for type blobdata
|
||||
#include "ringct/rctTypes.h"
|
||||
#include "common/fs.h"
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
@ -208,9 +207,9 @@ public:
|
|||
|
||||
block_header get_block_header_from_height(uint64_t height) const override;
|
||||
|
||||
cryptonote::blobdata get_block_blob(const crypto::hash& h) const override;
|
||||
std::string get_block_blob(const crypto::hash& h) const override;
|
||||
|
||||
cryptonote::blobdata get_block_blob_from_height(uint64_t height) const override;
|
||||
std::string get_block_blob_from_height(uint64_t height) const override;
|
||||
|
||||
std::vector<uint64_t> get_block_cumulative_rct_outputs(const std::vector<uint64_t> &heights) const override;
|
||||
|
||||
|
@ -249,10 +248,10 @@ public:
|
|||
|
||||
uint64_t get_tx_unlock_time(const crypto::hash& h) const override;
|
||||
|
||||
bool get_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override;
|
||||
bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override;
|
||||
bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const override;
|
||||
bool get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override;
|
||||
bool get_tx_blob(const crypto::hash& h, std::string &tx) const override;
|
||||
bool get_pruned_tx_blob(const crypto::hash& h, std::string &tx) const override;
|
||||
bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<std::string> &bd) const override;
|
||||
bool get_prunable_tx_blob(const crypto::hash& h, std::string &tx) const override;
|
||||
bool get_prunable_tx_hash(const crypto::hash& tx_hash, crypto::hash &prunable_hash) const override;
|
||||
|
||||
uint64_t get_tx_count() const override;
|
||||
|
@ -277,40 +276,40 @@ public:
|
|||
|
||||
bool has_key_image(const crypto::key_image& img) const override;
|
||||
|
||||
void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t& meta) override;
|
||||
void add_txpool_tx(const crypto::hash &txid, const std::string &blob, const txpool_tx_meta_t& meta) override;
|
||||
void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t& meta) override;
|
||||
uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const override;
|
||||
bool txpool_has_tx(const crypto::hash &txid) const override;
|
||||
void remove_txpool_tx(const crypto::hash& txid) override;
|
||||
bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const override;
|
||||
bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const override;
|
||||
cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const override;
|
||||
bool get_txpool_tx_blob(const crypto::hash& txid, std::string &bd) const override;
|
||||
std::string get_txpool_tx_blob(const crypto::hash& txid) const override;
|
||||
uint32_t get_blockchain_pruning_seed() const override;
|
||||
bool prune_blockchain(uint32_t pruning_seed = 0) override;
|
||||
bool update_pruning() override;
|
||||
bool check_pruning() override;
|
||||
|
||||
void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata &blob, const cryptonote::blobdata *checkpoint) override;
|
||||
bool get_alt_block(const crypto::hash &blkid, alt_block_data_t *data, cryptonote::blobdata *blob, cryptonote::blobdata *checkpoint) const override;
|
||||
void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const std::string &blob, const std::string *checkpoint) override;
|
||||
bool get_alt_block(const crypto::hash &blkid, alt_block_data_t *data, std::string *blob, std::string *checkpoint) const override;
|
||||
void remove_alt_block(const crypto::hash &blkid) override;
|
||||
uint64_t get_alt_block_count() override;
|
||||
void drop_alt_blocks() override;
|
||||
|
||||
bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob = false, bool include_unrelayed_txes = true) const override;
|
||||
bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const std::string*)> f, bool include_blob = false, bool include_unrelayed_txes = true) const override;
|
||||
|
||||
bool for_all_key_images(std::function<bool(const crypto::key_image&)>) const override;
|
||||
bool for_blocks_range(const uint64_t& h1, const uint64_t& h2, std::function<bool(uint64_t, const crypto::hash&, const cryptonote::block&)>) const override;
|
||||
bool for_all_transactions(std::function<bool(const crypto::hash&, const cryptonote::transaction&)>, bool pruned) const override;
|
||||
bool for_all_outputs(std::function<bool(uint64_t amount, const crypto::hash &tx_hash, uint64_t height, size_t tx_idx)> f) const override;
|
||||
bool for_all_outputs(uint64_t amount, const std::function<bool(uint64_t height)> &f) const override;
|
||||
bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata *block_blob, const cryptonote::blobdata *checkpoint_blob)> f, bool include_blob = false) const override;
|
||||
bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const std::string *block_blob, const std::string *checkpoint_blob)> f, bool include_blob = false) const override;
|
||||
|
||||
uint64_t add_block( const std::pair<block, blobdata>& blk
|
||||
uint64_t add_block( const std::pair<block, std::string>& blk
|
||||
, size_t block_weight
|
||||
, uint64_t long_term_block_weight
|
||||
, const difficulty_type& cumulative_difficulty
|
||||
, const uint64_t& coins_generated
|
||||
, const std::vector<std::pair<transaction, blobdata>>& txs
|
||||
, const std::vector<std::pair<transaction, std::string>>& txs
|
||||
) override;
|
||||
void update_block_checkpoint(checkpoint_t const &checkpoint) override;
|
||||
void remove_block_checkpoint(uint64_t height) override;
|
||||
|
@ -376,7 +375,7 @@ private:
|
|||
|
||||
void remove_block() override;
|
||||
|
||||
uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) override;
|
||||
uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, std::string>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) override;
|
||||
|
||||
void remove_transaction_data(const crypto::hash& tx_hash, const transaction& tx) override;
|
||||
|
||||
|
@ -446,7 +445,7 @@ private:
|
|||
template <typename T,
|
||||
std::enable_if_t<std::is_same_v<T, cryptonote::block> ||
|
||||
std::is_same_v<T, cryptonote::block_header> ||
|
||||
std::is_same_v<T, cryptonote::blobdata>, int> = 0>
|
||||
std::is_same_v<T, std::string>, int> = 0>
|
||||
T get_and_convert_block_blob_from_height(uint64_t height) const;
|
||||
|
||||
MDB_env* m_env;
|
||||
|
|
|
@ -0,0 +1,571 @@
|
|||
// Copyright (c) 2021, The Oxen 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 "db_sqlite.h"
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include <sodium.h>
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
#include "cryptonote_config.h"
|
||||
#include "cryptonote_core/blockchain.h"
|
||||
#include "cryptonote_core/service_node_list.h"
|
||||
#include "common/string_util.h"
|
||||
#include "cryptonote_basic/hardfork.h"
|
||||
|
||||
#undef OXEN_DEFAULT_LOG_CATEGORY
|
||||
#define OXEN_DEFAULT_LOG_CATEGORY "blockchain.db.sqlite"
|
||||
|
||||
namespace cryptonote {
|
||||
|
||||
BlockchainSQLite::BlockchainSQLite(cryptonote::network_type nettype, fs::path db_path): db::Database(db_path, ""), m_nettype(nettype), filename {db_path.u8string()} {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
|
||||
height = 0;
|
||||
|
||||
if (!db.tableExists("batched_payments_accrued") || !db.tableExists("batched_payments_raw") || !db.tableExists("batch_db_info")) {
|
||||
create_schema();
|
||||
}
|
||||
|
||||
height = prepared_get<int64_t>("SELECT height FROM batch_db_info");
|
||||
}
|
||||
|
||||
void BlockchainSQLite::create_schema() {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
|
||||
|
||||
db.exec(R"(
|
||||
CREATE TABLE batched_payments_accrued(
|
||||
address VARCHAR NOT NULL,
|
||||
amount BIGINT NOT NULL,
|
||||
PRIMARY KEY(address),
|
||||
CHECK(amount >= 0)
|
||||
);
|
||||
|
||||
CREATE TRIGGER batch_payments_delete_empty AFTER UPDATE ON batched_payments_accrued
|
||||
FOR EACH ROW WHEN NEW.amount = 0 BEGIN
|
||||
DELETE FROM batched_payments_accrued WHERE address = NEW.address;
|
||||
END;
|
||||
|
||||
CREATE TABLE batched_payments_raw(
|
||||
address VARCHAR NOT NULL,
|
||||
amount BIGINT NOT NULL,
|
||||
height_paid BIGINT NOT NULL,
|
||||
PRIMARY KEY(address, height_paid),
|
||||
CHECK(amount >= 0)
|
||||
);
|
||||
|
||||
CREATE INDEX batched_payments_raw_height_idx ON batched_payments_raw(height_paid);
|
||||
|
||||
CREATE TABLE batch_db_info(
|
||||
height BIGINT NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO batch_db_info(height) VALUES(0);
|
||||
|
||||
CREATE TRIGGER batch_payments_prune AFTER UPDATE ON batch_db_info
|
||||
FOR EACH ROW BEGIN
|
||||
DELETE FROM batched_payments_raw WHERE height_paid < (NEW.height - 10000);
|
||||
END;
|
||||
|
||||
CREATE VIEW batched_payments_paid AS SELECT * FROM batched_payments_raw;
|
||||
|
||||
CREATE TRIGGER make_payment INSTEAD OF INSERT ON batched_payments_paid
|
||||
FOR EACH ROW BEGIN
|
||||
UPDATE batched_payments_accrued SET amount = (amount - NEW.amount) WHERE address = NEW.address;
|
||||
SELECT RAISE(ABORT, 'Address not found') WHERE changes() = 0;
|
||||
INSERT INTO batched_payments_raw(address, amount, height_paid) VALUES(NEW.address, NEW.amount, NEW.height_paid);
|
||||
END;
|
||||
|
||||
CREATE TRIGGER rollback_payment INSTEAD OF DELETE ON batched_payments_paid
|
||||
FOR EACH ROW BEGIN
|
||||
DELETE FROM batched_payments_raw WHERE address = OLD.address AND height_paid = OLD.height_paid;
|
||||
INSERT INTO batched_payments_accrued(address, amount) VALUES(OLD.address, OLD.amount)
|
||||
ON CONFLICT(address) DO UPDATE SET amount = (amount + excluded.amount);
|
||||
END;
|
||||
)");
|
||||
|
||||
MDEBUG("Database setup complete");
|
||||
}
|
||||
|
||||
void BlockchainSQLite::reset_database() {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
|
||||
|
||||
db.exec(R"(
|
||||
DROP TABLE IF EXISTS batched_payments_accrued;
|
||||
|
||||
DROP VIEW IF EXISTS batched_payments_paid;
|
||||
|
||||
DROP TABLE IF EXISTS batched_payments_raw;
|
||||
|
||||
DROP TABLE IF EXISTS batch_db_info;
|
||||
)");
|
||||
|
||||
create_schema();
|
||||
|
||||
MDEBUG("Database reset complete");
|
||||
}
|
||||
|
||||
void BlockchainSQLite::update_height(uint64_t new_height) {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__ << " Called with new height: " << new_height);
|
||||
height = new_height;
|
||||
prepared_exec(
|
||||
"UPDATE batch_db_info SET height = ?",
|
||||
static_cast<int64_t>(height));
|
||||
}
|
||||
|
||||
void BlockchainSQLite::increment_height() {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__ << " Called with height: " << height + 1);
|
||||
update_height(height + 1);
|
||||
}
|
||||
|
||||
void BlockchainSQLite::decrement_height() {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__ << " Called with height: " << height - 1);
|
||||
update_height(height - 1);
|
||||
}
|
||||
|
||||
bool BlockchainSQLite::add_sn_rewards(const std::vector<cryptonote::batch_sn_payment>& payments) {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
|
||||
auto insert_payment = prepared_st(
|
||||
"INSERT INTO batched_payments_accrued (address, amount) VALUES (?, ?)"
|
||||
" ON CONFLICT (address) DO UPDATE SET amount = amount + excluded.amount");
|
||||
|
||||
for (auto& payment: payments) {
|
||||
std::string address_str = cryptonote::get_account_address_as_str(m_nettype, 0, payment.address_info.address);
|
||||
auto amt = static_cast<int64_t>(payment.amount);
|
||||
MTRACE(fmt::format("Adding record for SN reward contributor {} to database with amount {}",
|
||||
address_str, amt));
|
||||
|
||||
db::exec_query(insert_payment, address_str, amt);
|
||||
insert_payment->reset();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainSQLite::subtract_sn_rewards(const std::vector<cryptonote::batch_sn_payment>& payments) {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
|
||||
auto update_payment = prepared_st(
|
||||
"UPDATE batched_payments_accrued SET amount = (amount - ?) WHERE address = ?");
|
||||
|
||||
for (auto& payment: payments) {
|
||||
std::string address_str = cryptonote::get_account_address_as_str(m_nettype, 0, payment.address_info.address);
|
||||
auto result = db::exec_query(update_payment, static_cast<int64_t>(payment.amount), address_str);
|
||||
if (!result) {
|
||||
MERROR("tried to subtract payment from an address that doesn't exist: " << address_str);
|
||||
return false;
|
||||
}
|
||||
update_payment->reset();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<cryptonote::batch_sn_payment> BlockchainSQLite::get_sn_payments(uint64_t block_height) {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
|
||||
|
||||
// <= here because we might have crap in the db that we don't clear until we actually add the HF
|
||||
// block later on. (This is a pretty slim edge case that happened on devnet and is probably
|
||||
// virtually impossible on mainnet).
|
||||
if (m_nettype != cryptonote::network_type::FAKECHAIN && block_height <= cryptonote::get_hard_fork_heights(m_nettype, hf::hf19_reward_batching).first.value_or(0))
|
||||
return {};
|
||||
|
||||
const auto& conf = get_config(m_nettype);
|
||||
|
||||
auto accrued_amounts = prepared_results<std::string, int64_t>(
|
||||
"SELECT address, amount FROM batched_payments_accrued WHERE amount >= ? ORDER BY address ASC",
|
||||
static_cast<int64_t>(conf.MIN_BATCH_PAYMENT_AMOUNT * BATCH_REWARD_FACTOR));
|
||||
|
||||
std::vector<cryptonote::batch_sn_payment> payments;
|
||||
|
||||
for (auto [address, amount] : accrued_amounts) {
|
||||
if (cryptonote::is_valid_address(address, m_nettype)) {
|
||||
cryptonote::address_parse_info addr_info {};
|
||||
cryptonote::get_account_address_from_str(addr_info, m_nettype, address);
|
||||
uint64_t next_payout_height = addr_info.address.next_payout_height(block_height - 1, conf.BATCHING_INTERVAL);
|
||||
if (block_height == next_payout_height) {
|
||||
payments.emplace_back(
|
||||
std::move(address),
|
||||
amount / BATCH_REWARD_FACTOR * BATCH_REWARD_FACTOR /* truncate to atomic OXEN */,
|
||||
m_nettype);
|
||||
}
|
||||
} else {
|
||||
MERROR("Invalid address returned from batching database: " << address);
|
||||
}
|
||||
}
|
||||
|
||||
return payments;
|
||||
}
|
||||
|
||||
|
||||
uint64_t BlockchainSQLite::get_accrued_earnings(const std::string& address) {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
|
||||
|
||||
SQLite::Statement select_earnings {
|
||||
db,
|
||||
"SELECT amount FROM batched_payments_accrued WHERE address = ?;"
|
||||
};
|
||||
select_earnings.bind(1, address);
|
||||
|
||||
uint64_t amount{};
|
||||
while (select_earnings.executeStep()) {
|
||||
amount = static_cast<uint64_t>(select_earnings.getColumn(0).getInt64() / 1000);
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
std::pair<std::vector<std::string>, std::vector<uint64_t>> BlockchainSQLite::get_all_accrued_earnings() {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
|
||||
|
||||
SQLite::Statement select_earnings {
|
||||
db,
|
||||
"SELECT address, amount FROM batched_payments_accrued;"
|
||||
};
|
||||
|
||||
std::vector<uint64_t> amounts;
|
||||
std::vector<std::string> addresses;
|
||||
while (select_earnings.executeStep()) {
|
||||
addresses.emplace_back(select_earnings.getColumn(0).getString());
|
||||
amounts.emplace_back(static_cast<uint64_t>(select_earnings.getColumn(1).getInt64() / 1000));
|
||||
}
|
||||
|
||||
return std::make_pair(addresses, amounts);
|
||||
}
|
||||
|
||||
|
||||
std::vector<cryptonote::batch_sn_payment> BlockchainSQLite::calculate_rewards(hf hf_version, uint64_t distribution_amount, service_nodes::service_node_info sn_info) {
|
||||
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
|
||||
|
||||
// Find out how much is due for the operator: fee_portions/PORTIONS * reward
|
||||
assert(sn_info.portions_for_operator <= old::STAKING_PORTIONS);
|
||||
uint64_t operator_fee = mul128_div64(sn_info.portions_for_operator, distribution_amount, old::STAKING_PORTIONS);
|
||||
|
||||
assert(operator_fee <= distribution_amount);
|
||||
|
||||
std::vector<cryptonote::batch_sn_payment> payments;
|
||||
// Pay the operator fee to the operator
|
||||
if (operator_fee > 0)
|
||||
payments.emplace_back(sn_info.operator_address, operator_fee, m_nettype);
|
||||
|
||||
// Pay the balance to all the contributors (including the operator again)
|
||||
uint64_t total_contributed_to_sn = std::accumulate(
|
||||
sn_info.contributors.begin(),
|
||||
sn_info.contributors.end(),
|
||||
uint64_t(0),
|
||||
[](auto&& a, auto&& b) { return a + b.amount; });
|
||||
|
||||
for (auto& contributor: sn_info.contributors) {
|
||||
// This calculates (contributor.amount / total_contributed_to_winner_sn) * (distribution_amount - operator_fee) but using 128 bit integer math
|
||||
uint64_t c_reward = mul128_div64(contributor.amount, distribution_amount - operator_fee, total_contributed_to_sn);
|
||||
if (c_reward > 0)
|
||||
payments.emplace_back(contributor.address, c_reward, m_nettype);
|
||||
}
|
||||
|
||||
return payments;
|
||||
}
|
||||
|
||||
// Calculates block rewards, then invokes either `add_sn_rewards` (if `add`) or
|
||||
// `subtract_sn_rewards` (if `!add`) to process them.
|
||||
bool BlockchainSQLite::reward_handler(
|
||||
const cryptonote::block& block,
|
||||
const service_nodes::service_node_list::state_t& service_nodes_state,
|
||||
bool add)
|
||||
{
|
||||
// The method we call do actually handle the change: either `add_sn_payments` if add is true,
|
||||
// `subtract_sn_payments` otherwise:
|
||||
bool (BlockchainSQLite::* add_or_subtract)(const std::vector<cryptonote::batch_sn_payment>&)
|
||||
= add ? &BlockchainSQLite::add_sn_rewards : &BlockchainSQLite::subtract_sn_rewards;
|
||||
|
||||
// From here on we calculate everything in milli-atomic OXEN (i.e. thousanths of an atomic
|
||||
// OXEN) so that our integer math has minimal loss from integer division.
|
||||
if (block.reward > std::numeric_limits<uint64_t>::max() / BATCH_REWARD_FACTOR)
|
||||
throw std::logic_error{"Reward distribution amount is too large"};
|
||||
|
||||
uint64_t block_reward = block.reward * BATCH_REWARD_FACTOR;
|
||||
uint64_t service_node_reward = cryptonote::service_node_reward_formula(0, block.major_version) * BATCH_REWARD_FACTOR;
|
||||
|
||||
// Step 1: Pay out the block producer their tx fees (note that, unlike the below, this applies
|
||||
// even if the SN isn't currently payable).
|
||||
if (block_reward < service_node_reward && m_nettype != cryptonote::network_type::FAKECHAIN)
|
||||
throw std::logic_error{"Invalid payment: block reward is too small"};
|
||||
|
||||
if (uint64_t tx_fees = block_reward - service_node_reward;
|
||||
tx_fees > 0
|
||||
&& block.service_node_winner_key // "service_node_winner_key" tracks the pulse winner; 0 if a mined block
|
||||
&& crypto_core_ed25519_is_valid_point(reinterpret_cast<const unsigned char *>(block.service_node_winner_key.data))
|
||||
) {
|
||||
|
||||
if (auto service_node_winner = service_nodes_state.service_nodes_infos.find(block.service_node_winner_key);
|
||||
service_node_winner != service_nodes_state.service_nodes_infos.end()) {
|
||||
auto tx_fee_payments = calculate_rewards(block.major_version, tx_fees, *service_node_winner->second);
|
||||
// Takes the block producer and adds its contributors to the batching database for the transaction fees
|
||||
if (!(this->*add_or_subtract)(tx_fee_payments))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto block_height = get_block_height(block);
|
||||
|
||||
// Step 2: Iterate over the whole service node list and pay each node 1/service_node_list fraction
|
||||
const auto payable_service_nodes = service_nodes_state.payable_service_nodes_infos(block_height, m_nettype);
|
||||
size_t total_service_nodes_payable = payable_service_nodes.size();
|
||||
for (const auto& [node_pubkey, node_info]: payable_service_nodes) {
|
||||
auto payable_service_node = service_nodes_state.service_nodes_infos.find(node_pubkey);
|
||||
if (payable_service_node == service_nodes_state.service_nodes_infos.end())
|
||||
continue;
|
||||
auto snode_rewards = calculate_rewards(block.major_version, service_node_reward / total_service_nodes_payable, * payable_service_node -> second);
|
||||
// Takes the node and adds its contributors to the batching database
|
||||
if (!(this->*add_or_subtract)(snode_rewards))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3: Add Governance reward to the list
|
||||
if (m_nettype != cryptonote::network_type::FAKECHAIN) {
|
||||
std::vector<cryptonote::batch_sn_payment> governance_rewards;
|
||||
cryptonote::address_parse_info governance_wallet_address;
|
||||
cryptonote::get_account_address_from_str(governance_wallet_address, m_nettype,
|
||||
cryptonote::get_config(m_nettype).governance_wallet_address(block.major_version));
|
||||
uint64_t foundation_reward = cryptonote::governance_reward_formula(block.major_version) * BATCH_REWARD_FACTOR;
|
||||
governance_rewards.emplace_back(governance_wallet_address.address, foundation_reward, m_nettype);
|
||||
if (!(this->*add_or_subtract)(governance_rewards))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainSQLite::add_block(const cryptonote::block& block,
|
||||
const service_nodes::service_node_list::state_t& service_nodes_state) {
|
||||
auto block_height = get_block_height(block);
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__ << " called on height: " << block_height);
|
||||
|
||||
auto hf_version = block.major_version;
|
||||
if (hf_version < hf::hf19_reward_batching) {
|
||||
update_height(block_height);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto fork_height = cryptonote::get_hard_fork_heights(m_nettype, hf::hf19_reward_batching);
|
||||
if (block_height == fork_height.first.value_or(0)) {
|
||||
MDEBUG("Batching of Service Node Rewards Begins");
|
||||
reset_database();
|
||||
update_height(block_height - 1);
|
||||
}
|
||||
|
||||
if (block_height != height + 1) {
|
||||
MERROR(fmt::format("Block height ({}) out of sync with batching database ({})", block_height, height));
|
||||
return false;
|
||||
}
|
||||
|
||||
// We query our own database as a source of truth to verify the blocks payments against. The calculated_rewards
|
||||
// variable contains a known good list of who should have been paid in this block
|
||||
auto calculated_rewards = get_sn_payments(block_height);
|
||||
|
||||
// We iterate through the block's coinbase payments and build a copy of our own list of the payments
|
||||
// miner_tx_vouts this will be compared against calculated_rewards and if they match we know the block is
|
||||
// paying the correct people only.
|
||||
std::vector<std::tuple<crypto::public_key, uint64_t>> miner_tx_vouts;
|
||||
for (auto & vout: block.miner_tx.vout)
|
||||
miner_tx_vouts.emplace_back(var::get<txout_to_key>(vout.target).key, vout.amount);
|
||||
|
||||
try {
|
||||
SQLite::Transaction transaction {
|
||||
db,
|
||||
SQLite::TransactionBehavior::IMMEDIATE
|
||||
};
|
||||
|
||||
// Goes through the miner transactions vouts checks they are right and marks them as paid in the database
|
||||
if (!validate_batch_payment(miner_tx_vouts, calculated_rewards, block_height)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!reward_handler(block, service_nodes_state, /*add=*/ true))
|
||||
return false;
|
||||
|
||||
increment_height();
|
||||
|
||||
transaction.commit();
|
||||
} catch (std::exception& e) {
|
||||
MFATAL("Error adding reward payments: " << e.what());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainSQLite::pop_block(const cryptonote::block& block,
|
||||
const service_nodes::service_node_list::state_t& service_nodes_state) {
|
||||
auto block_height = get_block_height(block);
|
||||
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__ << " called on height: " << block_height);
|
||||
if (height < block_height) {
|
||||
MDEBUG("Block above batching DB height skipping pop");
|
||||
return true;
|
||||
}
|
||||
if (block_height != height) {
|
||||
MERROR("Block height out of sync with batching database");
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& conf = get_config(m_nettype);
|
||||
auto hf_version = block.major_version;
|
||||
if (hf_version < hf::hf19_reward_batching) {
|
||||
decrement_height();
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
SQLite::Transaction transaction {
|
||||
db,
|
||||
SQLite::TransactionBehavior::IMMEDIATE
|
||||
};
|
||||
|
||||
if (!reward_handler(block, service_nodes_state, /*add=*/ false))
|
||||
return false;
|
||||
|
||||
// Add back to the database payments that had been made in this block
|
||||
delete_block_payments(block_height);
|
||||
|
||||
decrement_height();
|
||||
transaction.commit();
|
||||
} catch (std::exception& e) {
|
||||
MFATAL("Error subtracting reward payments: " << e.what());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainSQLite::validate_batch_payment(
|
||||
const std::vector<std::tuple<crypto::public_key, uint64_t>>& miner_tx_vouts,
|
||||
const std::vector<cryptonote::batch_sn_payment>& calculated_payments_from_batching_db,
|
||||
uint64_t block_height) {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
|
||||
|
||||
if (miner_tx_vouts.size() != calculated_payments_from_batching_db.size()) {
|
||||
MERROR(fmt::format("Length of batch payments ({}) does not match block vouts ({})", calculated_payments_from_batching_db.size(), miner_tx_vouts.size()));
|
||||
return false;
|
||||
}
|
||||
|
||||
int8_t vout_index = 0;
|
||||
uint64_t total_oxen_payout_in_our_db = std::accumulate(
|
||||
calculated_payments_from_batching_db.begin(),
|
||||
calculated_payments_from_batching_db.end(),
|
||||
uint64_t(0),
|
||||
[](auto&& a, auto&& b) { return a + b.amount; });
|
||||
uint64_t total_oxen_payout_in_vouts = 0;
|
||||
std::vector<batch_sn_payment> finalised_payments;
|
||||
cryptonote::keypair
|
||||
const deterministic_keypair = cryptonote::get_deterministic_keypair_from_height(block_height);
|
||||
for (size_t vout_index = 0; vout_index < miner_tx_vouts.size(); vout_index++) {
|
||||
const auto& [pubkey, amt] = miner_tx_vouts[vout_index];
|
||||
uint64_t amount = amt * BATCH_REWARD_FACTOR;
|
||||
const auto& from_db = calculated_payments_from_batching_db[vout_index];
|
||||
if (amount != from_db.amount) {
|
||||
MERROR(fmt::format("Batched payout amount incorrect. Should be {}, not {}", from_db.amount, amount));
|
||||
return false;
|
||||
}
|
||||
crypto::public_key out_eph_public_key{};
|
||||
if (!cryptonote::get_deterministic_output_key(from_db.address_info.address, deterministic_keypair, vout_index, out_eph_public_key)) {
|
||||
MERROR("Failed to generate output one-time public key");
|
||||
return false;
|
||||
}
|
||||
if (tools::view_guts(pubkey) != tools::view_guts(out_eph_public_key)) {
|
||||
MERROR("Output ephemeral public key does not match");
|
||||
return false;
|
||||
}
|
||||
total_oxen_payout_in_vouts += amount;
|
||||
finalised_payments.emplace_back(from_db.address, amount, m_nettype);
|
||||
}
|
||||
if (total_oxen_payout_in_vouts != total_oxen_payout_in_our_db) {
|
||||
MERROR(fmt::format("Total batched payout amount incorrect. Should be {}, not {}", total_oxen_payout_in_our_db, total_oxen_payout_in_vouts));
|
||||
return false;
|
||||
}
|
||||
|
||||
return save_payments(block_height, finalised_payments);
|
||||
}
|
||||
|
||||
bool BlockchainSQLite::save_payments(uint64_t block_height, const std::vector<batch_sn_payment>& paid_amounts) {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
|
||||
|
||||
auto select_sum = prepared_st(
|
||||
"SELECT amount from batched_payments_accrued WHERE address = ?");
|
||||
|
||||
auto update_paid = prepared_st(
|
||||
"INSERT INTO batched_payments_paid (address, amount, height_paid) VALUES (?,?,?)");
|
||||
|
||||
for (const auto& payment: paid_amounts) {
|
||||
if (auto maybe_amount = db::exec_and_maybe_get<int64_t>(select_sum, payment.address))
|
||||
{
|
||||
// Truncate the thousanths amount to an atomic OXEN:
|
||||
auto amount = static_cast<uint64_t>(*maybe_amount) / BATCH_REWARD_FACTOR * BATCH_REWARD_FACTOR;
|
||||
|
||||
if (amount != payment.amount) {
|
||||
MERROR(fmt::format("Invalid amounts passed in to save payments for address {}: received {}, expected {} (truncated from {})",
|
||||
payment.address, payment.amount, amount, *maybe_amount));
|
||||
return false;
|
||||
}
|
||||
|
||||
db::exec_query(update_paid, payment.address, static_cast<int64_t>(amount), static_cast<int64_t>(block_height));
|
||||
update_paid->reset();
|
||||
}
|
||||
else {
|
||||
// This shouldn't occur: we validate payout addresses much earlier in the block validation.
|
||||
MERROR(fmt::format("Internal error: Invalid amounts passed in to save payments for address {}: that address has no accrued rewards",
|
||||
payment.address));
|
||||
return false;
|
||||
}
|
||||
|
||||
select_sum->reset();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<cryptonote::batch_sn_payment> BlockchainSQLite::get_block_payments(uint64_t block_height) {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__ << " Called with height: " << block_height);
|
||||
|
||||
std::vector<cryptonote::batch_sn_payment> payments_at_height;
|
||||
auto paid = prepared_results<std::string, int64_t>(
|
||||
"SELECT address, amount FROM batched_payments_paid WHERE height_paid = ? ORDER BY address",
|
||||
static_cast<int64_t>(block_height));
|
||||
|
||||
for (auto [addr, amt] : paid)
|
||||
payments_at_height.emplace_back(std::move(addr), static_cast<uint64_t>(amt), m_nettype);
|
||||
|
||||
return payments_at_height;
|
||||
}
|
||||
|
||||
bool BlockchainSQLite::delete_block_payments(uint64_t block_height) {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__ << " Called with height: " << block_height);
|
||||
prepared_exec(
|
||||
"DELETE FROM batched_payments_paid WHERE height_paid >= ?",
|
||||
static_cast<int64_t>(block_height));
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace cryptonote
|
|
@ -0,0 +1,122 @@
|
|||
// Copyright (c) 2021, The Oxen 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
#include "epee/misc_log_ex.h"
|
||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||
#include "cryptonote_core/cryptonote_tx_utils.h"
|
||||
#include "sqlitedb/database.hpp"
|
||||
#include "common/fs.h"
|
||||
|
||||
#include <SQLiteCpp/SQLiteCpp.h>
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
|
||||
fs::path check_if_copy_filename(std::string_view db_path);
|
||||
|
||||
class BlockchainSQLite : public db::Database
|
||||
{
|
||||
public:
|
||||
explicit BlockchainSQLite(cryptonote::network_type nettype, fs::path db_path);
|
||||
BlockchainSQLite(const BlockchainSQLite&) = delete;
|
||||
|
||||
// Database management functions. Should be called on creation of BlockchainSQLite
|
||||
void create_schema();
|
||||
void reset_database();
|
||||
|
||||
// The batching database maintains a height variable to know if it gets out of sync with the mainchain. Calling increment and decrement is the primary method of interacting with this height variable
|
||||
void update_height(uint64_t new_height);
|
||||
void increment_height();
|
||||
void decrement_height();
|
||||
|
||||
|
||||
// add_sn_payments/subtract_sn_payments -> passing an array of addresses and amounts. These will be added or subtracted to the database for each address specified. If the address does not exist it will be created.
|
||||
bool add_sn_rewards(const std::vector<cryptonote::batch_sn_payment>& payments);
|
||||
bool subtract_sn_rewards(const std::vector<cryptonote::batch_sn_payment>& payments);
|
||||
|
||||
private:
|
||||
bool reward_handler(
|
||||
const cryptonote::block& block,
|
||||
const service_nodes::service_node_list::state_t& service_nodes_state,
|
||||
bool add);
|
||||
|
||||
public:
|
||||
|
||||
// get_accrued_earnings -> queries the database for the amount that has been accrued to `service_node_address` will return the atomic value in oxen that
|
||||
// the service node is owed.
|
||||
uint64_t get_accrued_earnings(const std::string& address);
|
||||
// get_all_accrued_earnings -> queries the database for all the amount that has been accrued to service nodes will return
|
||||
// 2 vectors corresponding to the addresses and the atomic value in oxen that the service nodes are owed.
|
||||
std::pair<std::vector<std::string>, std::vector<uint64_t>> get_all_accrued_earnings();
|
||||
|
||||
// get_payments -> passing a block height will return an array of payments that should be created in a coinbase transaction on that block given the current batching DB state.
|
||||
std::vector<cryptonote::batch_sn_payment> get_sn_payments(uint64_t block_height);
|
||||
|
||||
// calculate_rewards -> takes the list of contributors from sn_info with their SN contribution
|
||||
// amounts and will calculate how much of the block rewards should be the allocated to the
|
||||
// contributors. The function will return a list suitable for passing to add_sn_payments
|
||||
//
|
||||
// Note that distribution_amount here is typically passed as milli-atomic OXEN for extra
|
||||
// precision.
|
||||
std::vector<cryptonote::batch_sn_payment> calculate_rewards(hf hf_version, uint64_t distribution_amount, service_nodes::service_node_info sn_info);
|
||||
|
||||
// add/pop_block -> takes a block that contains new block rewards to be batched and added to the database
|
||||
// and/or batching payments that need to be subtracted from the database, in addition it takes a reference to
|
||||
// the service node state which it will use to calculate the individual payouts.
|
||||
// The function will then process this block add and subtracting to the batching DB appropriately.
|
||||
// This is the primary entry point for the blockchain to add to the batching database.
|
||||
// Each accepted block should call this passing in the SN list structure.
|
||||
bool add_block(const cryptonote::block& block, const service_nodes::service_node_list::state_t& service_nodes_state);
|
||||
bool pop_block(const cryptonote::block& block, const service_nodes::service_node_list::state_t& service_nodes_state);
|
||||
|
||||
// validate_batch_payment -> used to make sure that list of miner_tx_vouts is correct. Compares the miner_tx_vouts with a list previously extracted payments to make sure that the correct persons are being paid.
|
||||
bool validate_batch_payment(
|
||||
const std::vector<std::tuple<crypto::public_key, uint64_t>>& miner_tx_vouts,
|
||||
const std::vector<cryptonote::batch_sn_payment>& calculated_payments_from_batching_db,
|
||||
uint64_t block_height);
|
||||
|
||||
// these keep track of payments made to SN operators after then payment has been made. Allows for popping blocks back and knowing who got paid in those blocks.
|
||||
// passing in a list of people to be marked as paid in the paid_amounts vector. Block height will be added to the batched_payments_paid database as height_paid.
|
||||
bool save_payments(uint64_t block_height, const std::vector<batch_sn_payment>& paid_amounts);
|
||||
std::vector<cryptonote::batch_sn_payment> get_block_payments(uint64_t block_height);
|
||||
bool delete_block_payments(uint64_t block_height);
|
||||
|
||||
uint64_t height;
|
||||
|
||||
protected:
|
||||
|
||||
cryptonote::network_type m_nettype;
|
||||
std::string filename;
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -43,7 +43,7 @@ namespace cryptonote
|
|||
class BaseTestDB: public cryptonote::BlockchainDB {
|
||||
public:
|
||||
BaseTestDB() {}
|
||||
virtual void open(const fs::path& filename, network_type nettype = FAKECHAIN, const int db_flags = 0) override { }
|
||||
virtual void open(const fs::path& filename, network_type nettype = network_type::FAKECHAIN, const int db_flags = 0) override { }
|
||||
virtual void close() override {}
|
||||
virtual void sync() override {}
|
||||
virtual void safesyncmode(const bool onoff) override {}
|
||||
|
@ -66,13 +66,13 @@ public:
|
|||
virtual void block_rtxn_abort() const override {}
|
||||
|
||||
virtual bool block_exists(const crypto::hash& h, uint64_t *height) const override { return false; }
|
||||
virtual cryptonote::blobdata get_block_blob_from_height(uint64_t height) const override { return cryptonote::t_serializable_object_to_blob(get_block_from_height(height)); }
|
||||
virtual cryptonote::blobdata get_block_blob(const crypto::hash& h) const override { return cryptonote::blobdata(); }
|
||||
virtual std::string get_block_blob_from_height(uint64_t height) const override { return cryptonote::t_serializable_object_to_blob(get_block_from_height(height)); }
|
||||
virtual std::string get_block_blob(const crypto::hash& h) const override { return std::string(); }
|
||||
virtual cryptonote::block_header get_block_header_from_height(uint64_t height) const override { return get_block_from_height(height); }
|
||||
virtual bool get_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override { return false; }
|
||||
virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override { return false; }
|
||||
virtual bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const override { return false; }
|
||||
virtual bool get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override { return false; }
|
||||
virtual bool get_tx_blob(const crypto::hash& h, std::string &tx) const override { return false; }
|
||||
virtual bool get_pruned_tx_blob(const crypto::hash& h, std::string &tx) const override { return false; }
|
||||
virtual bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<std::string> &bd) const override { return false; }
|
||||
virtual bool get_prunable_tx_blob(const crypto::hash& h, std::string &tx) const override { return false; }
|
||||
virtual bool get_prunable_tx_hash(const crypto::hash& tx_hash, crypto::hash &prunable_hash) const override { return false; }
|
||||
virtual uint64_t get_block_height(const crypto::hash& h) const override { return 0; }
|
||||
virtual uint64_t get_block_timestamp(const uint64_t& height) const override { return 0; }
|
||||
|
@ -110,7 +110,7 @@ public:
|
|||
virtual std::vector<std::vector<uint64_t>> get_tx_amount_output_indices(const uint64_t tx_index, size_t n_txes) const override { return std::vector<std::vector<uint64_t>>(); }
|
||||
virtual bool has_key_image(const crypto::key_image& img) const override { return false; }
|
||||
virtual void remove_block() override { }
|
||||
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<cryptonote::transaction, cryptonote::blobdata>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) override {return 0;}
|
||||
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<cryptonote::transaction, std::string>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) override {return 0;}
|
||||
virtual void remove_transaction_data(const crypto::hash& tx_hash, const cryptonote::transaction& tx) override {}
|
||||
virtual uint64_t add_output(const crypto::hash& tx_hash, const cryptonote::tx_out& tx_output, const uint64_t& local_index, const uint64_t unlock_time, const rct::key *commitment) override {return 0;}
|
||||
virtual void add_tx_amount_output_indices(const uint64_t tx_index, const std::vector<uint64_t>& amount_output_indices) override {}
|
||||
|
@ -126,16 +126,16 @@ public:
|
|||
virtual std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count) const override { return std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>>(); }
|
||||
virtual bool get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, std::vector<uint64_t> &distribution, uint64_t &base) const override { return false; }
|
||||
|
||||
virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const cryptonote::txpool_tx_meta_t& details) override {}
|
||||
virtual void add_txpool_tx(const crypto::hash &txid, const std::string &blob, const cryptonote::txpool_tx_meta_t& details) override {}
|
||||
virtual void update_txpool_tx(const crypto::hash &txid, const cryptonote::txpool_tx_meta_t& details) override {}
|
||||
virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const override { return 0; }
|
||||
virtual bool txpool_has_tx(const crypto::hash &txid) const override { return false; }
|
||||
virtual void remove_txpool_tx(const crypto::hash& txid) override {}
|
||||
virtual bool get_txpool_tx_meta(const crypto::hash& txid, cryptonote::txpool_tx_meta_t &meta) const override { return false; }
|
||||
virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const override { return false; }
|
||||
virtual bool get_txpool_tx_blob(const crypto::hash& txid, std::string &bd) const override { return false; }
|
||||
virtual uint64_t get_database_size() const override { return 0; }
|
||||
virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const override { return ""; }
|
||||
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const cryptonote::txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, bool include_unrelayed_txes = false) const override { return false; }
|
||||
virtual std::string get_txpool_tx_blob(const crypto::hash& txid) const override { return ""; }
|
||||
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const cryptonote::txpool_tx_meta_t&, const std::string*)>, bool include_blob = false, bool include_unrelayed_txes = false) const override { return false; }
|
||||
|
||||
virtual void add_block( const cryptonote::block& blk
|
||||
, size_t block_weight
|
||||
|
@ -173,12 +173,12 @@ public:
|
|||
void set_service_node_proof(const crypto::public_key &pubkey, const service_nodes::proof_info &proof) override { }
|
||||
bool remove_service_node_proof(const crypto::public_key &pubkey) override { return false; }
|
||||
|
||||
virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata &blob, const cryptonote::blobdata *checkpoint) override {}
|
||||
virtual bool get_alt_block(const crypto::hash &blkid, alt_block_data_t *data, cryptonote::blobdata *blob, cryptonote::blobdata *checkpoint) const override { return false; }
|
||||
virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const std::string &blob, const std::string *checkpoint) override {}
|
||||
virtual bool get_alt_block(const crypto::hash &blkid, alt_block_data_t *data, std::string *blob, std::string *checkpoint) const override { return false; }
|
||||
virtual void remove_alt_block(const crypto::hash &blkid) override {}
|
||||
virtual uint64_t get_alt_block_count() override { return 0; }
|
||||
virtual void drop_alt_blocks() override {}
|
||||
virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata *block_blob, const cryptonote::blobdata *checkpoint_blob)> f, bool include_blob = false) const override { return true; }
|
||||
virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const std::string *block_blob, const std::string *checkpoint_blob)> f, bool include_blob = false) const override { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ target_link_libraries(blockchain_tools_common_libs INTERFACE
|
|||
version
|
||||
filesystem
|
||||
Boost::program_options
|
||||
SQLiteCpp
|
||||
extra)
|
||||
|
||||
|
||||
|
|
|
@ -231,7 +231,7 @@ static bool get_block_from_height(ancestry_state_t &state, BlockchainDB *db, uin
|
|||
b = state.block_cache[height];
|
||||
return true;
|
||||
}
|
||||
cryptonote::blobdata bd = db->get_block_blob_from_height(height);
|
||||
std::string bd = db->get_block_blob_from_height(height);
|
||||
if (!cryptonote::parse_and_validate_block_from_blob(bd, b))
|
||||
{
|
||||
LOG_PRINT_L0("Bad block from db");
|
||||
|
@ -256,7 +256,7 @@ static bool get_transaction(ancestry_state_t &state, BlockchainDB *db, const cry
|
|||
return true;
|
||||
}
|
||||
|
||||
cryptonote::blobdata bd;
|
||||
std::string bd;
|
||||
if (!db->get_pruned_tx_blob(txid, bd))
|
||||
{
|
||||
LOG_PRINT_L0("Failed to get txid " << txid << " from db");
|
||||
|
@ -400,7 +400,7 @@ int main(int argc, char* argv[])
|
|||
std::string opt_data_dir = command_line::get_arg(vm, cryptonote::arg_data_dir);
|
||||
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
|
||||
bool opt_devnet = command_line::get_arg(vm, cryptonote::arg_devnet_on);
|
||||
network_type net_type = opt_testnet ? TESTNET : opt_devnet ? DEVNET : MAINNET;
|
||||
network_type net_type = opt_testnet ? network_type::TESTNET : opt_devnet ? network_type::DEVNET : network_type::MAINNET;
|
||||
std::string opt_txid_string = command_line::get_arg(vm, arg_txid);
|
||||
std::string opt_output_string = command_line::get_arg(vm, arg_output);
|
||||
uint64_t opt_height = command_line::get_arg(vm, arg_height);
|
||||
|
@ -458,7 +458,7 @@ int main(int argc, char* argv[])
|
|||
LOG_PRINT_L0("Error opening database: " << e.what());
|
||||
return 1;
|
||||
}
|
||||
r = core_storage->init(db, nullptr /*ons_db*/, net_type);
|
||||
r = core_storage->init(db, nullptr /*ons_db*/, nullptr, net_type);
|
||||
|
||||
CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage");
|
||||
LOG_PRINT_L0("Source blockchain storage initialized OK");
|
||||
|
@ -499,7 +499,7 @@ int main(int argc, char* argv[])
|
|||
for (uint64_t h = state.height; h < db_height; ++h)
|
||||
{
|
||||
size_t block_ancestry_size = 0;
|
||||
const cryptonote::blobdata bd = db->get_block_blob_from_height(h);
|
||||
const std::string bd = db->get_block_blob_from_height(h);
|
||||
++total_blocks;
|
||||
cryptonote::block b;
|
||||
if (!cryptonote::parse_and_validate_block_from_blob(bd, b))
|
||||
|
@ -532,7 +532,7 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
else
|
||||
{
|
||||
cryptonote::blobdata bd;
|
||||
std::string bd;
|
||||
if (!db->get_pruned_tx_blob(txid, bd))
|
||||
{
|
||||
LOG_PRINT_L0("Failed to get txid " << txid << " from db");
|
||||
|
@ -629,7 +629,7 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
else
|
||||
{
|
||||
const cryptonote::blobdata bd = db->get_block_blob_from_height(opt_height);
|
||||
const std::string bd = db->get_block_blob_from_height(opt_height);
|
||||
cryptonote::block b;
|
||||
if (!cryptonote::parse_and_validate_block_from_blob(bd, b))
|
||||
{
|
||||
|
|
|
@ -471,7 +471,7 @@ static bool for_all_transactions(const fs::path& filename, const uint64_t& start
|
|||
if (k.mv_size != sizeof(uint64_t))
|
||||
throw std::runtime_error("Bad key size");
|
||||
uint64_t height = *(const uint64_t*)k.mv_data;
|
||||
blobdata bd;
|
||||
std::string bd;
|
||||
bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
|
||||
block b;
|
||||
if (!parse_and_validate_block_from_blob(bd, b))
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "common/command_line.h"
|
||||
#include "common/varint.h"
|
||||
#include "common/median.h"
|
||||
#include "cryptonote_core/cryptonote_core.h"
|
||||
#include "blockchain_objects.h"
|
||||
#include "blockchain_db/blockchain_db.h"
|
||||
|
@ -99,7 +100,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
|
||||
bool opt_devnet = command_line::get_arg(vm, cryptonote::arg_devnet_on);
|
||||
network_type net_type = opt_testnet ? TESTNET : opt_devnet ? DEVNET : MAINNET;
|
||||
network_type net_type = opt_testnet ? network_type::TESTNET : opt_devnet ? network_type::DEVNET : network_type::MAINNET;
|
||||
std::string opt_txid_string = command_line::get_arg(vm, arg_txid);
|
||||
uint64_t opt_height = command_line::get_arg(vm, arg_height);
|
||||
bool opt_include_coinbase = command_line::get_arg(vm, arg_include_coinbase);
|
||||
|
@ -142,7 +143,7 @@ int main(int argc, char* argv[])
|
|||
LOG_PRINT_L0("Error opening database: " << e.what());
|
||||
return 1;
|
||||
}
|
||||
r = core_storage->init(db, nullptr /*ons_db*/, net_type);
|
||||
r = core_storage->init(db, nullptr /*ons_db*/, nullptr, net_type);
|
||||
|
||||
CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage");
|
||||
LOG_PRINT_L0("Source blockchain storage initialized OK");
|
||||
|
@ -154,7 +155,7 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
else
|
||||
{
|
||||
const cryptonote::blobdata bd = db->get_block_blob_from_height(opt_height);
|
||||
const std::string bd = db->get_block_blob_from_height(opt_height);
|
||||
cryptonote::block b;
|
||||
if (!cryptonote::parse_and_validate_block_from_blob(bd, b))
|
||||
{
|
||||
|
@ -187,7 +188,7 @@ int main(int argc, char* argv[])
|
|||
std::vector<crypto::hash> new_txids;
|
||||
for (const crypto::hash &txid: txids)
|
||||
{
|
||||
cryptonote::blobdata bd;
|
||||
std::string bd;
|
||||
if (!db->get_pruned_tx_blob(txid, bd))
|
||||
{
|
||||
LOG_PRINT_L0("Failed to get txid " << txid << " from db");
|
||||
|
@ -305,7 +306,7 @@ done:
|
|||
for (uint64_t depth: depths)
|
||||
cumulative_depth += depth;
|
||||
LOG_PRINT_L0("Average min depth for " << start_txids.size() << " transaction(s): " << cumulative_depth/(float)depths.size());
|
||||
LOG_PRINT_L0("Median min depth for " << start_txids.size() << " transaction(s): " << epee::misc_utils::median(depths));
|
||||
LOG_PRINT_L0("Median min depth for " << start_txids.size() << " transaction(s): " << tools::median(std::move(depths)));
|
||||
|
||||
core_storage->deinit();
|
||||
return 0;
|
||||
|
|
|
@ -142,7 +142,7 @@ int main(int argc, char* argv[])
|
|||
LOG_PRINT_L0("Error opening database: " << e.what());
|
||||
return 1;
|
||||
}
|
||||
r = core_storage->init(db, nullptr, opt_testnet ? cryptonote::TESTNET : opt_devnet ? cryptonote::DEVNET : cryptonote::MAINNET);
|
||||
r = core_storage->init(db, nullptr, nullptr, opt_testnet ? cryptonote::network_type::TESTNET : opt_devnet ? cryptonote::network_type::DEVNET : cryptonote::network_type::MAINNET);
|
||||
|
||||
if (core_storage->get_blockchain_pruning_seed() && !opt_blocks_dat)
|
||||
{
|
||||
|
|
|
@ -404,12 +404,12 @@ int import_from_file(cryptonote::core& core, const fs::path& import_file_path, u
|
|||
|
||||
if (opt_verify)
|
||||
{
|
||||
cryptonote::blobdata block;
|
||||
std::string block;
|
||||
cryptonote::block_to_blob(bp.block, block);
|
||||
std::vector<cryptonote::blobdata> txs;
|
||||
std::vector<std::string> txs;
|
||||
for (const auto &tx: bp.txs)
|
||||
{
|
||||
txs.push_back(cryptonote::blobdata());
|
||||
txs.push_back(std::string());
|
||||
cryptonote::tx_to_blob(tx, txs.back());
|
||||
}
|
||||
blocks.push_back({block, txs});
|
||||
|
@ -422,7 +422,7 @@ int import_from_file(cryptonote::core& core, const fs::path& import_file_path, u
|
|||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::pair<transaction, blobdata>> txs;
|
||||
std::vector<std::pair<transaction, std::string>> txs;
|
||||
std::vector<transaction> archived_txs;
|
||||
|
||||
archived_txs = bp.txs;
|
||||
|
|
|
@ -304,7 +304,7 @@ static void prune(MDB_env *env0, MDB_env *env1)
|
|||
if (dbr) throw std::runtime_error("Failed to open LMDB dbi: " + std::string(mdb_strerror(dbr)));
|
||||
|
||||
MDB_val k, v;
|
||||
uint32_t pruning_seed = tools::make_pruning_seed(tools::get_random_stripe(), CRYPTONOTE_PRUNING_LOG_STRIPES);
|
||||
uint32_t pruning_seed = tools::make_pruning_seed(tools::get_random_stripe(), PRUNING_LOG_STRIPES);
|
||||
static char pruning_seed_key[] = "pruning_seed";
|
||||
k.mv_data = pruning_seed_key;
|
||||
k.mv_size = strlen("pruning_seed") + 1;
|
||||
|
@ -334,7 +334,7 @@ static void prune(MDB_env *env0, MDB_env *env1)
|
|||
const txindex *ti = (const txindex*)v.mv_data;
|
||||
const uint64_t block_height = ti->data.block_id;
|
||||
MDB_val_set(kk, ti->data.tx_id);
|
||||
if (block_height + CRYPTONOTE_PRUNING_TIP_BLOCKS >= blockchain_height)
|
||||
if (block_height + PRUNING_TIP_BLOCKS >= blockchain_height)
|
||||
{
|
||||
MDEBUG(block_height << "/" << blockchain_height << " is in tip");
|
||||
MDB_val_set(vv, block_height);
|
||||
|
@ -494,7 +494,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
|
||||
bool opt_devnet = command_line::get_arg(vm, cryptonote::arg_devnet_on);
|
||||
network_type net_type = opt_testnet ? TESTNET : opt_devnet ? DEVNET : MAINNET;
|
||||
network_type net_type = opt_testnet ? network_type::TESTNET : opt_devnet ? network_type::DEVNET : network_type::MAINNET;
|
||||
bool opt_copy_pruned_database = command_line::get_arg(vm, arg_copy_pruned_database);
|
||||
std::string data_dir = command_line::get_arg(vm, cryptonote::arg_data_dir);
|
||||
while (tools::ends_with(data_dir, "/") || tools::ends_with(data_dir, "\\"))
|
||||
|
|
|
@ -160,7 +160,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
|
||||
bool opt_devnet = command_line::get_arg(vm, cryptonote::arg_devnet_on);
|
||||
network_type net_type = opt_testnet ? TESTNET : opt_devnet ? DEVNET : MAINNET;
|
||||
network_type net_type = opt_testnet ? network_type::TESTNET : opt_devnet ? network_type::DEVNET : network_type::MAINNET;
|
||||
bool opt_verbose = command_line::get_arg(vm, arg_verbose);
|
||||
bool opt_dry_run = command_line::get_arg(vm, arg_dry_run);
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ int main(int argc, char* argv[])
|
|||
std::string opt_data_dir = command_line::get_arg(vm, cryptonote::arg_data_dir);
|
||||
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
|
||||
bool opt_devnet = command_line::get_arg(vm, cryptonote::arg_devnet_on);
|
||||
network_type net_type = opt_testnet ? TESTNET : opt_devnet ? DEVNET : MAINNET;
|
||||
network_type net_type = opt_testnet ? network_type::TESTNET : opt_devnet ? network_type::DEVNET : network_type::MAINNET;
|
||||
block_start = command_line::get_arg(vm, arg_block_start);
|
||||
block_stop = command_line::get_arg(vm, arg_block_stop);
|
||||
bool do_inputs = command_line::get_arg(vm, arg_inputs);
|
||||
|
@ -145,7 +145,7 @@ int main(int argc, char* argv[])
|
|||
LOG_PRINT_L0("Error opening database: " << e.what());
|
||||
return 1;
|
||||
}
|
||||
r = core_storage->init(db, nullptr /*ons_db*/, net_type);
|
||||
r = core_storage->init(db, nullptr /*ons_db*/, nullptr, net_type);
|
||||
|
||||
CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage");
|
||||
LOG_PRINT_L0("Source blockchain storage initialized OK");
|
||||
|
@ -208,7 +208,7 @@ plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, ''
|
|||
|
||||
for (uint64_t h = block_start; h < block_stop; ++h)
|
||||
{
|
||||
cryptonote::blobdata bd = db->get_block_blob_from_height(h);
|
||||
std::string bd = db->get_block_blob_from_height(h);
|
||||
cryptonote::block blk;
|
||||
if (!cryptonote::parse_and_validate_block_from_blob(bd, blk))
|
||||
{
|
||||
|
|
|
@ -132,7 +132,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
|
||||
bool opt_devnet = command_line::get_arg(vm, cryptonote::arg_devnet_on);
|
||||
network_type net_type = opt_testnet ? TESTNET : opt_devnet ? DEVNET : MAINNET;
|
||||
network_type net_type = opt_testnet ? network_type::TESTNET : opt_devnet ? network_type::DEVNET : network_type::MAINNET;
|
||||
bool opt_rct_only = command_line::get_arg(vm, arg_rct_only);
|
||||
|
||||
// If we wanted to use the memory pool, we would set up a fake_core.
|
||||
|
@ -172,7 +172,7 @@ int main(int argc, char* argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
r = core_storage->init(db, nullptr /*ons_db*/, net_type);
|
||||
r = core_storage->init(db, nullptr /*ons_db*/, nullptr, net_type);
|
||||
|
||||
CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage");
|
||||
LOG_PRINT_L0("Source blockchain storage initialized OK");
|
||||
|
|
|
@ -138,7 +138,7 @@ bool BootstrapFile::initialize_file()
|
|||
|
||||
uint32_t bd_size = 0;
|
||||
|
||||
blobdata bd = t_serializable_object_to_blob(bfi);
|
||||
std::string bd = t_serializable_object_to_blob(bfi);
|
||||
MDEBUG("bootstrap::file_info size: " << bd.size());
|
||||
bd_size = bd.size();
|
||||
|
||||
|
@ -248,7 +248,7 @@ void BootstrapFile::write_block(block& block)
|
|||
bp.coins_generated = coins_generated;
|
||||
}
|
||||
|
||||
blobdata bd = t_serializable_object_to_blob(bp);
|
||||
std::string bd = t_serializable_object_to_blob(bp);
|
||||
m_output_stream->write((const char*)bd.data(), bd.size());
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ extern "C" {
|
|||
}
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <oxenmq/hex.h>
|
||||
#include <oxenmq/base32z.h>
|
||||
#include <oxenc/hex.h>
|
||||
#include <oxenc/base32z.h>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
@ -137,7 +137,7 @@ int generate(bool ed25519, std::list<std::string_view> args) {
|
|||
return error(11, "Internal error: pubkey check failed");
|
||||
|
||||
if (pubkey_pos != std::string::npos)
|
||||
filename.replace(pubkey_pos, 6, oxenmq::to_hex(pubkey.begin(), pubkey.end()));
|
||||
filename.replace(pubkey_pos, 6, oxenc::to_hex(pubkey.begin(), pubkey.end()));
|
||||
fs::ofstream out{fs::u8path(filename), std::ios::trunc | std::ios::binary};
|
||||
if (!out.good())
|
||||
return error(2, "Failed to open output file '" + filename + "': " + std::strerror(errno));
|
||||
|
@ -156,11 +156,11 @@ int generate(bool ed25519, std::list<std::string_view> args) {
|
|||
if (0 != crypto_sign_ed25519_pk_to_curve25519(x_pubkey.data(), pubkey.data()))
|
||||
return error(14, "Internal error: unable to convert Ed25519 pubkey to X25519 pubkey");
|
||||
std::cout <<
|
||||
"Public key: " << oxenmq::to_hex(pubkey.begin(), pubkey.end()) <<
|
||||
"\nX25519 pubkey: " << oxenmq::to_hex(x_pubkey.begin(), x_pubkey.end()) <<
|
||||
"\nLokinet address: " << oxenmq::to_base32z(pubkey.begin(), pubkey.end()) << ".snode\n";
|
||||
"Public key: " << oxenc::to_hex(pubkey.begin(), pubkey.end()) <<
|
||||
"\nX25519 pubkey: " << oxenc::to_hex(x_pubkey.begin(), x_pubkey.end()) <<
|
||||
"\nLokinet address: " << oxenc::to_base32z(pubkey.begin(), pubkey.end()) << ".snode\n";
|
||||
} else {
|
||||
std::cout << "Public key: " << oxenmq::to_hex(pubkey.begin(), pubkey.end()) << "\n";
|
||||
std::cout << "Public key: " << oxenc::to_hex(pubkey.begin(), pubkey.end()) << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -220,8 +220,8 @@ int show(std::list<std::string_view> args) {
|
|||
pubkey = pubkey_from_privkey(seckey);
|
||||
|
||||
std::cout << filename.u8string() << " (legacy SN keypair)" << "\n==========" <<
|
||||
"\nPrivate key: " << oxenmq::to_hex(seckey.begin(), seckey.begin() + 32) <<
|
||||
"\nPublic key: " << oxenmq::to_hex(pubkey.begin(), pubkey.end()) << "\n\n";
|
||||
"\nPrivate key: " << oxenc::to_hex(seckey.begin(), seckey.begin() + 32) <<
|
||||
"\nPublic key: " << oxenc::to_hex(pubkey.begin(), pubkey.end()) << "\n\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -234,16 +234,16 @@ int show(std::list<std::string_view> args) {
|
|||
ustring_view privkey{privkey_signhash.data(), 32};
|
||||
pubkey = pubkey_from_privkey(privkey);
|
||||
if (size >= 64 && ustring_view{pubkey.data(), pubkey.size()} != ustring_view{seckey.data() + 32, 32})
|
||||
return error(13, "Error: derived pubkey (" + oxenmq::to_hex(pubkey.begin(), pubkey.end()) + ")"
|
||||
" != embedded pubkey (" + oxenmq::to_hex(seckey.begin() + 32, seckey.end()) + ")");
|
||||
return error(13, "Error: derived pubkey (" + oxenc::to_hex(pubkey.begin(), pubkey.end()) + ")"
|
||||
" != embedded pubkey (" + oxenc::to_hex(seckey.begin() + 32, seckey.end()) + ")");
|
||||
if (0 != crypto_sign_ed25519_pk_to_curve25519(x_pubkey.data(), pubkey.data()))
|
||||
return error(14, "Unable to convert Ed25519 pubkey to X25519 pubkey; is this a really valid secret key?");
|
||||
|
||||
std::cout << filename << " (Ed25519 SN keypair)" << "\n==========" <<
|
||||
"\nSecret key: " << oxenmq::to_hex(seckey.begin(), seckey.begin() + 32) <<
|
||||
"\nPublic key: " << oxenmq::to_hex(pubkey.begin(), pubkey.end()) <<
|
||||
"\nX25519 pubkey: " << oxenmq::to_hex(x_pubkey.begin(), x_pubkey.end()) <<
|
||||
"\nLokinet address: " << oxenmq::to_base32z(pubkey.begin(), pubkey.end()) << ".snode\n\n";
|
||||
"\nSecret key: " << oxenc::to_hex(seckey.begin(), seckey.begin() + 32) <<
|
||||
"\nPublic key: " << oxenc::to_hex(pubkey.begin(), pubkey.end()) <<
|
||||
"\nX25519 pubkey: " << oxenc::to_hex(x_pubkey.begin(), x_pubkey.end()) <<
|
||||
"\nLokinet address: " << oxenc::to_base32z(pubkey.begin(), pubkey.end()) << ".snode\n\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -278,15 +278,15 @@ int restore(bool ed25519, std::list<std::string_view> args) {
|
|||
|
||||
// Advanced feature: if you provide the concatenated privkey and pubkey in hex, we won't prompt
|
||||
// for verification (as long as the pubkey matches what we derive from the privkey).
|
||||
if (!(skey_hex.size() == 64 || skey_hex.size() == 128) || !oxenmq::is_hex(skey_hex))
|
||||
if (!(skey_hex.size() == 64 || skey_hex.size() == 128) || !oxenc::is_hex(skey_hex))
|
||||
return error(7, "Invalid input: provide the secret key as 64 hex characters");
|
||||
std::array<unsigned char, crypto_sign_SECRETKEYBYTES> skey;
|
||||
std::array<unsigned char, crypto_sign_PUBLICKEYBYTES> pubkey;
|
||||
std::array<unsigned char, crypto_sign_SEEDBYTES> seed;
|
||||
std::optional<std::array<unsigned char, crypto_sign_PUBLICKEYBYTES>> pubkey_expected;
|
||||
oxenmq::from_hex(skey_hex.begin(), skey_hex.begin() + 64, seed.begin());
|
||||
oxenc::from_hex(skey_hex.begin(), skey_hex.begin() + 64, seed.begin());
|
||||
if (skey_hex.size() == 128)
|
||||
oxenmq::from_hex(skey_hex.begin() + 64, skey_hex.end(), pubkey_expected.emplace().begin());
|
||||
oxenc::from_hex(skey_hex.begin() + 64, skey_hex.end(), pubkey_expected.emplace().begin());
|
||||
|
||||
if (ed25519) {
|
||||
crypto_sign_seed_keypair(pubkey.data(), skey.data(), seed.data());
|
||||
|
@ -294,19 +294,19 @@ int restore(bool ed25519, std::list<std::string_view> args) {
|
|||
pubkey = pubkey_from_privkey(seed);
|
||||
}
|
||||
|
||||
std::cout << "\nPublic key: " << oxenmq::to_hex(pubkey.begin(), pubkey.end()) << "\n";
|
||||
std::cout << "\nPublic key: " << oxenc::to_hex(pubkey.begin(), pubkey.end()) << "\n";
|
||||
if (ed25519) {
|
||||
std::array<unsigned char, crypto_scalarmult_curve25519_BYTES> x_pubkey;
|
||||
if (0 != crypto_sign_ed25519_pk_to_curve25519(x_pubkey.data(), pubkey.data()))
|
||||
return error(14, "Unable to convert Ed25519 pubkey to X25519 pubkey; is this a really valid secret key?");
|
||||
std::cout << "X25519 pubkey: " << oxenmq::to_hex(x_pubkey.begin(), x_pubkey.end()) <<
|
||||
"\nLokinet address: " << oxenmq::to_base32z(pubkey.begin(), pubkey.end()) << ".snode";
|
||||
std::cout << "X25519 pubkey: " << oxenc::to_hex(x_pubkey.begin(), x_pubkey.end()) <<
|
||||
"\nLokinet address: " << oxenc::to_base32z(pubkey.begin(), pubkey.end()) << ".snode";
|
||||
}
|
||||
|
||||
if (pubkey_expected) {
|
||||
if (*pubkey_expected != pubkey)
|
||||
return error(2, "Derived pubkey (" + oxenmq::to_hex(pubkey.begin(), pubkey.end()) + ") doesn't match "
|
||||
"provided pubkey (" + oxenmq::to_hex(pubkey_expected->begin(), pubkey_expected->end()) + ")");
|
||||
return error(2, "Derived pubkey (" + oxenc::to_hex(pubkey.begin(), pubkey.end()) + ") doesn't match "
|
||||
"provided pubkey (" + oxenc::to_hex(pubkey_expected->begin(), pubkey_expected->end()) + ")");
|
||||
} else {
|
||||
|
||||
if (ed25519 && filename.size() >= 4 && filename.substr(filename.size() - 4) == "/key") {
|
||||
|
@ -324,7 +324,7 @@ int restore(bool ed25519, std::list<std::string_view> args) {
|
|||
}
|
||||
|
||||
if (pubkey_pos != std::string::npos)
|
||||
filename.replace(pubkey_pos, 6, oxenmq::to_hex(pubkey.begin(), pubkey.end()));
|
||||
filename.replace(pubkey_pos, 6, oxenc::to_hex(pubkey.begin(), pubkey.end()));
|
||||
|
||||
auto filepath = fs::u8path(filename);
|
||||
if (!overwrite && fs::exists(filepath))
|
||||
|
|
|
@ -75,10 +75,10 @@ namespace cryptonote
|
|||
{
|
||||
crypto::hash result = crypto::null_hash;
|
||||
*height = 0;
|
||||
if (nettype != MAINNET && nettype != TESTNET)
|
||||
if (nettype != network_type::MAINNET && nettype != network_type::TESTNET)
|
||||
return result;
|
||||
|
||||
if (nettype == MAINNET)
|
||||
if (nettype == network_type::MAINNET)
|
||||
{
|
||||
uint64_t last_index = oxen::array_count(HARDCODED_MAINNET_CHECKPOINTS) - 1;
|
||||
height_to_hash const &entry = HARDCODED_MAINNET_CHECKPOINTS[last_index];
|
||||
|
@ -170,7 +170,7 @@ namespace cryptonote
|
|||
bool checkpoints::block_added(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs, checkpoint_t const *checkpoint)
|
||||
{
|
||||
uint64_t const height = get_block_height(block);
|
||||
if (height < service_nodes::CHECKPOINT_STORE_PERSISTENTLY_INTERVAL || block.major_version < network_version_12_checkpointing)
|
||||
if (height < service_nodes::CHECKPOINT_STORE_PERSISTENTLY_INTERVAL || block.major_version < hf::hf12_checkpointing)
|
||||
return true;
|
||||
|
||||
uint64_t end_cull_height = 0;
|
||||
|
@ -308,12 +308,13 @@ namespace cryptonote
|
|||
if (db->is_read_only())
|
||||
return true;
|
||||
|
||||
if (nettype == MAINNET)
|
||||
if (nettype == network_type::MAINNET)
|
||||
{
|
||||
for (size_t i = 0; i < oxen::array_count(HARDCODED_MAINNET_CHECKPOINTS); ++i)
|
||||
{
|
||||
height_to_hash const &checkpoint = HARDCODED_MAINNET_CHECKPOINTS[i];
|
||||
ADD_CHECKPOINT(checkpoint.height, checkpoint.hash);
|
||||
bool added = add_checkpoint(checkpoint.height, checkpoint.hash);
|
||||
CHECK_AND_ASSERT(added, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,11 +38,11 @@
|
|||
#include "cryptonote_basic/cryptonote_basic_impl.h"
|
||||
#include "common/fs.h"
|
||||
|
||||
#define ADD_CHECKPOINT(h, hash) CHECK_AND_ASSERT(add_checkpoint(h, hash), false);
|
||||
#define JSON_HASH_FILE_NAME "checkpoints.json"
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
constexpr std::string_view JSON_HASH_FILE_NAME = "checkpoints.json"sv;
|
||||
|
||||
enum struct checkpoint_type
|
||||
{
|
||||
hardcoded,
|
||||
|
@ -197,7 +197,7 @@ namespace cryptonote
|
|||
bool init(network_type nettype, class BlockchainDB *db);
|
||||
|
||||
private:
|
||||
network_type m_nettype = UNDEFINED;
|
||||
network_type m_nettype = network_type::UNDEFINED;
|
||||
uint64_t m_last_cull_height = 0;
|
||||
uint64_t m_immutable_height = 0;
|
||||
BlockchainDB *m_db;
|
||||
|
|
|
@ -32,7 +32,6 @@ add_library(common
|
|||
base58.cpp
|
||||
combinator.cpp
|
||||
command_line.cpp
|
||||
dns_utils.cpp
|
||||
error.cpp
|
||||
expect.cpp
|
||||
file.cpp
|
||||
|
@ -70,7 +69,5 @@ target_link_libraries(common
|
|||
date::date
|
||||
fmt::fmt
|
||||
PRIVATE
|
||||
libunbound
|
||||
OpenSSL::SSL
|
||||
OpenSSL::Crypto
|
||||
sodium
|
||||
extra)
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
namespace tools
|
||||
{
|
||||
class DNSResolver;
|
||||
struct login;
|
||||
class password_container;
|
||||
class t_http_connection;
|
||||
|
|
|
@ -1,670 +0,0 @@
|
|||
// Copyright (c) 2014-2019, The Monero Project
|
||||
// Copyright (c) 2018, The Loki 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 "common/dns_utils.h"
|
||||
// check local first (in the event of static or in-source compilation of libunbound)
|
||||
#include "common/string_util.h"
|
||||
#include "unbound.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include "epee/misc_log_ex.h"
|
||||
#include "common/threadpool.h"
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
#undef OXEN_DEFAULT_LOG_CATEGORY
|
||||
#define OXEN_DEFAULT_LOG_CATEGORY "net.dns"
|
||||
|
||||
using namespace std::literals;
|
||||
static constexpr std::array DEFAULT_DNS_PUBLIC_ADDR =
|
||||
{
|
||||
"194.150.168.168"sv, // CCC (Germany)
|
||||
"80.67.169.40"sv, // FDN (France)
|
||||
"89.233.43.71"sv, // http://censurfridns.dk (Denmark)
|
||||
"109.69.8.51"sv, // punCAT (Spain)
|
||||
"193.58.251.251"sv, // SkyDNS (Russia)
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
/*
|
||||
* The following two functions were taken from unbound-anchor.c, from
|
||||
* the unbound library packaged with this source. The license and source
|
||||
* can be found in $PROJECT_ROOT/external/unbound
|
||||
*/
|
||||
|
||||
/* Cert builtin commented out until it's used, as the compiler complains
|
||||
|
||||
// return the built in root update certificate
|
||||
static const char*
|
||||
get_builtin_cert(void)
|
||||
{
|
||||
return
|
||||
// The ICANN CA fetched at 24 Sep 2010. Valid to 2028
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDdzCCAl+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQ4wDAYDVQQKEwVJQ0FO\n"
|
||||
"TjEmMCQGA1UECxMdSUNBTk4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNV\n"
|
||||
"BAMTDUlDQU5OIFJvb3QgQ0ExCzAJBgNVBAYTAlVTMB4XDTA5MTIyMzA0MTkxMloX\n"
|
||||
"DTI5MTIxODA0MTkxMlowXTEOMAwGA1UEChMFSUNBTk4xJjAkBgNVBAsTHUlDQU5O\n"
|
||||
"IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1JQ0FOTiBSb290IENB\n"
|
||||
"MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKDb\n"
|
||||
"cLhPNNqc1NB+u+oVvOnJESofYS9qub0/PXagmgr37pNublVThIzyLPGCJ8gPms9S\n"
|
||||
"G1TaKNIsMI7d+5IgMy3WyPEOECGIcfqEIktdR1YWfJufXcMReZwU4v/AdKzdOdfg\n"
|
||||
"ONiwc6r70duEr1IiqPbVm5T05l1e6D+HkAvHGnf1LtOPGs4CHQdpIUcy2kauAEy2\n"
|
||||
"paKcOcHASvbTHK7TbbvHGPB+7faAztABLoneErruEcumetcNfPMIjXKdv1V1E3C7\n"
|
||||
"MSJKy+jAqqQJqjZoQGB0necZgUMiUv7JK1IPQRM2CXJllcyJrm9WFxY0c1KjBO29\n"
|
||||
"iIKK69fcglKcBuFShUECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B\n"
|
||||
"Af8EBAMCAf4wHQYDVR0OBBYEFLpS6UmDJIZSL8eZzfyNa2kITcBQMA0GCSqGSIb3\n"
|
||||
"DQEBCwUAA4IBAQAP8emCogqHny2UYFqywEuhLys7R9UKmYY4suzGO4nkbgfPFMfH\n"
|
||||
"6M+Zj6owwxlwueZt1j/IaCayoKU3QsrYYoDRolpILh+FPwx7wseUEV8ZKpWsoDoD\n"
|
||||
"2JFbLg2cfB8u/OlE4RYmcxxFSmXBg0yQ8/IoQt/bxOcEEhhiQ168H2yE5rxJMt9h\n"
|
||||
"15nu5JBSewrCkYqYYmaxyOC3WrVGfHZxVI7MpIFcGdvSb2a1uyuua8l0BKgk3ujF\n"
|
||||
"0/wsHNeP22qNyVO+XVBzrM8fk8BSUFuiT/6tZTYXRtEt5aKQZgXbKU5dUF3jT9qg\n"
|
||||
"j/Br5BZw3X/zd325TvnswzMC1+ljLzHnQGGk\n"
|
||||
"-----END CERTIFICATE-----\n"
|
||||
;
|
||||
}
|
||||
*/
|
||||
|
||||
/** return the built in root DS trust anchor */
|
||||
constexpr auto get_builtin_ds()
|
||||
{
|
||||
return std::array{
|
||||
". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n",
|
||||
". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D\n",
|
||||
};
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
************************************************************
|
||||
***********************************************************/
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace tools
|
||||
{
|
||||
|
||||
static constexpr const char *get_record_name(int record_type)
|
||||
{
|
||||
switch (record_type)
|
||||
{
|
||||
case DNS_TYPE_A: return "A";
|
||||
case DNS_TYPE_TXT: return "TXT";
|
||||
case DNS_TYPE_AAAA: return "AAAA";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
// fuck it, I'm tired of dealing with getnameinfo()/inet_ntop/etc
|
||||
std::optional<std::string> ipv4_to_string(const char* src, size_t len)
|
||||
{
|
||||
if (len < 4)
|
||||
{
|
||||
MERROR("Invalid IPv4 address: " << std::string(src, len));
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
unsigned int bytes[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
unsigned char a = src[i];
|
||||
bytes[i] = a;
|
||||
}
|
||||
ss << bytes[0] << "."
|
||||
<< bytes[1] << "."
|
||||
<< bytes[2] << "."
|
||||
<< bytes[3];
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// this obviously will need to change, but is here to reflect the above
|
||||
// stop-gap measure and to make the tests pass at least...
|
||||
std::optional<std::string> ipv6_to_string(const char* src, size_t len)
|
||||
{
|
||||
if (len < 8)
|
||||
{
|
||||
MERROR("Invalid IPv4 address: " << std::string(src, len));
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
unsigned int bytes[8];
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
unsigned char a = src[i];
|
||||
bytes[i] = a;
|
||||
}
|
||||
ss << bytes[0] << ":"
|
||||
<< bytes[1] << ":"
|
||||
<< bytes[2] << ":"
|
||||
<< bytes[3] << ":"
|
||||
<< bytes[4] << ":"
|
||||
<< bytes[5] << ":"
|
||||
<< bytes[6] << ":"
|
||||
<< bytes[7];
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::optional<std::string> txt_to_string(const char* src, size_t len)
|
||||
{
|
||||
if (len == 0)
|
||||
return std::nullopt;
|
||||
return std::string(src+1, len-1);
|
||||
}
|
||||
|
||||
void ub_ctx_deleter::operator()(ub_ctx* ctx) {
|
||||
ub_ctx_delete(ctx);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct ub_result_deleter {
|
||||
void operator()(ub_result* result) {
|
||||
ub_resolve_free(result);
|
||||
}
|
||||
};
|
||||
|
||||
using ub_result_ptr = std::unique_ptr<ub_result, ub_result_deleter>;
|
||||
|
||||
void add_anchors(ub_ctx *ctx)
|
||||
{
|
||||
for (const char* ds : get_builtin_ds())
|
||||
{
|
||||
MINFO("adding trust anchor: " << *ds);
|
||||
ub_ctx_add_ta(ctx, const_cast<char*>(ds));
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
DNSResolver::DNSResolver()
|
||||
{
|
||||
int use_dns_public = 0;
|
||||
std::vector<std::string> dns_public_addr;
|
||||
const char *DNS_PUBLIC = getenv("DNS_PUBLIC");
|
||||
if (DNS_PUBLIC)
|
||||
{
|
||||
dns_public_addr = tools::dns_utils::parse_dns_public(DNS_PUBLIC);
|
||||
if (!dns_public_addr.empty())
|
||||
{
|
||||
MGINFO("Using public DNS server(s): " << tools::join(", ", dns_public_addr) << " (TCP)");
|
||||
use_dns_public = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
MERROR("Failed to parse DNS_PUBLIC");
|
||||
}
|
||||
}
|
||||
|
||||
// init libunbound context
|
||||
m_ctx = ub_ctx_create();
|
||||
|
||||
if (use_dns_public)
|
||||
{
|
||||
for (const auto &ip: dns_public_addr)
|
||||
ub_ctx_set_fwd(m_ctx, ip.c_str());
|
||||
ub_ctx_set_option(m_ctx, "do-udp:", "no");
|
||||
ub_ctx_set_option(m_ctx, "do-tcp:", "yes");
|
||||
}
|
||||
else {
|
||||
// look for "/etc/resolv.conf" and "/etc/hosts" or platform equivalent
|
||||
ub_ctx_resolvconf(m_ctx, NULL);
|
||||
ub_ctx_hosts(m_ctx, NULL);
|
||||
}
|
||||
|
||||
add_anchors(m_ctx);
|
||||
|
||||
if (!DNS_PUBLIC)
|
||||
{
|
||||
// TODO(oxen): Don't probe moneropulse for Loki
|
||||
#if 0
|
||||
// if no DNS_PUBLIC specified, we try a lookup to what we know
|
||||
// should be a valid DNSSEC record, and switch to known good
|
||||
// DNSSEC resolvers if verification fails
|
||||
bool available, valid;
|
||||
static const char *probe_hostname = "updates.moneropulse.org";
|
||||
auto records = get_txt_record(probe_hostname, available, valid);
|
||||
if (!valid)
|
||||
{
|
||||
MINFO("Failed to verify DNSSEC record from " << probe_hostname << ", falling back to TCP with well known DNSSEC resolvers");
|
||||
ub_ctx_delete(m_ctx);
|
||||
m_ctx = ub_ctx_create();
|
||||
add_anchors(m_ctx);
|
||||
for (const auto &ip: DEFAULT_DNS_PUBLIC_ADDR)
|
||||
ub_ctx_set_fwd(m_ctx, string_copy(ip));
|
||||
ub_ctx_set_option(m_ctx, string_copy("do-udp:"), string_copy("no"));
|
||||
ub_ctx_set_option(m_ctx, string_copy("do-tcp:"), string_copy("yes"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> DNSResolver::get_record(const std::string& url, int record_type, std::optional<std::string> (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid)
|
||||
{
|
||||
std::vector<std::string> addresses;
|
||||
dnssec_available = false;
|
||||
dnssec_valid = false;
|
||||
|
||||
if (url.find('.') == std::string::npos)
|
||||
{
|
||||
return addresses;
|
||||
}
|
||||
|
||||
ub_result* result_raw = nullptr;
|
||||
// call DNS resolver, blocking. if return value not zero, something went wrong
|
||||
if (!ub_resolve(m_ctx, url.c_str(), record_type, DNS_CLASS_IN, &result_raw))
|
||||
{
|
||||
// destructor takes care of cleanup
|
||||
ub_result_ptr result{result_raw};
|
||||
|
||||
dnssec_available = (result->secure || result->bogus);
|
||||
dnssec_valid = result->secure && !result->bogus;
|
||||
if (result->havedata)
|
||||
{
|
||||
for (size_t i=0; result->data[i] != NULL; i++)
|
||||
{
|
||||
if (auto res = (*reader)(result->data[i], result->len[i]))
|
||||
{
|
||||
MINFO("Found \"" << *res << "\" in " << get_record_name(record_type) << " record for " << url);
|
||||
addresses.push_back(*res);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return addresses;
|
||||
}
|
||||
|
||||
std::vector<std::string> DNSResolver::get_ipv4(const std::string& url, bool& dnssec_available, bool& dnssec_valid)
|
||||
{
|
||||
return get_record(url, DNS_TYPE_A, ipv4_to_string, dnssec_available, dnssec_valid);
|
||||
}
|
||||
|
||||
std::vector<std::string> DNSResolver::get_ipv6(const std::string& url, bool& dnssec_available, bool& dnssec_valid)
|
||||
{
|
||||
return get_record(url, DNS_TYPE_AAAA, ipv6_to_string, dnssec_available, dnssec_valid);
|
||||
}
|
||||
|
||||
std::vector<std::string> DNSResolver::get_txt_record(const std::string& url, bool& dnssec_available, bool& dnssec_valid)
|
||||
{
|
||||
return get_record(url, DNS_TYPE_TXT, txt_to_string, dnssec_available, dnssec_valid);
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Data pack that we pass into the unbound callback:
|
||||
struct dns_results {
|
||||
int& all_done;
|
||||
const std::string& hostname;
|
||||
const char* record_name;
|
||||
std::vector<std::string>& results;
|
||||
std::optional<std::string> (*reader)(const char*, size_t);
|
||||
int async_id{0};
|
||||
bool done{false};
|
||||
bool dnssec;
|
||||
bool dnssec_required;
|
||||
|
||||
dns_results(int& a, const std::string& h, const char* rn, std::vector<std::string>& r, std::optional<std::string> (*rdr)(const char*, size_t), bool dnssec, bool dnssec_req)
|
||||
: all_done{a}, hostname{h}, record_name{rn}, results{r}, reader{rdr}, dnssec{dnssec}, dnssec_required{dnssec_req}
|
||||
{}
|
||||
};
|
||||
}
|
||||
|
||||
extern "C" void DNSResolver_async_callback(void* data, int err, ub_result* result_raw)
|
||||
{
|
||||
ub_result_ptr result{result_raw};
|
||||
auto &res = *static_cast<dns_results*>(data);
|
||||
res.all_done++;
|
||||
res.done = true;
|
||||
if (err)
|
||||
MWARNING("resolution of " << res.hostname << " failed: " << ub_strerror(err));
|
||||
else if ((res.dnssec || res.dnssec_required) && result->bogus)
|
||||
MWARNING("resolution of " << res.hostname << " failed DNSSEC validation: " << result->why_bogus);
|
||||
else if (res.dnssec_required && !result->secure)
|
||||
MWARNING("resolution of " << res.hostname << " failed: DNSSEC validate is required but is not available");
|
||||
else if (result->havedata)
|
||||
{
|
||||
for (size_t i = 0; result->data[i] != NULL; i++)
|
||||
{
|
||||
if (auto r = (*res.reader)(result->data[i], result->len[i]))
|
||||
{
|
||||
MINFO("Found \"" << *r << "\" in " << res.record_name << " record for " << res.hostname);
|
||||
res.results.push_back(*r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::vector<std::string>> DNSResolver::get_many(int type, const std::vector<std::string>& hostnames, std::chrono::milliseconds timeout, bool dnssec, bool dnssec_required)
|
||||
{
|
||||
auto* reader = type == DNS_TYPE_A ? ipv4_to_string : type == DNS_TYPE_AAAA ? ipv6_to_string : type == DNS_TYPE_TXT ? txt_to_string : nullptr;
|
||||
if (!reader)
|
||||
throw std::invalid_argument("Invalid lookup type: " + std::to_string(type));
|
||||
|
||||
std::vector<std::vector<std::string>> results;
|
||||
if (hostnames.empty())
|
||||
return results;
|
||||
|
||||
int num_done = 0;
|
||||
std::vector<dns_results> result_packs;
|
||||
results.reserve(hostnames.size());
|
||||
result_packs.reserve(hostnames.size());
|
||||
ub_ctx_async(m_ctx, true); // Tells libunbound to use a thread instead of a fork
|
||||
|
||||
// Initiate lookups:
|
||||
for (auto& host : hostnames)
|
||||
{
|
||||
auto& pack = result_packs.emplace_back(num_done, host, get_record_name(type), results.emplace_back(), reader, dnssec, dnssec_required);
|
||||
int err = ub_resolve_async(m_ctx, host.c_str(), type, DNS_CLASS_IN, static_cast<void*>(&pack), DNSResolver_async_callback, &pack.async_id);
|
||||
if (err)
|
||||
{
|
||||
MWARNING("unable to initiate lookup for " << host << ": " << ub_strerror(err));
|
||||
num_done++;
|
||||
pack.done = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for results
|
||||
auto expiry = std::chrono::steady_clock::now() + timeout;
|
||||
while (num_done < (int)results.size() && std::chrono::steady_clock::now() < expiry)
|
||||
{
|
||||
std::this_thread::sleep_for(5ms);
|
||||
int err = ub_process(m_ctx);
|
||||
if (err)
|
||||
{
|
||||
MWARNING("ub_process returned an error while waiting for async results: " << ub_strerror(err));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel any outstanding requests
|
||||
for (auto& pack : result_packs)
|
||||
{
|
||||
if (!pack.done)
|
||||
ub_cancel(m_ctx, pack.async_id);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
std::string DNSResolver::get_dns_format_from_oa_address(std::string_view addr_v)
|
||||
{
|
||||
std::string addr{addr_v};
|
||||
auto first_at = addr.find("@");
|
||||
if (first_at == std::string::npos)
|
||||
return addr;
|
||||
|
||||
// convert name@domain.tld to name.domain.tld
|
||||
addr.replace(first_at, 1, ".");
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
DNSResolver& DNSResolver::instance()
|
||||
{
|
||||
static DNSResolver staticInstance;
|
||||
return staticInstance;
|
||||
}
|
||||
|
||||
DNSResolver DNSResolver::create()
|
||||
{
|
||||
return DNSResolver();
|
||||
}
|
||||
|
||||
namespace dns_utils
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// TODO: parse the string in a less stupid way, probably with regex
|
||||
std::string address_from_txt_record(std::string_view s)
|
||||
{
|
||||
// make sure the txt record has the addr_type and find it
|
||||
constexpr auto addr_type = "oa1:xmr"sv;
|
||||
if (auto pos = s.find(addr_type); pos != std::string_view::npos)
|
||||
s.remove_prefix(pos + addr_type.size()); // remove it and everything before it
|
||||
else
|
||||
return {}; // not found.
|
||||
|
||||
constexpr auto recipient_address = "recipient_address="sv;
|
||||
if (auto pos = s.find(recipient_address); pos != std::string_view::npos)
|
||||
s.remove_prefix(pos + recipient_address.size()); // delete it and everything up to it
|
||||
else
|
||||
return {}; // not found
|
||||
|
||||
// find the next semicolon
|
||||
if (auto pos = s.find(';'); pos != std::string::npos)
|
||||
{
|
||||
// length of address == 95, we can at least validate that much here
|
||||
if (pos == 95)
|
||||
return std::string{s.substr(0, 95)};
|
||||
else if (pos == 106) // length of address == 106 --> integrated address
|
||||
return std::string{s.substr(0, 106)};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
/**
|
||||
* @brief gets a oxen address from the TXT record of a DNS entry
|
||||
*
|
||||
* gets the oxen address from the TXT record of the DNS entry associated
|
||||
* with <url>. If this lookup fails, or the TXT record does not contain an
|
||||
* XMR address in the correct format, returns an empty string. <dnssec_valid>
|
||||
* will be set true or false according to whether or not the DNS query passes
|
||||
* DNSSEC validation.
|
||||
*
|
||||
* @param url the url to look up
|
||||
* @param dnssec_valid return-by-reference for DNSSEC status of query
|
||||
*
|
||||
* @return a oxen address (as a string) or an empty string
|
||||
*/
|
||||
std::vector<std::string> addresses_from_url(const std::string_view url, bool& dnssec_valid)
|
||||
{
|
||||
std::vector<std::string> addresses;
|
||||
// get txt records
|
||||
bool dnssec_available, dnssec_isvalid;
|
||||
std::string oa_addr = DNSResolver::instance().get_dns_format_from_oa_address(url);
|
||||
auto records = DNSResolver::instance().get_txt_record(oa_addr, dnssec_available, dnssec_isvalid);
|
||||
|
||||
// TODO: update this to allow for conveying that dnssec was not available
|
||||
if (dnssec_available && dnssec_isvalid)
|
||||
{
|
||||
dnssec_valid = true;
|
||||
}
|
||||
else dnssec_valid = false;
|
||||
|
||||
// for each txt record, try to find a oxen address in it.
|
||||
for (auto& rec : records)
|
||||
{
|
||||
std::string addr = address_from_txt_record(rec);
|
||||
if (addr.size())
|
||||
{
|
||||
addresses.push_back(std::move(addr));
|
||||
}
|
||||
}
|
||||
return addresses;
|
||||
}
|
||||
|
||||
std::string get_account_address_as_str_from_url(const std::string_view url, bool& dnssec_valid,
|
||||
std::function<std::string(const std::string_view, const std::vector<std::string>&, bool)> dns_confirm)
|
||||
{
|
||||
// attempt to get address from dns query
|
||||
auto addresses = addresses_from_url(url, dnssec_valid);
|
||||
if (addresses.empty())
|
||||
{
|
||||
LOG_ERROR("wrong address: " << url);
|
||||
return {};
|
||||
}
|
||||
return dns_confirm(url, addresses, dnssec_valid);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
bool dns_records_match(const std::vector<std::string>& a, const std::vector<std::string>& b)
|
||||
{
|
||||
if (a.size() != b.size()) return false;
|
||||
|
||||
for (const auto& record_in_a : a)
|
||||
{
|
||||
bool ok = false;
|
||||
for (const auto& record_in_b : b)
|
||||
{
|
||||
if (record_in_a == record_in_b)
|
||||
{
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ok) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool load_txt_records_from_dns(std::vector<std::string> &good_records, const std::vector<std::string> &dns_urls)
|
||||
{
|
||||
// Prevent infinite recursion when distributing
|
||||
if (dns_urls.empty()) return false;
|
||||
|
||||
std::vector<std::vector<std::string> > records;
|
||||
records.resize(dns_urls.size());
|
||||
|
||||
size_t first_index = crypto::rand_idx(dns_urls.size());
|
||||
|
||||
// send all requests in parallel
|
||||
std::deque<bool> avail(dns_urls.size(), false), valid(dns_urls.size(), false);
|
||||
tools::threadpool& tpool = tools::threadpool::getInstance();
|
||||
tools::threadpool::waiter waiter;
|
||||
for (size_t n = 0; n < dns_urls.size(); ++n)
|
||||
{
|
||||
tpool.submit(&waiter,[n, dns_urls, &records, &avail, &valid](){
|
||||
records[n] = tools::DNSResolver::instance().get_txt_record(dns_urls[n], avail[n], valid[n]);
|
||||
});
|
||||
}
|
||||
waiter.wait(&tpool);
|
||||
|
||||
size_t cur_index = first_index;
|
||||
do
|
||||
{
|
||||
const std::string &url = dns_urls[cur_index];
|
||||
if (!avail[cur_index])
|
||||
{
|
||||
records[cur_index].clear();
|
||||
LOG_PRINT_L2("DNSSEC not available for hostname: " << url << ", skipping.");
|
||||
}
|
||||
if (!valid[cur_index])
|
||||
{
|
||||
records[cur_index].clear();
|
||||
LOG_PRINT_L2("DNSSEC validation failed for hostname: " << url << ", skipping.");
|
||||
}
|
||||
|
||||
cur_index++;
|
||||
if (cur_index == dns_urls.size())
|
||||
{
|
||||
cur_index = 0;
|
||||
}
|
||||
} while (cur_index != first_index);
|
||||
|
||||
size_t num_valid_records = 0;
|
||||
|
||||
for( const auto& record_set : records)
|
||||
{
|
||||
if (record_set.size() != 0)
|
||||
{
|
||||
num_valid_records++;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_valid_records < 2)
|
||||
{
|
||||
LOG_PRINT_L0("WARNING: no two valid DNS TXT records were received");
|
||||
return false;
|
||||
}
|
||||
|
||||
int good_records_index = -1;
|
||||
for (size_t i = 0; i < records.size() - 1; ++i)
|
||||
{
|
||||
if (records[i].size() == 0) continue;
|
||||
|
||||
for (size_t j = i + 1; j < records.size(); ++j)
|
||||
{
|
||||
if (dns_records_match(records[i], records[j]))
|
||||
{
|
||||
good_records_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (good_records_index >= 0) break;
|
||||
}
|
||||
|
||||
if (good_records_index < 0)
|
||||
{
|
||||
LOG_PRINT_L0("WARNING: no two DNS TXT records matched");
|
||||
return false;
|
||||
}
|
||||
|
||||
good_records = records[good_records_index];
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::string> parse_dns_public(const char *s)
|
||||
{
|
||||
unsigned ip0, ip1, ip2, ip3;
|
||||
char c;
|
||||
std::vector<std::string> dns_public_addr;
|
||||
if (s == "tcp"sv)
|
||||
{
|
||||
for (auto& default_dns : DEFAULT_DNS_PUBLIC_ADDR)
|
||||
dns_public_addr.emplace_back(default_dns);
|
||||
LOG_PRINT_L0("Using default public DNS server(s): " << tools::join(", ", dns_public_addr) << " (TCP)");
|
||||
}
|
||||
else if (std::sscanf(s, "tcp://%u.%u.%u.%u%c", &ip0, &ip1, &ip2, &ip3, &c) == 4)
|
||||
{
|
||||
if (ip0 > 255 || ip1 > 255 || ip2 > 255 || ip3 > 255)
|
||||
{
|
||||
MERROR("Invalid IP: " << s << ", using default");
|
||||
}
|
||||
else
|
||||
{
|
||||
dns_public_addr.emplace_back(s + 6);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MERROR("Invalid DNS_PUBLIC contents, ignored");
|
||||
}
|
||||
return dns_public_addr;
|
||||
}
|
||||
|
||||
} // namespace tools::dns_utils
|
||||
|
||||
} // namespace tools
|
|
@ -1,186 +0,0 @@
|
|||
// Copyright (c) 2014-2019, 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.
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <chrono>
|
||||
#include <string_view>
|
||||
|
||||
struct ub_ctx;
|
||||
|
||||
namespace tools
|
||||
{
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
// RFC defines for record types and classes for DNS, gleaned from ldns source
|
||||
constexpr int DNS_CLASS_IN = 1;
|
||||
constexpr int DNS_TYPE_A = 1;
|
||||
constexpr int DNS_TYPE_TXT = 16;
|
||||
constexpr int DNS_TYPE_AAAA = 8;
|
||||
|
||||
struct ub_ctx_deleter { void operator()(ub_ctx*); };
|
||||
|
||||
/**
|
||||
* @brief Provides high-level access to DNS resolution
|
||||
*
|
||||
* This class is designed to provide a high-level abstraction to DNS resolution
|
||||
* functionality, including access to TXT records and such. It will also
|
||||
* handle DNSSEC validation of the results.
|
||||
*/
|
||||
class DNSResolver
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Constructs an instance of DNSResolver
|
||||
*
|
||||
* Constructs a class instance and does setup stuff for the backend resolver.
|
||||
*/
|
||||
DNSResolver();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief gets ipv4 addresses from DNS query of a URL
|
||||
*
|
||||
* returns a vector of all IPv4 "A" records for given URL.
|
||||
* If no "A" records found, returns an empty vector.
|
||||
*
|
||||
* @param url A string containing a URL to query for
|
||||
*
|
||||
* @param dnssec_available
|
||||
*
|
||||
* @return vector of strings containing ipv4 addresses
|
||||
*/
|
||||
std::vector<std::string> get_ipv4(const std::string& url, bool& dnssec_available, bool& dnssec_valid);
|
||||
|
||||
/**
|
||||
* @brief gets ipv6 addresses from DNS query
|
||||
*
|
||||
* returns a vector of all IPv6 "A" records for given URL.
|
||||
* If no "A" records found, returns an empty vector.
|
||||
*
|
||||
* @param url A string containing a URL to query for
|
||||
*
|
||||
* @return vector of strings containing ipv6 addresses
|
||||
*/
|
||||
std::vector<std::string> get_ipv6(const std::string& url, bool& dnssec_available, bool& dnssec_valid);
|
||||
|
||||
/**
|
||||
* @brief gets all TXT records from a DNS query for the supplied URL;
|
||||
* if no TXT record present returns an empty vector.
|
||||
*
|
||||
* @param url A string containing a URL to query for
|
||||
*
|
||||
* @return A vector of strings containing a TXT record; or an empty vector
|
||||
*/
|
||||
// TODO: modify this to accommodate DNSSEC
|
||||
std::vector<std::string> get_txt_record(const std::string& url, bool& dnssec_available, bool& dnssec_valid);
|
||||
|
||||
/**
|
||||
* @brief query multiple hostnames simultaneously for results, waiting up to a fixed amount of
|
||||
* time for results before returning.
|
||||
*
|
||||
* @param type `DNS_TYPE_A` or `DNS_TYPE_AAAA` or `DNS_TYPE_TXT` indicating the lookup type.
|
||||
* @param hostnames a vector of hostnames to look up
|
||||
* @param timeout how long to wait for results before giving up. Any results not yet retrieved by
|
||||
* the timeout are left empty.
|
||||
* @param dnssec if true then validate DNSSEC if available (i.e. reject DNSSEC failures, but allow insecure results when DNSSEC not available)
|
||||
* @param dnssec_required if true then require and validate DNSSEC (i.e. reject failures and reject when DNSSEC not available)
|
||||
*
|
||||
* Returns a vector of vector of results: the results for address [i] are in result element [i].
|
||||
* If lookup failed (or DNSSEC failed with the relevant options given) for element [i] then vector
|
||||
* [i] will be empty.
|
||||
*/
|
||||
// TODO: this could be extended to support doing multiple lookup types at once (e.g. A and AAAA).
|
||||
std::vector<std::vector<std::string>> get_many(int type, const std::vector<std::string>& hostnames, std::chrono::milliseconds timeout = 10s, bool dnssec = false, bool dnssec_required = false);
|
||||
|
||||
/**
|
||||
* @brief Gets a DNS address from OpenAlias format
|
||||
*
|
||||
* If the address looks good, but contains one @ symbol, replace that with a .
|
||||
* e.g. donate@getmonero.org becomes donate.getmonero.org
|
||||
*
|
||||
* @param oa_addr OpenAlias address
|
||||
*
|
||||
* @return dns_addr DNS address
|
||||
*/
|
||||
std::string get_dns_format_from_oa_address(std::string_view oa_addr);
|
||||
|
||||
/**
|
||||
* @brief Gets the singleton instance of DNSResolver
|
||||
*
|
||||
* @return returns a reference to the singleton
|
||||
*/
|
||||
static DNSResolver& instance();
|
||||
|
||||
/**
|
||||
* @brief Gets a new instance of DNSResolver
|
||||
*
|
||||
* @return returns a pointer to the new object
|
||||
*/
|
||||
static DNSResolver create();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief gets all records of a given type from a DNS query for the supplied URL;
|
||||
* if no such record is present returns an empty vector.
|
||||
*
|
||||
* @param url A string containing a URL to query for
|
||||
* @param record_type the record type to retrieve (DNS_TYPE_A, etc)
|
||||
* @param reader a function that converts a record data to a string
|
||||
*
|
||||
* @return A vector of strings containing the requested record; or an empty vector
|
||||
*/
|
||||
// TODO: modify this to accommodate DNSSEC
|
||||
std::vector<std::string> get_record(const std::string& url, int record_type, std::optional<std::string> (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid);
|
||||
|
||||
ub_ctx* m_ctx = nullptr;
|
||||
}; // class DNSResolver
|
||||
|
||||
namespace dns_utils
|
||||
{
|
||||
|
||||
std::string address_from_txt_record(std::string_view s);
|
||||
std::vector<std::string> addresses_from_url(const std::string_view url, bool& dnssec_valid);
|
||||
|
||||
std::string get_account_address_as_str_from_url(const std::string_view url, bool& dnssec_valid,
|
||||
std::function<std::string(const std::string_view, const std::vector<std::string>&, bool)> confirm_dns);
|
||||
|
||||
bool load_txt_records_from_dns(std::vector<std::string> &records, const std::vector<std::string> &dns_urls);
|
||||
|
||||
std::vector<std::string> parse_dns_public(const char *s);
|
||||
|
||||
} // namespace tools::dns_utils
|
||||
|
||||
} // namespace tools
|
|
@ -254,7 +254,7 @@ namespace tools {
|
|||
}
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
fs::path get_special_folder_path(int nfolder, bool iscreate)
|
||||
{
|
||||
WCHAR psz_path[MAX_PATH] = L"";
|
||||
|
@ -267,31 +267,29 @@ namespace tools {
|
|||
LOG_ERROR("SHGetSpecialFolderPathW() failed, could not obtain requested path.");
|
||||
return "";
|
||||
}
|
||||
|
||||
// Windows < Vista: C:\Documents and Settings\Username\Application Data\CRYPTONOTE_NAME
|
||||
// Windows >= Vista: C:\Users\Username\AppData\Roaming\CRYPTONOTE_NAME
|
||||
fs::path get_default_data_dir()
|
||||
{
|
||||
return get_special_folder_path(CSIDL_COMMON_APPDATA, true) / fs::u8path(CRYPTONOTE_NAME);
|
||||
}
|
||||
fs::path get_depreciated_default_data_dir()
|
||||
{
|
||||
return get_special_folder_path(CSIDL_COMMON_APPDATA, true) / fs::u8path("loki");
|
||||
}
|
||||
#else
|
||||
// Non-windows: ~/.CRYPTONOTE_NAME
|
||||
fs::path get_default_data_dir()
|
||||
{
|
||||
char* home = std::getenv("HOME");
|
||||
return (home && std::strlen(home) ? fs::u8path(home) : fs::current_path()) / fs::u8path("." CRYPTONOTE_NAME);
|
||||
}
|
||||
fs::path get_depreciated_default_data_dir()
|
||||
{
|
||||
char* home = std::getenv("HOME");
|
||||
return (home && std::strlen(home) ? fs::u8path(home) : fs::current_path()) / fs::u8path(".loki");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Windows < Vista: C:\Documents and Settings\Username\Application Data\...
|
||||
// Windows >= Vista: C:\Users\Username\AppData\Roaming\...
|
||||
// Sane OSes: ~/
|
||||
static fs::path get_default_parent_dir() {
|
||||
#ifdef _WIN32
|
||||
return get_special_folder_path(CSIDL_COMMON_APPDATA, true);
|
||||
#else
|
||||
char* home = std::getenv("HOME");
|
||||
return home && std::strlen(home) ? fs::u8path(home) : fs::current_path();
|
||||
#endif
|
||||
}
|
||||
|
||||
fs::path get_default_data_dir()
|
||||
{
|
||||
return get_default_parent_dir() / fs::u8path(cryptonote::DATA_DIRNAME);
|
||||
}
|
||||
fs::path get_depreciated_default_data_dir()
|
||||
{
|
||||
return get_default_parent_dir() / fs::u8path(cryptonote::old::DATA_DIRNAME);
|
||||
}
|
||||
|
||||
void set_strict_default_file_permissions(bool strict)
|
||||
{
|
||||
#if defined(__MINGW32__) || defined(__MINGW__)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#pragma once
|
||||
#include <oxenmq/hex.h>
|
||||
#include <oxenc/hex.h>
|
||||
#include <type_traits>
|
||||
#include "epee/span.h" // epee
|
||||
|
||||
|
@ -11,9 +11,9 @@ namespace tools {
|
|||
!std::is_const_v<T> && (std::is_trivially_copyable_v<T> || epee::is_byte_spannable<T>)
|
||||
>>
|
||||
bool hex_to_type(std::string_view hex, T& x) {
|
||||
if (!oxenmq::is_hex(hex) || hex.size() != 2*sizeof(T))
|
||||
if (!oxenc::is_hex(hex) || hex.size() != 2*sizeof(T))
|
||||
return false;
|
||||
oxenmq::from_hex(hex.begin(), hex.end(), reinterpret_cast<char*>(&x));
|
||||
oxenc::from_hex(hex.begin(), hex.end(), reinterpret_cast<char*>(&x));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,6 @@ namespace tools {
|
|||
|| epee::is_byte_spannable<T>
|
||||
>>
|
||||
std::string type_to_hex(const T& val) {
|
||||
return oxenmq::to_hex(std::string_view{reinterpret_cast<const char*>(&val), sizeof(val)});
|
||||
return oxenc::to_hex(std::string_view{reinterpret_cast<const char*>(&val), sizeof(val)});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2022, The Oxen Project
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace tools {
|
||||
|
||||
// Calculate the median element (the middle element, if an odd size, and the mean of the two
|
||||
// middle elements if even). Pass first=true if you don't care about the mean of the middle two,
|
||||
// in which case you'll get back the value of lower of the two middle elements.
|
||||
// This leaves the given range in an indeterminant (partially sorted) order.
|
||||
template <typename RandomAccessIter>
|
||||
auto median(RandomAccessIter begin, RandomAccessIter end, bool first=false) {
|
||||
std::size_t size = end - begin;
|
||||
if (size == 0)
|
||||
return std::decay_t<decltype(*begin)>{};
|
||||
|
||||
auto mid = begin + (size - 1) / 2;
|
||||
std::nth_element(begin, mid, end);
|
||||
|
||||
if (first || size % 2)
|
||||
return *mid;
|
||||
|
||||
auto mid2 = std::min_element(mid + 1, end);
|
||||
return (*mid + *mid2) / 2;
|
||||
}
|
||||
|
||||
// Same as above, but takes a vector by value or move for convenience.
|
||||
template <typename T>
|
||||
T median(std::vector<T> v, bool first=false) {
|
||||
return median(v.begin(), v.end(), first);
|
||||
}
|
||||
}
|
|
@ -34,6 +34,8 @@
|
|||
namespace tools
|
||||
{
|
||||
|
||||
using namespace cryptonote;
|
||||
|
||||
uint32_t make_pruning_seed(uint32_t stripe, uint32_t log_stripes)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(log_stripes <= PRUNING_SEED_LOG_STRIPES_MASK, "log_stripes out of range");
|
||||
|
@ -53,9 +55,9 @@ bool has_unpruned_block(uint64_t block_height, uint64_t blockchain_height, uint3
|
|||
|
||||
uint32_t get_pruning_stripe(uint64_t block_height, uint64_t blockchain_height, uint32_t log_stripes)
|
||||
{
|
||||
if (block_height + CRYPTONOTE_PRUNING_TIP_BLOCKS >= blockchain_height)
|
||||
if (block_height + PRUNING_TIP_BLOCKS >= blockchain_height)
|
||||
return 0;
|
||||
return ((block_height / CRYPTONOTE_PRUNING_STRIPE_SIZE) & (uint64_t)((1ul << log_stripes) - 1)) + 1;
|
||||
return ((block_height / PRUNING_STRIPE_SIZE) & (uint64_t)((1ul << log_stripes) - 1)) + 1;
|
||||
}
|
||||
|
||||
uint32_t get_pruning_seed(uint64_t block_height, uint64_t blockchain_height, uint32_t log_stripes)
|
||||
|
@ -68,24 +70,24 @@ uint32_t get_pruning_seed(uint64_t block_height, uint64_t blockchain_height, uin
|
|||
|
||||
uint64_t get_next_unpruned_block_height(uint64_t block_height, uint64_t blockchain_height, uint32_t pruning_seed)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(block_height <= CRYPTONOTE_MAX_BLOCK_NUMBER+1, block_height, "block_height too large");
|
||||
CHECK_AND_ASSERT_MES(blockchain_height <= CRYPTONOTE_MAX_BLOCK_NUMBER+1, block_height, "blockchain_height too large");
|
||||
CHECK_AND_ASSERT_MES(block_height <= MAX_BLOCK_NUMBER+1, block_height, "block_height too large");
|
||||
CHECK_AND_ASSERT_MES(blockchain_height <= MAX_BLOCK_NUMBER+1, block_height, "blockchain_height too large");
|
||||
const uint32_t stripe = get_pruning_stripe(pruning_seed);
|
||||
if (stripe == 0)
|
||||
return block_height;
|
||||
if (block_height + CRYPTONOTE_PRUNING_TIP_BLOCKS >= blockchain_height)
|
||||
if (block_height + PRUNING_TIP_BLOCKS >= blockchain_height)
|
||||
return block_height;
|
||||
const uint32_t seed_log_stripes = get_pruning_log_stripes(pruning_seed);
|
||||
const uint64_t log_stripes = seed_log_stripes ? seed_log_stripes : CRYPTONOTE_PRUNING_LOG_STRIPES;
|
||||
const uint64_t log_stripes = seed_log_stripes ? seed_log_stripes : PRUNING_LOG_STRIPES;
|
||||
const uint64_t mask = (1ul << log_stripes) - 1;
|
||||
const uint32_t block_pruning_stripe = ((block_height / CRYPTONOTE_PRUNING_STRIPE_SIZE) & mask) + 1;
|
||||
const uint32_t block_pruning_stripe = ((block_height / PRUNING_STRIPE_SIZE) & mask) + 1;
|
||||
if (block_pruning_stripe == stripe)
|
||||
return block_height;
|
||||
const uint64_t cycles = ((block_height / CRYPTONOTE_PRUNING_STRIPE_SIZE) >> log_stripes);
|
||||
const uint64_t cycles = ((block_height / PRUNING_STRIPE_SIZE) >> log_stripes);
|
||||
const uint64_t cycle_start = cycles + ((stripe > block_pruning_stripe) ? 0 : 1);
|
||||
const uint64_t h = cycle_start * (CRYPTONOTE_PRUNING_STRIPE_SIZE << log_stripes) + (stripe - 1) * CRYPTONOTE_PRUNING_STRIPE_SIZE;
|
||||
if (h + CRYPTONOTE_PRUNING_TIP_BLOCKS > blockchain_height)
|
||||
return blockchain_height < CRYPTONOTE_PRUNING_TIP_BLOCKS ? 0 : blockchain_height - CRYPTONOTE_PRUNING_TIP_BLOCKS;
|
||||
const uint64_t h = cycle_start * (PRUNING_STRIPE_SIZE << log_stripes) + (stripe - 1) * PRUNING_STRIPE_SIZE;
|
||||
if (h + PRUNING_TIP_BLOCKS > blockchain_height)
|
||||
return blockchain_height < PRUNING_TIP_BLOCKS ? 0 : blockchain_height - PRUNING_TIP_BLOCKS;
|
||||
CHECK_AND_ASSERT_MES(h >= block_height, block_height, "h < block_height, unexpected");
|
||||
return h;
|
||||
}
|
||||
|
@ -95,12 +97,12 @@ uint64_t get_next_pruned_block_height(uint64_t block_height, uint64_t blockchain
|
|||
const uint32_t stripe = get_pruning_stripe(pruning_seed);
|
||||
if (stripe == 0)
|
||||
return blockchain_height;
|
||||
if (block_height + CRYPTONOTE_PRUNING_TIP_BLOCKS >= blockchain_height)
|
||||
if (block_height + PRUNING_TIP_BLOCKS >= blockchain_height)
|
||||
return blockchain_height;
|
||||
const uint32_t seed_log_stripes = get_pruning_log_stripes(pruning_seed);
|
||||
const uint64_t log_stripes = seed_log_stripes ? seed_log_stripes : CRYPTONOTE_PRUNING_LOG_STRIPES;
|
||||
const uint64_t log_stripes = seed_log_stripes ? seed_log_stripes : PRUNING_LOG_STRIPES;
|
||||
const uint64_t mask = (1ul << log_stripes) - 1;
|
||||
const uint32_t block_pruning_seed = ((block_height / CRYPTONOTE_PRUNING_STRIPE_SIZE) & mask) + 1;
|
||||
const uint32_t block_pruning_seed = ((block_height / PRUNING_STRIPE_SIZE) & mask) + 1;
|
||||
if (block_pruning_seed != stripe)
|
||||
return block_height;
|
||||
const uint32_t next_stripe = 1 + (block_pruning_seed & mask);
|
||||
|
@ -109,7 +111,7 @@ uint64_t get_next_pruned_block_height(uint64_t block_height, uint64_t blockchain
|
|||
|
||||
uint32_t get_random_stripe()
|
||||
{
|
||||
return 1 + crypto::rand<uint8_t>() % (1ul << CRYPTONOTE_PRUNING_LOG_STRIPES);
|
||||
return 1 + crypto::rand<uint8_t>() % (1ul << PRUNING_LOG_STRIPES);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,13 +32,19 @@
|
|||
|
||||
namespace tools
|
||||
{
|
||||
static constexpr uint32_t PRUNING_SEED_LOG_STRIPES_SHIFT = 7;
|
||||
static constexpr uint32_t PRUNING_SEED_LOG_STRIPES_MASK = 0x7;
|
||||
static constexpr uint32_t PRUNING_SEED_STRIPE_SHIFT = 0;
|
||||
static constexpr uint32_t PRUNING_SEED_STRIPE_MASK = 0x7f;
|
||||
inline constexpr uint32_t PRUNING_SEED_LOG_STRIPES_SHIFT = 7;
|
||||
inline constexpr uint32_t PRUNING_SEED_LOG_STRIPES_MASK = 0x7;
|
||||
inline constexpr uint32_t PRUNING_SEED_STRIPE_SHIFT = 0;
|
||||
inline constexpr uint32_t PRUNING_SEED_STRIPE_MASK = 0x7f;
|
||||
|
||||
constexpr inline uint32_t get_pruning_log_stripes(uint32_t pruning_seed) { return (pruning_seed >> PRUNING_SEED_LOG_STRIPES_SHIFT) & PRUNING_SEED_LOG_STRIPES_MASK; }
|
||||
inline uint32_t get_pruning_stripe(uint32_t pruning_seed) { if (pruning_seed == 0) return 0; return 1 + ((pruning_seed >> PRUNING_SEED_STRIPE_SHIFT) & PRUNING_SEED_STRIPE_MASK); }
|
||||
inline constexpr uint32_t get_pruning_log_stripes(uint32_t pruning_seed) {
|
||||
return (pruning_seed >> PRUNING_SEED_LOG_STRIPES_SHIFT) & PRUNING_SEED_LOG_STRIPES_MASK;
|
||||
}
|
||||
inline constexpr uint32_t get_pruning_stripe(uint32_t pruning_seed) {
|
||||
if (pruning_seed == 0)
|
||||
return 0;
|
||||
return 1 + ((pruning_seed >> PRUNING_SEED_STRIPE_SHIFT) & PRUNING_SEED_STRIPE_MASK);
|
||||
}
|
||||
|
||||
uint32_t make_pruning_seed(uint32_t stripe, uint32_t log_stripes);
|
||||
|
||||
|
|
|
@ -41,11 +41,11 @@ namespace rules
|
|||
|
||||
bool is_output_unlocked(uint64_t unlock_time, uint64_t height)
|
||||
{
|
||||
if(unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER)
|
||||
if(unlock_time < MAX_BLOCK_NUMBER)
|
||||
{
|
||||
// ND: Instead of calling get_current_blockchain_height(), call m_db->height()
|
||||
// directly as get_current_blockchain_height() locks the recursive mutex.
|
||||
if(height - 1 + CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS >= unlock_time)
|
||||
if(height - 1 + LOCKED_TX_ALLOWED_DELTA_BLOCKS >= unlock_time)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
@ -54,7 +54,7 @@ bool is_output_unlocked(uint64_t unlock_time, uint64_t height)
|
|||
{
|
||||
//interpret as time
|
||||
uint64_t current_time = static_cast<uint64_t>(time(NULL));
|
||||
if(current_time + tools::to_seconds(CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V2) >= unlock_time)
|
||||
if(current_time + tools::to_seconds(LOCKED_TX_ALLOWED_DELTA_BLOCKS * TARGET_BLOCK_TIME) >= unlock_time)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
|
|
@ -28,14 +28,11 @@
|
|||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
#include <cstdint>
|
||||
|
||||
namespace rules
|
||||
namespace cryptonote::rules
|
||||
{
|
||||
|
||||
bool is_output_unlocked(uint64_t unlock_time, uint64_t height);
|
||||
|
||||
} // namespace rules
|
||||
|
||||
} // namespace cryptonote
|
||||
} // namespace cryptonote::rules
|
||||
|
|
|
@ -3,22 +3,16 @@
|
|||
#include <fstream>
|
||||
#include "crypto/hash.h"
|
||||
#include "fs.h"
|
||||
|
||||
extern "C" {
|
||||
#include <openssl/sha.h>
|
||||
}
|
||||
#include <sodium/crypto_hash_sha256.h>
|
||||
|
||||
namespace tools {
|
||||
|
||||
bool sha256sum_str(std::string_view data, crypto::hash &hash)
|
||||
{
|
||||
SHA256_CTX ctx;
|
||||
if (!SHA256_Init(&ctx))
|
||||
return false;
|
||||
if (!SHA256_Update(&ctx, data.data(), data.size()))
|
||||
return false;
|
||||
if (!SHA256_Final(reinterpret_cast<unsigned char*>(hash.data), &ctx))
|
||||
return false;
|
||||
crypto_hash_sha256(
|
||||
reinterpret_cast<unsigned char*>(hash.data),
|
||||
reinterpret_cast<const unsigned char*>(data.data()),
|
||||
data.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -32,25 +26,23 @@ namespace tools {
|
|||
if (!f)
|
||||
return false;
|
||||
std::ifstream::pos_type file_size = f.tellg();
|
||||
SHA256_CTX ctx;
|
||||
if (!SHA256_Init(&ctx))
|
||||
return false;
|
||||
crypto_hash_sha256_state st;
|
||||
crypto_hash_sha256_init(&st);
|
||||
size_t size_left = file_size;
|
||||
f.seekg(0, std::ios::beg);
|
||||
|
||||
std::array<unsigned char, 16384> buf;
|
||||
while (size_left)
|
||||
{
|
||||
char buf[4096];
|
||||
std::ifstream::pos_type read_size = size_left > sizeof(buf) ? sizeof(buf) : size_left;
|
||||
f.read(buf, read_size);
|
||||
auto read_size = std::min(size_left, buf.size());
|
||||
f.read(reinterpret_cast<char*>(buf.data()), read_size);
|
||||
if (!f || !f.good())
|
||||
return false;
|
||||
if (!SHA256_Update(&ctx, buf, read_size))
|
||||
return false;
|
||||
crypto_hash_sha256_update(&st, buf.data(), read_size);
|
||||
size_left -= read_size;
|
||||
}
|
||||
f.close();
|
||||
if (!SHA256_Final((unsigned char*)hash.data, &ctx))
|
||||
return false;
|
||||
crypto_hash_sha256_final(&st, reinterpret_cast<unsigned char*>(hash.data));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,13 +8,6 @@ namespace crypto { struct hash; }
|
|||
|
||||
namespace tools {
|
||||
|
||||
// This used to be really dangerously overloaded with very different purposes:
|
||||
//bool sha256sum(const uint8_t* data, size_t len, crypto::hash& hash);
|
||||
//bool sha256sum(const fs::path& filename, crypto::hash& hash);
|
||||
// which is incredibly dangerous if you happen to have a string you want to hash and see that
|
||||
// there is both a pointer+size and std::string overload. Renamed *both* of these to prevent any
|
||||
// existing code from compiling.
|
||||
|
||||
// Calculates sha256 checksum of the given data
|
||||
bool sha256sum_str(std::string_view str, crypto::hash& hash);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "string_util.h"
|
||||
#include <cassert>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
namespace tools {
|
||||
|
@ -114,4 +115,31 @@ std::string friendly_duration(std::chrono::nanoseconds dur) {
|
|||
return os.str();
|
||||
}
|
||||
|
||||
std::string short_duration(std::chrono::duration<double> dur) {
|
||||
std::ostringstream os;
|
||||
os << std::fixed << std::setprecision(1);
|
||||
if (dur >= 36h)
|
||||
os << dur / 24h;
|
||||
else if (dur >= 90min)
|
||||
os << dur / 1h;
|
||||
else if (dur >= 90s)
|
||||
os << dur / 1min;
|
||||
else if (dur >= 1s)
|
||||
os << dur / 1s;
|
||||
else if (dur >= 100ms)
|
||||
os << std::setprecision(0) << dur / 1ms;
|
||||
else if (dur >= 1ms)
|
||||
os << dur / 1ms;
|
||||
else if (dur >= 100us)
|
||||
os << std::setprecision(0) << dur / 1us;
|
||||
else if (dur >= 1us)
|
||||
os << dur / 1us;
|
||||
else if (dur >= 1ns)
|
||||
os << std::setprecision(0) << dur / 1ns;
|
||||
else
|
||||
os << "0s";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -170,9 +170,12 @@ T make_from_guts(std::string_view s) {
|
|||
|
||||
std::string lowercase_ascii_string(std::string_view src);
|
||||
|
||||
/// Converts a duration into a human friendlier string.
|
||||
/// Converts a duration into a human friendlier string, such as "3d7d47m12s" or "347µs"
|
||||
std::string friendly_duration(std::chrono::nanoseconds dur);
|
||||
|
||||
/// Converts a duration into a shorter, single-unit fractional display such as `42.3min`
|
||||
std::string short_duration(std::chrono::duration<double> dur);
|
||||
|
||||
/// Given an array of string arguments, look for strings of the format <prefix><value> and return <value>
|
||||
/// Returns empty string view if not found.
|
||||
template <typename It>
|
||||
|
|
|
@ -34,17 +34,14 @@
|
|||
#include <iomanip>
|
||||
#include <thread>
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#include <date/date.h>
|
||||
|
||||
#include "unbound.h"
|
||||
|
||||
#include "epee/string_tools.h"
|
||||
#include "epee/wipeable_string.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "util.h"
|
||||
#include "epee/readline_buffer.h"
|
||||
#include "epee/misc_log_ex.h"
|
||||
#include "string_util.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
@ -60,21 +57,6 @@
|
|||
namespace tools
|
||||
{
|
||||
|
||||
static bool unbound_built_with_threads()
|
||||
{
|
||||
ub_ctx *ctx = ub_ctx_create();
|
||||
if (!ctx) return false; // cheat a bit, should not happen unless OOM
|
||||
char *oxen = strdup("oxen"), *unbound = strdup("unbound");
|
||||
ub_ctx_zone_add(ctx, oxen, unbound); // this calls ub_ctx_finalize first, then errors out with UB_SYNTAX
|
||||
free(unbound);
|
||||
free(oxen);
|
||||
// if no threads, bails out early with UB_NOERROR, otherwise fails with UB_AFTERFINAL id already finalized
|
||||
bool with_threads = ub_ctx_async(ctx, 1) != 0; // UB_AFTERFINAL is not defined in public headers, check any error
|
||||
ub_ctx_delete(ctx);
|
||||
MINFO("libunbound was built " << (with_threads ? "with" : "without") << " threads");
|
||||
return with_threads;
|
||||
}
|
||||
|
||||
bool disable_core_dumps()
|
||||
{
|
||||
#ifdef __GLIBC__
|
||||
|
@ -115,15 +97,6 @@ namespace tools
|
|||
MCLOG_RED(el::Level::Warning, "global", "Running with glibc " << ver << ", hangs may occur - change glibc version if possible");
|
||||
#endif
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(LIBRESSL_VERSION_TEXT)
|
||||
SSL_library_init();
|
||||
#else
|
||||
OPENSSL_init_ssl(0, NULL);
|
||||
#endif
|
||||
|
||||
if (!unbound_built_with_threads())
|
||||
MCLOG_RED(el::Level::Warning, "global", "libunbound was not built with threads enabled - crashes may occur");
|
||||
|
||||
return true;
|
||||
}
|
||||
namespace
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <boost/endian/conversion.hpp>
|
||||
#include <oxenc/endian.h>
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
@ -85,7 +85,7 @@ namespace tools
|
|||
// Copy an integer type, swapping to little-endian if needed
|
||||
template <typename T, std::enable_if_t<std::is_integral<T>::value, int> = 0>
|
||||
void memcpy_one(char*& dest, T t) {
|
||||
boost::endian::native_to_little_inplace(t);
|
||||
oxenc::host_to_little_inplace(t);
|
||||
std::memcpy(dest, &t, sizeof(T));
|
||||
dest += sizeof(T);
|
||||
}
|
||||
|
|
|
@ -291,7 +291,7 @@ namespace crypto {
|
|||
ec_point Y;
|
||||
};
|
||||
|
||||
void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) {
|
||||
signature generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec) {
|
||||
ge_p3 tmp3;
|
||||
ec_scalar k;
|
||||
s_comm buf;
|
||||
|
@ -307,6 +307,7 @@ namespace crypto {
|
|||
#endif
|
||||
buf.h = prefix_hash;
|
||||
buf.key = pub;
|
||||
signature sig;
|
||||
try_again:
|
||||
random_scalar(k);
|
||||
ge_scalarmult_base(&tmp3, &k);
|
||||
|
@ -318,6 +319,11 @@ namespace crypto {
|
|||
if (!sc_isnonzero((const unsigned char*)sig.r.data))
|
||||
goto try_again;
|
||||
memwipe(&k, sizeof(k));
|
||||
return sig;
|
||||
}
|
||||
|
||||
void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) {
|
||||
sig = generate_signature(prefix_hash, pub, sec);
|
||||
}
|
||||
|
||||
static constexpr ec_point infinity = {{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
|
|
|
@ -238,6 +238,7 @@ namespace crypto {
|
|||
* Ed25519: given signature (R, s), (unhashed) message M, pubkey A:
|
||||
* Check: sB == R + H(R||A||M)A
|
||||
*/
|
||||
signature generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec);
|
||||
void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig);
|
||||
// See above.
|
||||
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig);
|
||||
|
|
|
@ -39,13 +39,7 @@
|
|||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
// ANDROID, FreeBSD, OpenBSD and NetBSD also don't need timeb.h
|
||||
#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__ANDROID__) \
|
||||
&& !defined(__NetBSD__)
|
||||
#include <sys/timeb.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <process.h>
|
||||
|
@ -474,19 +468,6 @@ OAES_RET oaes_sprintf(
|
|||
#ifdef OAES_HAVE_ISAAC
|
||||
static void oaes_get_seed( char buf[RANDSIZ + 1] )
|
||||
{
|
||||
#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
|
||||
struct timeb timer;
|
||||
struct tm *gmTimer;
|
||||
char * _test = NULL;
|
||||
|
||||
ftime (&timer);
|
||||
gmTimer = gmtime( &timer.time );
|
||||
_test = (char *) calloc( sizeof( char ), timer.millitm );
|
||||
sprintf( buf, "%04d%02d%02d%02d%02d%02d%03d%p%d",
|
||||
gmTimer->tm_year + 1900, gmTimer->tm_mon + 1, gmTimer->tm_mday,
|
||||
gmTimer->tm_hour, gmTimer->tm_min, gmTimer->tm_sec, timer.millitm,
|
||||
_test + timer.millitm, GETPID() );
|
||||
#else
|
||||
struct timeval timer;
|
||||
struct tm *gmTimer;
|
||||
char * _test = NULL;
|
||||
|
@ -498,7 +479,6 @@ static void oaes_get_seed( char buf[RANDSIZ + 1] )
|
|||
gmTimer->tm_year + 1900, gmTimer->tm_mon + 1, gmTimer->tm_mday,
|
||||
gmTimer->tm_hour, gmTimer->tm_min, gmTimer->tm_sec, timer.tv_usec/1000,
|
||||
_test + timer.tv_usec/1000, GETPID() );
|
||||
#endif
|
||||
|
||||
if( _test )
|
||||
free( _test );
|
||||
|
@ -506,19 +486,6 @@ static void oaes_get_seed( char buf[RANDSIZ + 1] )
|
|||
#else
|
||||
static uint32_t oaes_get_seed(void)
|
||||
{
|
||||
#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(__NetBSD__)
|
||||
struct timeb timer;
|
||||
struct tm *gmTimer;
|
||||
char * _test = NULL;
|
||||
uint32_t _ret = 0;
|
||||
|
||||
ftime (&timer);
|
||||
gmTimer = gmtime( &timer.time );
|
||||
_test = (char *) calloc( sizeof( char ), timer.millitm );
|
||||
_ret = gmTimer->tm_year + 1900 + gmTimer->tm_mon + 1 + gmTimer->tm_mday +
|
||||
gmTimer->tm_hour + gmTimer->tm_min + gmTimer->tm_sec + timer.millitm +
|
||||
(uintptr_t) ( _test + timer.millitm ) + GETPID();
|
||||
#else
|
||||
struct timeval timer;
|
||||
struct tm *gmTimer;
|
||||
char * _test = NULL;
|
||||
|
@ -530,7 +497,6 @@ static uint32_t oaes_get_seed(void)
|
|||
_ret = gmTimer->tm_year + 1900 + gmTimer->tm_mon + 1 + gmTimer->tm_mday +
|
||||
gmTimer->tm_hour + gmTimer->tm_min + gmTimer->tm_sec + timer.tv_usec/1000 +
|
||||
(uintptr_t) ( _test + timer.tv_usec/1000 ) + GETPID();
|
||||
#endif
|
||||
|
||||
if( _test )
|
||||
free( _test );
|
||||
|
|
|
@ -68,7 +68,7 @@ DISABLE_VS_WARNINGS(4244 4345)
|
|||
static_assert(sizeof(base_key) == sizeof(crypto::hash), "chacha key and hash should be the same size");
|
||||
epee::mlocked<tools::scrubbed_arr<char, sizeof(base_key)+1>> data;
|
||||
memcpy(data.data(), &base_key, sizeof(base_key));
|
||||
data[sizeof(base_key)] = config::HASH_KEY_MEMORY;
|
||||
data[sizeof(base_key)] = cryptonote::hashkey::MEMORY;
|
||||
crypto::generate_chacha_key(data.data(), sizeof(data), key, 1);
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
// Copyright (c) 2014-2019, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "epee/span.h"
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
typedef std::string blobdata;
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#include "cryptonote_basic.h"
|
||||
#include <oxenc/endian.h>
|
||||
|
||||
#include "cryptonote_format_utils.h"
|
||||
|
||||
|
@ -104,7 +105,10 @@ block::block(const block& b) :
|
|||
block_header(b),
|
||||
miner_tx{b.miner_tx},
|
||||
tx_hashes{b.tx_hashes},
|
||||
signatures{b.signatures}
|
||||
signatures{b.signatures},
|
||||
height{b.height},
|
||||
service_node_winner_key{b.service_node_winner_key},
|
||||
reward{b.reward}
|
||||
{
|
||||
copy_hash(b);
|
||||
}
|
||||
|
@ -113,7 +117,10 @@ block::block(block&& b) :
|
|||
block_header(std::move(b)),
|
||||
miner_tx{std::move(b.miner_tx)},
|
||||
tx_hashes{std::move(b.tx_hashes)},
|
||||
signatures{std::move(b.signatures)}
|
||||
signatures{std::move(b.signatures)},
|
||||
height{std::move(b.height)},
|
||||
service_node_winner_key{std::move(b.service_node_winner_key)},
|
||||
reward{std::move(b.reward)}
|
||||
{
|
||||
copy_hash(b);
|
||||
}
|
||||
|
@ -124,6 +131,9 @@ block& block::operator=(const block& b)
|
|||
miner_tx = b.miner_tx;
|
||||
tx_hashes = b.tx_hashes;
|
||||
signatures = b.signatures;
|
||||
height = b.height;
|
||||
service_node_winner_key = b.service_node_winner_key;
|
||||
reward = b.reward;
|
||||
copy_hash(b);
|
||||
return *this;
|
||||
}
|
||||
|
@ -133,6 +143,9 @@ block& block::operator=(block&& b)
|
|||
miner_tx = std::move(b.miner_tx);
|
||||
tx_hashes = std::move(b.tx_hashes);
|
||||
signatures = std::move(b.signatures);
|
||||
height = std::move(b.height);
|
||||
service_node_winner_key = std::move(b.service_node_winner_key);
|
||||
reward = std::move(b.reward);
|
||||
copy_hash(b);
|
||||
return *this;
|
||||
}
|
||||
|
@ -146,4 +159,23 @@ void block::set_hash_valid(bool v) const
|
|||
hash_valid.store(v,std::memory_order_release);
|
||||
}
|
||||
|
||||
// Convert the address to an integer and then performs (address % interval)
|
||||
// it does this by taking the first 64 bits of the public_view_key and converting to an integer
|
||||
// This is used to determine when an address gets paid their batching reward.
|
||||
uint64_t account_public_address::modulus(uint64_t interval) const
|
||||
{
|
||||
uint64_t address_as_integer = 0;
|
||||
std::memcpy(&address_as_integer, m_view_public_key.data, sizeof(address_as_integer));
|
||||
oxenc::host_to_little_inplace(address_as_integer);
|
||||
return address_as_integer % interval;
|
||||
}
|
||||
|
||||
uint64_t account_public_address::next_payout_height(uint64_t current_height, uint64_t interval) const
|
||||
{
|
||||
uint64_t next_payout_height = current_height + (modulus(interval) - current_height % interval);
|
||||
if (next_payout_height <= current_height)
|
||||
next_payout_height += interval;
|
||||
return next_payout_height;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -176,9 +176,9 @@ namespace cryptonote
|
|||
static char const* version_to_string(txversion v);
|
||||
static char const* type_to_string(txtype type);
|
||||
|
||||
static constexpr txversion get_min_version_for_hf(uint8_t hf_version);
|
||||
static txversion get_max_version_for_hf(uint8_t hf_version);
|
||||
static constexpr txtype get_max_type_for_hf (uint8_t hf_version);
|
||||
static constexpr txversion get_min_version_for_hf(hf hf_version);
|
||||
static txversion get_max_version_for_hf(hf hf_version);
|
||||
static constexpr txtype get_max_type_for_hf (hf hf_version);
|
||||
|
||||
// tx information
|
||||
txversion version;
|
||||
|
@ -208,7 +208,9 @@ namespace cryptonote
|
|||
FIELD(vin)
|
||||
FIELD(vout)
|
||||
if (version >= txversion::v3_per_output_unlock_times && vout.size() != output_unlock_times.size())
|
||||
{
|
||||
throw std::invalid_argument{"v3 tx without correct unlock times"};
|
||||
}
|
||||
FIELD(extra)
|
||||
if (version >= txversion::v4_tx_types)
|
||||
ENUM_FIELD_N("type", type, type < txtype::_count);
|
||||
|
@ -393,22 +395,12 @@ namespace cryptonote
|
|||
|
||||
struct block_header
|
||||
{
|
||||
uint8_t major_version = cryptonote::network_version_7;
|
||||
uint8_t minor_version = cryptonote::network_version_7; // now used as a voting mechanism, rather than how this particular block is built
|
||||
hf major_version = hf::hf7;
|
||||
uint8_t minor_version = 0;
|
||||
uint64_t timestamp;
|
||||
crypto::hash prev_id;
|
||||
uint32_t nonce;
|
||||
pulse_header pulse = {};
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
VARINT_FIELD(major_version)
|
||||
VARINT_FIELD(minor_version)
|
||||
VARINT_FIELD(timestamp)
|
||||
FIELD(prev_id)
|
||||
FIELD(nonce)
|
||||
if (major_version >= cryptonote::network_version_16_pulse)
|
||||
FIELD(pulse)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct block: public block_header
|
||||
|
@ -429,26 +421,49 @@ namespace cryptonote
|
|||
void set_hash_valid(bool v) const;
|
||||
|
||||
transaction miner_tx;
|
||||
size_t height;
|
||||
crypto::public_key service_node_winner_key;
|
||||
uint64_t reward = 0;
|
||||
std::vector<crypto::hash> tx_hashes;
|
||||
|
||||
// hash cache
|
||||
mutable crypto::hash hash;
|
||||
std::vector<service_nodes::quorum_signature> signatures;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
if (Archive::is_deserializer)
|
||||
set_hash_valid(false);
|
||||
|
||||
FIELDS(static_cast<block_header&>(*this))
|
||||
FIELD(miner_tx)
|
||||
FIELD(tx_hashes)
|
||||
if (tx_hashes.size() > CRYPTONOTE_MAX_TX_PER_BLOCK)
|
||||
throw std::invalid_argument{"too many txs in block"};
|
||||
if (major_version >= cryptonote::network_version_16_pulse)
|
||||
FIELD(signatures)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
template <class Archive>
|
||||
void serialize_value(Archive& ar, block_header& b) {
|
||||
using namespace serialization;
|
||||
field(ar, "major_version", b.major_version);
|
||||
field_varint(ar, "minor_version", b.minor_version);
|
||||
field_varint(ar, "timestamp", b.timestamp);
|
||||
field(ar, "prev_id", b.prev_id);
|
||||
field(ar, "nonce", b.nonce);
|
||||
if (b.major_version >= hf::hf16_pulse)
|
||||
field(ar, "pulse", b.pulse);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize_value(Archive& ar, block& b) {
|
||||
auto _obj = ar.begin_object();
|
||||
if constexpr (Archive::is_deserializer)
|
||||
b.set_hash_valid(false);
|
||||
|
||||
serialization::value(ar, static_cast<block_header&>(b));
|
||||
field(ar, "miner_tx", b.miner_tx);
|
||||
field(ar, "tx_hashes", b.tx_hashes);
|
||||
if (b.tx_hashes.size() > MAX_TX_PER_BLOCK)
|
||||
throw std::invalid_argument{"too many txs in block"};
|
||||
if (b.major_version >= hf::hf16_pulse)
|
||||
field(ar, "signatures", b.signatures);
|
||||
if (b.major_version >= hf::hf19_reward_batching)
|
||||
{
|
||||
field_varint(ar, "height", b.height);
|
||||
field(ar, "service_node_winner_key", b.service_node_winner_key);
|
||||
field(ar, "reward", b.reward);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
|
@ -478,6 +493,10 @@ namespace cryptonote
|
|||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
uint64_t modulus(uint64_t interval) const;
|
||||
uint64_t next_payout_height(uint64_t current_height, uint64_t interval) const;
|
||||
|
||||
};
|
||||
inline constexpr account_public_address null_address{};
|
||||
|
||||
|
@ -503,9 +522,9 @@ namespace cryptonote
|
|||
using byte_and_output_fees = std::pair<uint64_t, uint64_t>;
|
||||
|
||||
//---------------------------------------------------------------
|
||||
constexpr txversion transaction_prefix::get_min_version_for_hf(uint8_t hf_version)
|
||||
constexpr txversion transaction_prefix::get_min_version_for_hf(hf hf_version)
|
||||
{
|
||||
if (hf_version >= cryptonote::network_version_7 && hf_version <= cryptonote::network_version_10_bulletproofs)
|
||||
if (hf_version >= hf::hf7 && hf_version <= hf::hf10_bulletproofs)
|
||||
return txversion::v2_ringct;
|
||||
return txversion::v4_tx_types;
|
||||
}
|
||||
|
@ -514,26 +533,26 @@ namespace cryptonote
|
|||
// tests can still use particular hard forks without needing to actually generate pre-v4 txes.
|
||||
namespace hack { inline bool test_suite_permissive_txes = false; }
|
||||
|
||||
inline txversion transaction_prefix::get_max_version_for_hf(uint8_t hf_version)
|
||||
inline txversion transaction_prefix::get_max_version_for_hf(hf hf_version)
|
||||
{
|
||||
if (!hack::test_suite_permissive_txes) {
|
||||
if (hf_version >= cryptonote::network_version_7 && hf_version <= cryptonote::network_version_8)
|
||||
if (hf_version >= hf::hf7 && hf_version <= hf::hf8)
|
||||
return txversion::v2_ringct;
|
||||
|
||||
if (hf_version >= cryptonote::network_version_9_service_nodes && hf_version <= cryptonote::network_version_10_bulletproofs)
|
||||
if (hf_version >= hf::hf9_service_nodes && hf_version <= hf::hf10_bulletproofs)
|
||||
return txversion::v3_per_output_unlock_times;
|
||||
}
|
||||
|
||||
return txversion::v4_tx_types;
|
||||
}
|
||||
|
||||
constexpr txtype transaction_prefix::get_max_type_for_hf(uint8_t hf_version)
|
||||
constexpr txtype transaction_prefix::get_max_type_for_hf(hf hf_version)
|
||||
{
|
||||
txtype result = txtype::standard;
|
||||
if (hf_version >= network_version_15_ons) result = txtype::oxen_name_system;
|
||||
else if (hf_version >= network_version_14_blink) result = txtype::stake;
|
||||
else if (hf_version >= network_version_11_infinite_staking) result = txtype::key_image_unlock;
|
||||
else if (hf_version >= network_version_9_service_nodes) result = txtype::state_change;
|
||||
if (hf_version >= hf::hf15_ons) result = txtype::oxen_name_system;
|
||||
else if (hf_version >= hf::hf14_blink) result = txtype::stake;
|
||||
else if (hf_version >= hf::hf11_infinite_staking) result = txtype::key_image_unlock;
|
||||
else if (hf_version >= hf::hf9_service_nodes) result = txtype::state_change;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -563,12 +582,25 @@ namespace cryptonote
|
|||
}
|
||||
}
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &os, txtype t) {
|
||||
inline std::ostream& operator<<(std::ostream& os, txtype t) {
|
||||
return os << transaction::type_to_string(t);
|
||||
}
|
||||
inline std::ostream &operator<<(std::ostream &os, txversion v) {
|
||||
inline std::ostream& operator<<(std::ostream& os, txversion v) {
|
||||
return os << transaction::version_to_string(v);
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, hf v) = delete;/*{
|
||||
return os << "HF" << static_cast<int>(v);
|
||||
}*/
|
||||
|
||||
// Serialization for the `hf` type; this is simply writing/reading the underlying uint8_t value
|
||||
template <class Archive>
|
||||
void serialize_value(Archive& ar, hf& x) {
|
||||
auto val = static_cast<std::underlying_type_t<hf>>(x);
|
||||
serialization::value(ar, val);
|
||||
if constexpr (Archive::is_deserializer)
|
||||
x = static_cast<hf>(val);
|
||||
}
|
||||
}
|
||||
|
||||
namespace std {
|
||||
|
|
|
@ -35,11 +35,9 @@
|
|||
#include "serialization/container.h"
|
||||
#include "cryptonote_format_utils.h"
|
||||
#include "cryptonote_config.h"
|
||||
#include "epee/misc_language.h"
|
||||
#include "common/base58.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "epee/int-util.h"
|
||||
#include "common/dns_utils.h"
|
||||
#include "common/oxen.h"
|
||||
#include <cfenv>
|
||||
|
||||
|
@ -67,38 +65,33 @@ namespace cryptonote {
|
|||
constexpr cryptonote::pulse_random_value empty_random_value = {};
|
||||
bool bitset = blk_header.pulse.validator_bitset > 0;
|
||||
bool random_value = !(blk_header.pulse.random_value == empty_random_value);
|
||||
uint8_t hf_version = blk_header.major_version;
|
||||
bool result = hf_version >= cryptonote::network_version_16_pulse && (bitset || random_value);
|
||||
auto hf_version = blk_header.major_version;
|
||||
bool result = hf_version >= hf::hf16_pulse && (bitset || random_value);
|
||||
return result;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool block_has_pulse_components(block const &blk)
|
||||
{
|
||||
bool signatures = blk.signatures.size();
|
||||
uint8_t hf_version = blk.major_version;
|
||||
bool signatures = blk.signatures.size();
|
||||
auto hf_version = blk.major_version;
|
||||
bool result =
|
||||
(hf_version >= cryptonote::network_version_16_pulse && signatures) || block_header_has_pulse_components(blk);
|
||||
(hf_version >= hf::hf16_pulse && signatures) || block_header_has_pulse_components(blk);
|
||||
return result;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
size_t get_min_block_weight(uint8_t version)
|
||||
size_t get_min_block_weight(hf version)
|
||||
{
|
||||
return CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
size_t get_max_tx_size()
|
||||
{
|
||||
return CRYPTONOTE_MAX_TX_SIZE;
|
||||
return BLOCK_GRANTED_FULL_REWARD_ZONE_V5;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
// TODO(oxen): Move into oxen_economy, this will require access to oxen::exp2
|
||||
uint64_t block_reward_unpenalized_formula_v7(uint64_t already_generated_coins, uint64_t height)
|
||||
{
|
||||
uint64_t emission_supply_component = (already_generated_coins * EMISSION_SUPPLY_MULTIPLIER) / EMISSION_SUPPLY_DIVISOR;
|
||||
uint64_t result = (EMISSION_LINEAR_BASE - emission_supply_component) / EMISSION_DIVISOR;
|
||||
uint64_t emission_supply_component = (already_generated_coins * oxen::EMISSION_SUPPLY_MULTIPLIER) / oxen::EMISSION_SUPPLY_DIVISOR;
|
||||
uint64_t result = (oxen::EMISSION_LINEAR_BASE - emission_supply_component) / oxen::EMISSION_DIVISOR;
|
||||
|
||||
// Check if we just overflowed
|
||||
if (emission_supply_component > EMISSION_LINEAR_BASE)
|
||||
if (emission_supply_component > oxen::EMISSION_LINEAR_BASE)
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
@ -110,21 +103,21 @@ namespace cryptonote {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool get_base_block_reward(size_t median_weight, size_t current_block_weight, uint64_t already_generated_coins, uint64_t &reward, uint64_t &reward_unpenalized, uint8_t version, uint64_t height) {
|
||||
bool get_base_block_reward(size_t median_weight, size_t current_block_weight, uint64_t already_generated_coins, uint64_t &reward, uint64_t &reward_unpenalized, hf version, uint64_t height) {
|
||||
|
||||
//premine reward
|
||||
if (already_generated_coins == 0)
|
||||
{
|
||||
reward = 22'500'000 * COIN;
|
||||
reward = 22'500'000 * oxen::COIN;
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert((TARGET_BLOCK_TIME % 1min) == 0s, "difficulty targets must be a multiple of a minute");
|
||||
|
||||
uint64_t base_reward =
|
||||
version >= network_version_17 ? BLOCK_REWARD_HF17 :
|
||||
version >= network_version_15_ons ? BLOCK_REWARD_HF15 :
|
||||
version >= network_version_8 ? block_reward_unpenalized_formula_v8(height) :
|
||||
version >= hf::hf17 ? oxen::BLOCK_REWARD_HF17 :
|
||||
version >= hf::hf15_ons ? oxen::BLOCK_REWARD_HF15 :
|
||||
version >= hf::hf8 ? block_reward_unpenalized_formula_v8(height) :
|
||||
block_reward_unpenalized_formula_v7(already_generated_coins, height);
|
||||
|
||||
uint64_t full_reward_zone = get_min_block_weight(version);
|
||||
|
@ -166,6 +159,17 @@ namespace cryptonote {
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
batch_sn_payment::batch_sn_payment(std::string addr, uint64_t amt, cryptonote::network_type nettype):address(addr),amount(amt){
|
||||
cryptonote::get_account_address_from_str(address_info, nettype, address);
|
||||
};
|
||||
batch_sn_payment::batch_sn_payment(cryptonote::address_parse_info& addr_info, uint64_t amt, cryptonote::network_type nettype):address_info(addr_info),amount(amt){
|
||||
address = cryptonote::get_account_address_as_str(nettype, address_info.is_subaddress, address_info.address);
|
||||
};
|
||||
batch_sn_payment::batch_sn_payment(const cryptonote::account_public_address& addr, uint64_t amt, cryptonote::network_type nettype):amount(amt){
|
||||
address_info = cryptonote::address_parse_info{addr,0};
|
||||
address = cryptonote::get_account_address_as_str(nettype, address_info.is_subaddress, address_info.address);
|
||||
};
|
||||
//------------------------------------------------------------------------------------
|
||||
uint8_t get_account_address_checksum(const public_address_outer_blob& bl)
|
||||
{
|
||||
const unsigned char* pbuf = reinterpret_cast<const unsigned char*>(&bl);
|
||||
|
@ -192,7 +196,8 @@ namespace cryptonote {
|
|||
, account_public_address const & adr
|
||||
)
|
||||
{
|
||||
uint64_t address_prefix = subaddress ? get_config(nettype).CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : get_config(nettype).CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX;
|
||||
auto& conf = get_config(nettype);
|
||||
uint64_t address_prefix = subaddress ? conf.PUBLIC_SUBADDRESS_BASE58_PREFIX : conf.PUBLIC_ADDRESS_BASE58_PREFIX;
|
||||
|
||||
return tools::base58::encode_addr(address_prefix, t_serializable_object_to_blob(adr));
|
||||
}
|
||||
|
@ -203,7 +208,7 @@ namespace cryptonote {
|
|||
, crypto::hash8 const & payment_id
|
||||
)
|
||||
{
|
||||
uint64_t integrated_address_prefix = get_config(nettype).CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
|
||||
uint64_t integrated_address_prefix = get_config(nettype).PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
|
||||
|
||||
integrated_address iadr = {
|
||||
adr, payment_id
|
||||
|
@ -222,11 +227,12 @@ namespace cryptonote {
|
|||
, const std::string_view str
|
||||
)
|
||||
{
|
||||
uint64_t address_prefix = get_config(nettype).CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX;
|
||||
uint64_t integrated_address_prefix = get_config(nettype).CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
|
||||
uint64_t subaddress_prefix = get_config(nettype).CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX;
|
||||
auto& conf = get_config(nettype);
|
||||
uint64_t address_prefix = conf.PUBLIC_ADDRESS_BASE58_PREFIX;
|
||||
uint64_t integrated_address_prefix = conf.PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
|
||||
uint64_t subaddress_prefix = conf.PUBLIC_SUBADDRESS_BASE58_PREFIX;
|
||||
|
||||
blobdata data;
|
||||
std::string data;
|
||||
uint64_t prefix{0};
|
||||
if (!tools::base58::decode_addr(str, prefix, data))
|
||||
{
|
||||
|
@ -282,21 +288,6 @@ namespace cryptonote {
|
|||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
bool get_account_address_from_str_or_url(
|
||||
address_parse_info& info
|
||||
, network_type nettype
|
||||
, const std::string_view str_or_url
|
||||
, std::function<std::string(const std::string_view, const std::vector<std::string>&, bool)> dns_confirm
|
||||
)
|
||||
{
|
||||
if (get_account_address_from_str(info, nettype, str_or_url))
|
||||
return true;
|
||||
bool dnssec_valid;
|
||||
std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(str_or_url, dnssec_valid, dns_confirm);
|
||||
return !address_str.empty() &&
|
||||
get_account_address_from_str(info, nettype, address_str);
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
bool operator ==(const cryptonote::transaction& a, const cryptonote::transaction& b) {
|
||||
return cryptonote::get_transaction_hash(a) == cryptonote::get_transaction_hash(b);
|
||||
}
|
||||
|
|
|
@ -54,10 +54,32 @@ namespace cryptonote {
|
|||
virtual void init() = 0;
|
||||
};
|
||||
|
||||
struct address_parse_info
|
||||
{
|
||||
account_public_address address;
|
||||
bool is_subaddress;
|
||||
bool has_payment_id;
|
||||
crypto::hash8 payment_id;
|
||||
|
||||
std::string as_str(network_type nettype) const;
|
||||
|
||||
KV_MAP_SERIALIZABLE
|
||||
};
|
||||
|
||||
struct batch_sn_payment {
|
||||
std::string address;
|
||||
cryptonote::address_parse_info address_info;
|
||||
uint64_t amount;
|
||||
batch_sn_payment() = default;
|
||||
batch_sn_payment(std::string addr, uint64_t amt, cryptonote::network_type nettype);
|
||||
batch_sn_payment(cryptonote::address_parse_info& addr_info, uint64_t amt, cryptonote::network_type nettype);
|
||||
batch_sn_payment(const cryptonote::account_public_address& addr, uint64_t amt, cryptonote::network_type nettype);
|
||||
};
|
||||
|
||||
class ValidateMinerTxHook
|
||||
{
|
||||
public:
|
||||
virtual bool validate_miner_tx(cryptonote::block const &block, struct block_reward_parts const &reward_parts) const = 0;
|
||||
virtual bool validate_miner_tx(cryptonote::block const &block, struct block_reward_parts const &reward_parts, std::optional<std::vector<cryptonote::batch_sn_payment>> const &batched_sn_payments) const = 0;
|
||||
};
|
||||
|
||||
class AltBlockAddedHook
|
||||
|
@ -89,28 +111,17 @@ namespace cryptonote {
|
|||
return addresses[0];
|
||||
}
|
||||
|
||||
struct address_parse_info
|
||||
{
|
||||
account_public_address address;
|
||||
bool is_subaddress;
|
||||
bool has_payment_id;
|
||||
crypto::hash8 payment_id;
|
||||
|
||||
std::string as_str(network_type nettype) const;
|
||||
|
||||
KV_MAP_SERIALIZABLE
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* Cryptonote helper functions */
|
||||
/************************************************************************/
|
||||
bool block_header_has_pulse_components(block_header const &blk_header);
|
||||
bool block_has_pulse_components(block const &blk);
|
||||
size_t get_min_block_weight(uint8_t version);
|
||||
size_t get_max_tx_size();
|
||||
size_t get_min_block_weight(hf version);
|
||||
uint64_t block_reward_unpenalized_formula_v7(uint64_t already_generated_coins, uint64_t height);
|
||||
uint64_t block_reward_unpenalized_formula_v8(uint64_t height);
|
||||
bool get_base_block_reward(size_t median_weight, size_t current_block_weight, uint64_t already_generated_coins, uint64_t &reward, uint64_t &reward_unpenalized, uint8_t version, uint64_t height);
|
||||
bool get_base_block_reward(size_t median_weight, size_t current_block_weight, uint64_t already_generated_coins, uint64_t &reward, uint64_t &reward_unpenalized, hf version, uint64_t height);
|
||||
uint8_t get_account_address_checksum(const public_address_outer_blob& bl);
|
||||
uint8_t get_account_integrated_address_checksum(const public_integrated_address_outer_blob& bl);
|
||||
|
||||
|
@ -140,13 +151,6 @@ namespace cryptonote {
|
|||
, const std::string_view str
|
||||
);
|
||||
|
||||
bool get_account_address_from_str_or_url(
|
||||
address_parse_info& info
|
||||
, network_type nettype
|
||||
, const std::string_view str_or_url
|
||||
, std::function<std::string(const std::string_view, const std::vector<std::string>&, bool)> dns_confirm = return_first_address
|
||||
);
|
||||
|
||||
bool is_coinbase(const transaction& tx);
|
||||
|
||||
bool operator ==(const cryptonote::transaction& a, const cryptonote::transaction& b);
|
||||
|
|
|
@ -215,6 +215,11 @@ namespace boost
|
|||
//------------------
|
||||
a & b.miner_tx;
|
||||
a & b.tx_hashes;
|
||||
if (ver < 19)
|
||||
return;
|
||||
a & b.height;
|
||||
a & b.service_node_winner_key;
|
||||
a & b.reward;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
|
|
|
@ -32,9 +32,10 @@
|
|||
#include <atomic>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <limits>
|
||||
#include <oxenmq/hex.h>
|
||||
#include <oxenc/hex.h>
|
||||
#include <variant>
|
||||
#include "common/hex.h"
|
||||
#include "cryptonote_core/service_node_list.h"
|
||||
#include "epee/wipeable_string.h"
|
||||
#include "epee/string_tools.h"
|
||||
#include "common/i18n.h"
|
||||
|
@ -91,7 +92,7 @@ namespace cryptonote
|
|||
++nlr;
|
||||
nlr += 6;
|
||||
const size_t bp_size = 32 * (9 + 2 * nlr);
|
||||
CHECK_AND_ASSERT_THROW_MES_L1(n_outputs <= BULLETPROOF_MAX_OUTPUTS, "maximum number of outputs is " + std::to_string(BULLETPROOF_MAX_OUTPUTS) + " per transaction");
|
||||
CHECK_AND_ASSERT_THROW_MES_L1(n_outputs <= TX_BULLETPROOF_MAX_OUTPUTS, "maximum number of outputs is " + std::to_string(TX_BULLETPROOF_MAX_OUTPUTS) + " per transaction");
|
||||
CHECK_AND_ASSERT_THROW_MES_L1(bp_base * n_padded_outputs >= bp_size, "Invalid bulletproof clawback: bp_base " + std::to_string(bp_base) + ", n_padded_outputs "
|
||||
+ std::to_string(n_padded_outputs) + ", bp_size " + std::to_string(bp_size));
|
||||
const uint64_t bp_clawback = (bp_base * n_padded_outputs - bp_size) * 4 / 5;
|
||||
|
@ -353,80 +354,65 @@ namespace cryptonote
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
uint64_t power_integral(uint64_t a, uint64_t b)
|
||||
{
|
||||
if(b == 0)
|
||||
return 1;
|
||||
uint64_t total = a;
|
||||
for(uint64_t i = 1; i != b; i++)
|
||||
total *= a;
|
||||
return total;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool parse_amount(uint64_t& amount, std::string_view str_amount)
|
||||
std::optional<uint64_t> parse_amount(std::string_view str_amount)
|
||||
{
|
||||
uint64_t amount;
|
||||
tools::trim(str_amount);
|
||||
|
||||
auto parts = tools::split(str_amount, "."sv);
|
||||
if (parts.size() > 2)
|
||||
return false; // 123.456.789 no thanks.
|
||||
return std::nullopt; // 123.456.789 no thanks.
|
||||
|
||||
if (parts.size() == 2 && parts[1].empty())
|
||||
parts.pop_back(); // allow "123." (treat it as as "123")
|
||||
|
||||
if (parts[0].find_first_not_of("0123456789"sv) != std::string::npos)
|
||||
return false; // whole part contains non-digit
|
||||
return std::nullopt; // whole part contains non-digit
|
||||
|
||||
if (parts[0].empty()) {
|
||||
// Only allow an empty whole number part if there is a fractional part.
|
||||
if (parts.size() == 1)
|
||||
return false;
|
||||
return std::nullopt;
|
||||
amount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!tools::parse_int(parts[0], amount))
|
||||
return false;
|
||||
return std::nullopt;
|
||||
|
||||
// Scale up the number (e.g. 12 from "12.45") to atomic units.
|
||||
//
|
||||
// TODO: get rid of the user-configurable default_decimal_point nonsense and just multiply
|
||||
// this value by the `COIN` constant.
|
||||
for (size_t i = 0; i < CRYPTONOTE_DISPLAY_DECIMAL_POINT; i++)
|
||||
{
|
||||
if (amount > std::numeric_limits<uint64_t>::max() / 10)
|
||||
return false; // would overflow
|
||||
amount *= 10;
|
||||
}
|
||||
if (amount > std::numeric_limits<uint64_t>::max() / oxen::COIN)
|
||||
return std::nullopt; // would overflow
|
||||
amount *= oxen::COIN;
|
||||
}
|
||||
|
||||
if (parts.size() == 1)
|
||||
return true;
|
||||
return amount;
|
||||
|
||||
if (parts[1].find_first_not_of("0123456789"sv) != std::string::npos)
|
||||
return false; // fractional part contains non-digit
|
||||
return std::nullopt; // fractional part contains non-digit
|
||||
|
||||
// If too long, but with insignificant 0's, trim them off
|
||||
while (parts[1].size() > CRYPTONOTE_DISPLAY_DECIMAL_POINT && parts[1].back() == '0')
|
||||
while (parts[1].size() > oxen::DISPLAY_DECIMAL_POINT && parts[1].back() == '0')
|
||||
parts[1].remove_suffix(1);
|
||||
|
||||
if (parts[1].size() > CRYPTONOTE_DISPLAY_DECIMAL_POINT)
|
||||
return false; // fractional part has too many significant digits
|
||||
if (parts[1].size() > oxen::DISPLAY_DECIMAL_POINT)
|
||||
return std::nullopt; // fractional part has too many significant digits
|
||||
|
||||
uint64_t fractional;
|
||||
if (!tools::parse_int(parts[1], fractional))
|
||||
return false;
|
||||
return std::nullopt;
|
||||
|
||||
// Scale up the value if it wasn't a full fractional value, e.g. if we have "10.45" then we
|
||||
// need to convert the 45 we just parsed to 450'000'000.
|
||||
for (size_t i = parts[1].size(); i < CRYPTONOTE_DISPLAY_DECIMAL_POINT; i++)
|
||||
for (size_t i = parts[1].size(); i < oxen::DISPLAY_DECIMAL_POINT; i++)
|
||||
fractional *= 10;
|
||||
|
||||
if (fractional > std::numeric_limits<uint64_t>::max() - amount)
|
||||
return false; // would overflow
|
||||
return std::nullopt; // would overflow
|
||||
|
||||
amount += fractional;
|
||||
return true;
|
||||
return amount;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
|
||||
|
@ -541,7 +527,7 @@ namespace cryptonote
|
|||
try {
|
||||
serialization::deserialize_all(ar, tx_extra_fields);
|
||||
} catch (const std::exception& e) {
|
||||
MWARNING(__func__ << ": failed to deserialize extra field: " << e.what() << "; extra = " << oxenmq::to_hex(tx_extra.begin(), tx_extra.end()));
|
||||
MWARNING(__func__ << ": failed to deserialize extra field: " << e.what() << "; extra = " << oxenc::to_hex(tx_extra.begin(), tx_extra.end()));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -627,7 +613,7 @@ namespace cryptonote
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool add_extra_nonce_to_tx_extra(std::vector<uint8_t>& tx_extra, const blobdata& extra_nonce)
|
||||
bool add_extra_nonce_to_tx_extra(std::vector<uint8_t>& tx_extra, const std::string& extra_nonce)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(extra_nonce.size() <= TX_EXTRA_NONCE_MAX_COUNT, false, "extra nonce could be 255 bytes max");
|
||||
tx_extra.reserve(tx_extra.size() + 2 + extra_nonce.size());
|
||||
|
@ -637,10 +623,10 @@ namespace cryptonote
|
|||
return true;
|
||||
}
|
||||
|
||||
bool add_service_node_state_change_to_tx_extra(std::vector<uint8_t>& tx_extra, const tx_extra_service_node_state_change& state_change, const uint8_t hf_version)
|
||||
bool add_service_node_state_change_to_tx_extra(std::vector<uint8_t>& tx_extra, const tx_extra_service_node_state_change& state_change, const hf hf_version)
|
||||
{
|
||||
tx_extra_field field;
|
||||
if (hf_version < network_version_12_checkpointing)
|
||||
if (hf_version < hf::hf12_checkpointing)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(state_change.state == service_nodes::new_state::deregister, false, "internal error: cannot construct an old deregistration for a non-deregistration state change (before hardfork v12)");
|
||||
field = tx_extra_service_node_deregister_old{state_change};
|
||||
|
@ -715,36 +701,22 @@ namespace cryptonote
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool add_service_node_register_to_tx_extra(
|
||||
std::vector<uint8_t>& tx_extra,
|
||||
const std::vector<cryptonote::account_public_address>& addresses,
|
||||
uint64_t portions_for_operator,
|
||||
const std::vector<uint64_t>& portions,
|
||||
uint64_t expiration_timestamp,
|
||||
const crypto::signature& service_node_signature)
|
||||
bool add_service_node_registration_to_tx_extra(std::vector<uint8_t>& tx_extra, const service_nodes::registration_details& reg)
|
||||
{
|
||||
if (addresses.size() != portions.size())
|
||||
tx_extra_field field;
|
||||
auto& txreg = field.emplace<tx_extra_service_node_register>();
|
||||
txreg.amounts.reserve(reg.reserved.size());
|
||||
txreg.public_spend_keys.reserve(reg.reserved.size());
|
||||
txreg.public_view_keys.reserve(reg.reserved.size());
|
||||
for (const auto& [addr, amount] : reg.reserved)
|
||||
{
|
||||
LOG_ERROR("Tried to serialize registration with more addresses than portions, this should never happen");
|
||||
return false;
|
||||
txreg.public_spend_keys.push_back(addr.m_spend_public_key);
|
||||
txreg.public_view_keys.push_back(addr.m_view_public_key);
|
||||
txreg.amounts.push_back(amount);
|
||||
}
|
||||
std::vector<crypto::public_key> public_view_keys(addresses.size());
|
||||
std::vector<crypto::public_key> public_spend_keys(addresses.size());
|
||||
for (size_t i = 0; i < addresses.size(); i++)
|
||||
{
|
||||
public_view_keys[i] = addresses[i].m_view_public_key;
|
||||
public_spend_keys[i] = addresses[i].m_spend_public_key;
|
||||
}
|
||||
// convert to variant
|
||||
tx_extra_field field =
|
||||
tx_extra_service_node_register{
|
||||
public_spend_keys,
|
||||
public_view_keys,
|
||||
portions_for_operator,
|
||||
portions,
|
||||
expiration_timestamp,
|
||||
service_node_signature
|
||||
};
|
||||
txreg.fee = reg.fee;
|
||||
txreg.hf_or_expiration = reg.hf;
|
||||
txreg.signature = reg.signature;
|
||||
|
||||
bool r = add_tx_extra_field_to_tx_extra(tx_extra, field);
|
||||
CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to serialize tx extra registration tx");
|
||||
|
@ -756,9 +728,9 @@ namespace cryptonote
|
|||
add_tx_extra<tx_extra_service_node_winner>(tx_extra, winner);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_service_node_state_change_from_tx_extra(const std::vector<uint8_t>& tx_extra, tx_extra_service_node_state_change &state_change, const uint8_t hf_version)
|
||||
bool get_service_node_state_change_from_tx_extra(const std::vector<uint8_t>& tx_extra, tx_extra_service_node_state_change &state_change, const hf hf_version)
|
||||
{
|
||||
if (hf_version >= cryptonote::network_version_12_checkpointing) {
|
||||
if (hf_version >= hf::hf12_checkpointing) {
|
||||
// Look for a new-style state change field:
|
||||
return get_field_from_tx_extra(tx_extra, state_change);
|
||||
}
|
||||
|
@ -807,7 +779,7 @@ namespace cryptonote
|
|||
value(newar, field);
|
||||
} while (ar.remaining_bytes() > 0);
|
||||
} catch (const std::exception& e) {
|
||||
LOG_PRINT_L1(__func__ << ": failed to deserialize extra field: " << e.what() << "; extra = " << oxenmq::to_hex(tx_extra.begin(), tx_extra.end()));
|
||||
LOG_PRINT_L1(__func__ << ": failed to deserialize extra field: " << e.what() << "; extra = " << oxenc::to_hex(tx_extra.begin(), tx_extra.end()));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -818,7 +790,7 @@ namespace cryptonote
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
void set_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash& payment_id)
|
||||
void set_payment_id_to_tx_extra_nonce(std::string& extra_nonce, const crypto::hash& payment_id)
|
||||
{
|
||||
extra_nonce.clear();
|
||||
extra_nonce.push_back(TX_EXTRA_NONCE_PAYMENT_ID);
|
||||
|
@ -826,7 +798,7 @@ namespace cryptonote
|
|||
std::copy(payment_id_ptr, payment_id_ptr + sizeof(payment_id), std::back_inserter(extra_nonce));
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
void set_encrypted_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash8& payment_id)
|
||||
void set_encrypted_payment_id_to_tx_extra_nonce(std::string& extra_nonce, const crypto::hash8& payment_id)
|
||||
{
|
||||
extra_nonce.clear();
|
||||
extra_nonce.push_back(TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID);
|
||||
|
@ -834,7 +806,7 @@ namespace cryptonote
|
|||
std::copy(payment_id_ptr, payment_id_ptr + sizeof(payment_id), std::back_inserter(extra_nonce));
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id)
|
||||
bool get_payment_id_from_tx_extra_nonce(const std::string& extra_nonce, crypto::hash& payment_id)
|
||||
{
|
||||
if(sizeof(crypto::hash) + 1 != extra_nonce.size())
|
||||
return false;
|
||||
|
@ -844,7 +816,7 @@ namespace cryptonote
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash8& payment_id)
|
||||
bool get_encrypted_payment_id_from_tx_extra_nonce(const std::string& extra_nonce, crypto::hash8& payment_id)
|
||||
{
|
||||
if(sizeof(crypto::hash8) + 1 != extra_nonce.size())
|
||||
return false;
|
||||
|
@ -883,9 +855,19 @@ namespace cryptonote
|
|||
//---------------------------------------------------------------
|
||||
uint64_t get_block_height(const block& b)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, 0, "wrong miner tx in block: " << get_block_hash(b) << ", b.miner_tx.vin.size() != 1 (size is: " << b.miner_tx.vin.size() << ")");
|
||||
CHECKED_GET_SPECIFIC_VARIANT(b.miner_tx.vin[0], txin_gen, coinbase_in, 0);
|
||||
return coinbase_in.height;
|
||||
cryptonote::block bl = b;
|
||||
if (b.miner_tx.vout.size() > 0)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, 0, "wrong miner tx in block: " << get_block_hash(b) << ", b.miner_tx.vin.size() != 1 (size is: " << b.miner_tx.vin.size() << ")");
|
||||
CHECKED_GET_SPECIFIC_VARIANT(b.miner_tx.vin[0], txin_gen, coinbase_in, 0);
|
||||
if (b.major_version >= hf::hf19_reward_batching)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(coinbase_in.height == b.height, 0, "wrong miner tx in block: " << get_block_hash(b));
|
||||
}
|
||||
return coinbase_in.height;
|
||||
} else {
|
||||
return b.height;
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool check_inputs_types_supported(const transaction& tx)
|
||||
|
@ -895,7 +877,6 @@ namespace cryptonote
|
|||
CHECK_AND_ASSERT_MES(std::holds_alternative<txin_to_key>(in), false, "wrong variant type: "
|
||||
<< tools::type_name(tools::variant_type(in)) << ", expected " << tools::type_name<txin_to_key>()
|
||||
<< ", in transaction id=" << get_transaction_hash(tx));
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -969,7 +950,7 @@ namespace cryptonote
|
|||
//---------------------------------------------------------------
|
||||
std::string short_hash_str(const crypto::hash& h)
|
||||
{
|
||||
return oxenmq::to_hex(tools::view_guts(h).substr(0, 4)) + "....";
|
||||
return oxenc::to_hex(tools::view_guts(h).substr(0, 4)) + "....";
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_pub_keys, size_t output_index)
|
||||
|
@ -1047,13 +1028,17 @@ namespace cryptonote
|
|||
cn_fast_hash(blob.data(), blob.size(), res);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
std::string print_money(uint64_t amount, bool trim_insignificant)
|
||||
std::string print_money(uint64_t amount, bool strip_zeros)
|
||||
{
|
||||
std::string s = tools::int_to_string(amount);
|
||||
if (s.size() <= CRYPTONOTE_DISPLAY_DECIMAL_POINT)
|
||||
s.insert(0, CRYPTONOTE_DISPLAY_DECIMAL_POINT - s.size() + 1, '0');
|
||||
s.insert(s.size() - CRYPTONOTE_DISPLAY_DECIMAL_POINT, ".");
|
||||
if (trim_insignificant) {
|
||||
constexpr unsigned int decimal_point = oxen::DISPLAY_DECIMAL_POINT;
|
||||
std::string s = std::to_string(amount);
|
||||
if(s.size() < decimal_point+1)
|
||||
{
|
||||
s.insert(0, decimal_point+1 - s.size(), '0');
|
||||
}
|
||||
s.insert(s.size() - decimal_point, ".");
|
||||
if (strip_zeros)
|
||||
{
|
||||
while (s.back() == '0')
|
||||
s.pop_back();
|
||||
if (s.back() == '.')
|
||||
|
@ -1062,6 +1047,14 @@ namespace cryptonote
|
|||
return s;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
std::string format_money(uint64_t amount, bool strip_zeros)
|
||||
{
|
||||
auto value = print_money(amount, strip_zeros);
|
||||
value += ' ';
|
||||
value += get_unit();
|
||||
return value;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
std::string print_tx_verification_context(tx_verification_context const &tvc, transaction const *tx)
|
||||
{
|
||||
std::ostringstream os;
|
||||
|
@ -1189,7 +1182,7 @@ namespace cryptonote
|
|||
return get_transaction_hash(t, res, NULL);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
[[nodiscard]] bool calculate_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blob, crypto::hash& res)
|
||||
[[nodiscard]] bool calculate_transaction_prunable_hash(const transaction& t, const std::string *blob, crypto::hash& res)
|
||||
{
|
||||
if (t.version == txversion::v1)
|
||||
return false;
|
||||
|
@ -1217,7 +1210,7 @@ namespace cryptonote
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::hash get_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blobdata)
|
||||
crypto::hash get_transaction_prunable_hash(const transaction& t, const std::string* blobdata)
|
||||
{
|
||||
crypto::hash res;
|
||||
CHECK_AND_ASSERT_THROW_MES(calculate_transaction_prunable_hash(t, blobdata, res), "Failed to calculate tx prunable hash");
|
||||
|
@ -1273,7 +1266,7 @@ namespace cryptonote
|
|||
// prefix
|
||||
get_transaction_prefix_hash(t, hashes[0]);
|
||||
|
||||
const blobdata blob = tx_to_blob(t);
|
||||
const std::string blob = tx_to_blob(t);
|
||||
CHECK_AND_ASSERT_MES(!blob.empty(), false, "Failed to convert tx to blob");
|
||||
|
||||
// TODO(oxen): Not sure if this is the right fix, we may just want to set
|
||||
|
@ -1330,38 +1323,6 @@ namespace cryptonote
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_registration_hash(const std::vector<cryptonote::account_public_address>& addresses, uint64_t operator_portions, const std::vector<uint64_t>& portions, uint64_t expiration_timestamp, crypto::hash& hash)
|
||||
{
|
||||
if (addresses.size() != portions.size())
|
||||
{
|
||||
LOG_ERROR("get_registration_hash addresses.size() != portions.size()");
|
||||
return false;
|
||||
}
|
||||
uint64_t portions_left = STAKING_PORTIONS;
|
||||
for (uint64_t portion : portions)
|
||||
{
|
||||
if (portion > portions_left)
|
||||
{
|
||||
LOG_ERROR(tr("Your registration has more than ") << STAKING_PORTIONS << tr(" portions, this registration is invalid!"));
|
||||
return false;
|
||||
}
|
||||
portions_left -= portion;
|
||||
}
|
||||
size_t size = sizeof(uint64_t) + addresses.size() * (sizeof(cryptonote::account_public_address) + sizeof(uint64_t)) + sizeof(uint64_t);
|
||||
std::string buffer;
|
||||
buffer.reserve(size);
|
||||
buffer += tools::view_guts(operator_portions);
|
||||
for (size_t i = 0; i < addresses.size(); i++)
|
||||
{
|
||||
buffer += tools::view_guts(addresses[i]);
|
||||
buffer += tools::view_guts(portions[i]);
|
||||
}
|
||||
buffer += tools::view_guts(expiration_timestamp);
|
||||
assert(buffer.size() == size);
|
||||
crypto::cn_fast_hash(buffer.data(), buffer.size(), hash);
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size)
|
||||
{
|
||||
if (t.is_hash_valid())
|
||||
|
@ -1396,9 +1357,9 @@ namespace cryptonote
|
|||
return get_transaction_hash(t, res, &blob_size);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
blobdata get_block_hashing_blob(const block& b)
|
||||
std::string get_block_hashing_blob(const block& b)
|
||||
{
|
||||
blobdata blob = t_serializable_object_to_blob(static_cast<block_header>(b));
|
||||
std::string blob = t_serializable_object_to_blob(static_cast<block_header>(b));
|
||||
crypto::hash tree_root_hash = get_tx_tree_hash(b);
|
||||
blob.append(reinterpret_cast<const char*>(&tree_root_hash), sizeof(tree_root_hash));
|
||||
blob.append(tools::get_varint_data(b.tx_hashes.size()+1));
|
||||
|
@ -1485,22 +1446,22 @@ namespace cryptonote
|
|||
return parse_and_validate_block_from_blob(b_blob, b, &block_hash);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
blobdata block_to_blob(const block& b)
|
||||
std::string block_to_blob(const block& b)
|
||||
{
|
||||
return t_serializable_object_to_blob(b);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool block_to_blob(const block& b, blobdata& b_blob)
|
||||
bool block_to_blob(const block& b, std::string& b_blob)
|
||||
{
|
||||
return t_serializable_object_to_blob(b, b_blob);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
blobdata tx_to_blob(const transaction& tx)
|
||||
std::string tx_to_blob(const transaction& tx)
|
||||
{
|
||||
return t_serializable_object_to_blob(tx);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool tx_to_blob(const transaction& tx, blobdata& b_blob)
|
||||
bool tx_to_blob(const transaction& tx, std::string& b_blob)
|
||||
{
|
||||
return t_serializable_object_to_blob(tx, b_blob);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#pragma once
|
||||
#include "blobdatatype.h"
|
||||
#include "cryptonote_basic_impl.h"
|
||||
#include "tx_extra.h"
|
||||
#include "account.h"
|
||||
|
@ -46,7 +45,10 @@ namespace epee
|
|||
class wipeable_string;
|
||||
}
|
||||
|
||||
namespace service_nodes { struct quorum_vote_t; }
|
||||
namespace service_nodes {
|
||||
struct quorum_vote_t;
|
||||
struct registration_details;
|
||||
}
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
|
@ -129,12 +131,12 @@ namespace cryptonote
|
|||
crypto::public_key get_tx_pub_key_from_extra(const std::vector<uint8_t>& tx_extra, size_t pk_index = 0);
|
||||
crypto::public_key get_tx_pub_key_from_extra(const transaction_prefix& tx, size_t pk_index = 0);
|
||||
|
||||
bool add_service_node_state_change_to_tx_extra(std::vector<uint8_t>& tx_extra, const tx_extra_service_node_state_change& state_change, uint8_t hf_version);
|
||||
bool get_service_node_state_change_from_tx_extra(const std::vector<uint8_t>& tx_extra, tx_extra_service_node_state_change& state_change, uint8_t hf_version);
|
||||
bool add_service_node_state_change_to_tx_extra(std::vector<uint8_t>& tx_extra, const tx_extra_service_node_state_change& state_change, hf hf_version);
|
||||
bool get_service_node_state_change_from_tx_extra(const std::vector<uint8_t>& tx_extra, tx_extra_service_node_state_change& state_change, hf hf_version);
|
||||
|
||||
bool get_service_node_pubkey_from_tx_extra(const std::vector<uint8_t>& tx_extra, crypto::public_key& pubkey);
|
||||
bool get_service_node_contributor_from_tx_extra(const std::vector<uint8_t>& tx_extra, cryptonote::account_public_address& address);
|
||||
bool add_service_node_register_to_tx_extra(std::vector<uint8_t>& tx_extra, const std::vector<cryptonote::account_public_address>& addresses, uint64_t portions_for_operator, const std::vector<uint64_t>& portions, uint64_t expiration_timestamp, const crypto::signature& signature);
|
||||
bool add_service_node_registration_to_tx_extra(std::vector<uint8_t>& tx_extra, const service_nodes::registration_details& registration);
|
||||
|
||||
bool get_tx_secret_key_from_tx_extra(const std::vector<uint8_t>& tx_extra, crypto::secret_key& key);
|
||||
void add_tx_secret_key_to_tx_extra(std::vector<uint8_t>& tx_extra, const crypto::secret_key& key);
|
||||
|
@ -151,16 +153,16 @@ namespace cryptonote
|
|||
std::vector<crypto::public_key> get_additional_tx_pub_keys_from_extra(const std::vector<uint8_t>& tx_extra);
|
||||
std::vector<crypto::public_key> get_additional_tx_pub_keys_from_extra(const transaction_prefix& tx);
|
||||
bool add_additional_tx_pub_keys_to_extra(std::vector<uint8_t>& tx_extra, const std::vector<crypto::public_key>& additional_pub_keys);
|
||||
bool add_extra_nonce_to_tx_extra(std::vector<uint8_t>& tx_extra, const blobdata& extra_nonce);
|
||||
bool add_extra_nonce_to_tx_extra(std::vector<uint8_t>& tx_extra, const std::string& extra_nonce);
|
||||
bool remove_field_from_tx_extra(std::vector<uint8_t>& tx_extra, size_t variant_index);
|
||||
template <typename T>
|
||||
bool remove_field_from_tx_extra(std::vector<uint8_t>& tx_extra) {
|
||||
return remove_field_from_tx_extra(tx_extra, tools::template_index<T, tx_extra_field>);
|
||||
}
|
||||
void set_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash& payment_id);
|
||||
void set_encrypted_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash8& payment_id);
|
||||
bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id);
|
||||
bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash8& payment_id);
|
||||
void set_payment_id_to_tx_extra_nonce(std::string& extra_nonce, const crypto::hash& payment_id);
|
||||
void set_encrypted_payment_id_to_tx_extra_nonce(std::string& extra_nonce, const crypto::hash8& payment_id);
|
||||
bool get_payment_id_from_tx_extra_nonce(const std::string& extra_nonce, crypto::hash& payment_id);
|
||||
bool get_encrypted_payment_id_from_tx_extra_nonce(const std::string& extra_nonce, crypto::hash8& payment_id);
|
||||
bool add_burned_amount_to_tx_extra(std::vector<uint8_t>& tx_extra, uint64_t burn);
|
||||
uint64_t get_burned_amount_from_tx_extra(const std::vector<uint8_t>& tx_extra);
|
||||
bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_public_keys, size_t output_index);
|
||||
|
@ -180,18 +182,16 @@ namespace cryptonote
|
|||
crypto::hash get_blob_hash(const std::string_view blob);
|
||||
std::string short_hash_str(const crypto::hash& h);
|
||||
|
||||
bool get_registration_hash(const std::vector<cryptonote::account_public_address>& addresses, uint64_t operator_portions, const std::vector<uint64_t>& portions, uint64_t expiration_timestamp, crypto::hash& hash);
|
||||
|
||||
crypto::hash get_transaction_hash(const transaction& t);
|
||||
bool get_transaction_hash(const transaction& t, crypto::hash& res);
|
||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size);
|
||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size);
|
||||
bool calculate_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blob, crypto::hash& res);
|
||||
crypto::hash get_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blob = NULL);
|
||||
bool calculate_transaction_prunable_hash(const transaction& t, const std::string *blob, crypto::hash& res);
|
||||
crypto::hash get_transaction_prunable_hash(const transaction& t, const std::string *blob = NULL);
|
||||
bool calculate_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size);
|
||||
crypto::hash get_pruned_transaction_hash(const transaction& t, const crypto::hash &pruned_data_hash);
|
||||
|
||||
blobdata get_block_hashing_blob(const block& b);
|
||||
std::string get_block_hashing_blob(const block& b);
|
||||
bool calculate_block_hash(const block& b, crypto::hash& res);
|
||||
bool get_block_hash(const block& b, crypto::hash& res);
|
||||
crypto::hash get_block_hash(const block& b);
|
||||
|
@ -202,7 +202,7 @@ namespace cryptonote
|
|||
uint64_t get_outs_money_amount(const transaction& tx);
|
||||
bool check_inputs_types_supported(const transaction& tx);
|
||||
bool check_outs_valid(const transaction& tx);
|
||||
bool parse_amount(uint64_t& amount, std::string_view str_amount);
|
||||
std::optional<uint64_t> parse_amount(std::string_view str_amount);
|
||||
uint64_t get_transaction_weight(const transaction &tx);
|
||||
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size);
|
||||
uint64_t get_pruned_transaction_weight(const transaction &tx);
|
||||
|
@ -213,8 +213,12 @@ namespace cryptonote
|
|||
uint64_t get_block_height(const block& b);
|
||||
std::vector<uint64_t> relative_output_offsets_to_absolute(const std::vector<uint64_t>& off);
|
||||
std::vector<uint64_t> absolute_output_offsets_to_relative(const std::vector<uint64_t>& off);
|
||||
inline constexpr std::string_view get_unit() { return "OXEN"sv; }
|
||||
std::string print_money(uint64_t amount, bool trim_insignificant = false);
|
||||
constexpr std::string_view get_unit() { return "OXEN"sv; }
|
||||
// Returns a monetary value with a decimal point; optionally strips insignificant trailing 0s.
|
||||
std::string print_money(uint64_t amount, bool strip_zeros = false);
|
||||
// Returns a formatted monetary value including the unit, e.g. "1.234567 OXEN"; strips
|
||||
// insignificant trailing 0s by default (unlike the above) but can be overridden to not do that.
|
||||
std::string format_money(uint64_t amount, bool strip_zeros = true);
|
||||
|
||||
std::string print_tx_verification_context (tx_verification_context const &tvc, transaction const *tx = nullptr);
|
||||
std::string print_vote_verification_context(vote_verification_context const &vvc, service_nodes::quorum_vote_t const *vote = nullptr);
|
||||
|
@ -251,7 +255,7 @@ namespace cryptonote
|
|||
|
||||
//---------------------------------------------------------------
|
||||
template <typename T>
|
||||
bool t_serializable_object_from_blob(T& to, const blobdata& blob)
|
||||
bool t_serializable_object_from_blob(T& to, const std::string& blob)
|
||||
{
|
||||
try {
|
||||
serialization::parse_binary(blob, to);
|
||||
|
@ -262,7 +266,7 @@ namespace cryptonote
|
|||
}
|
||||
//---------------------------------------------------------------
|
||||
template <typename T>
|
||||
bool t_serializable_object_to_blob(T& val, blobdata& blob)
|
||||
bool t_serializable_object_to_blob(T& val, std::string& blob)
|
||||
{
|
||||
try {
|
||||
blob = serialization::dump_binary(const_cast<std::remove_const_t<T>&>(val));
|
||||
|
@ -275,9 +279,9 @@ namespace cryptonote
|
|||
}
|
||||
//---------------------------------------------------------------
|
||||
template <typename T>
|
||||
blobdata t_serializable_object_to_blob(const T& val)
|
||||
std::string t_serializable_object_to_blob(const T& val)
|
||||
{
|
||||
blobdata b;
|
||||
std::string b;
|
||||
t_serializable_object_to_blob(val, b);
|
||||
return b;
|
||||
}
|
||||
|
@ -298,7 +302,7 @@ namespace cryptonote
|
|||
template <typename T>
|
||||
bool get_object_hash(const T& o, crypto::hash& res, size_t& blob_size)
|
||||
{
|
||||
blobdata bl;
|
||||
std::string bl;
|
||||
if (!t_serializable_object_to_blob(o, bl))
|
||||
return false;
|
||||
blob_size = bl.size();
|
||||
|
@ -320,10 +324,10 @@ namespace cryptonote
|
|||
return ss.str();
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
blobdata block_to_blob(const block& b);
|
||||
bool block_to_blob(const block& b, blobdata& b_blob);
|
||||
blobdata tx_to_blob(const transaction& b);
|
||||
bool tx_to_blob(const transaction& b, blobdata& b_blob);
|
||||
std::string block_to_blob(const block& b);
|
||||
bool block_to_blob(const block& b, std::string& b_blob);
|
||||
std::string tx_to_blob(const transaction& b);
|
||||
bool tx_to_blob(const transaction& b, std::string& b_blob);
|
||||
void get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes, crypto::hash& h);
|
||||
crypto::hash get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes);
|
||||
crypto::hash get_tx_tree_hash(const block& b);
|
||||
|
|
|
@ -128,13 +128,13 @@ namespace cryptonote {
|
|||
timestamps.push_back(timestamp);
|
||||
difficulties.push_back(cumulative_difficulty);
|
||||
|
||||
bool before_hf16 = !is_hard_fork_at_least(nettype, network_version_16_pulse, chain_height);
|
||||
bool before_hf16 = !is_hard_fork_at_least(nettype, hf::hf16_pulse, chain_height);
|
||||
|
||||
// Trim down arrays
|
||||
while (timestamps.size() > DIFFICULTY_BLOCKS_COUNT(before_hf16))
|
||||
while (timestamps.size() > old::DIFFICULTY_BLOCKS_COUNT(before_hf16))
|
||||
timestamps.erase(timestamps.begin());
|
||||
|
||||
while (difficulties.size() > DIFFICULTY_BLOCKS_COUNT(before_hf16))
|
||||
while (difficulties.size() > old::DIFFICULTY_BLOCKS_COUNT(before_hf16))
|
||||
difficulties.erase(difficulties.begin());
|
||||
}
|
||||
|
||||
|
@ -167,15 +167,15 @@ namespace cryptonote {
|
|||
{
|
||||
auto result = difficulty_calc_mode::normal;
|
||||
|
||||
if (!is_hard_fork_at_least(nettype, cryptonote::network_version_10_bulletproofs, height))
|
||||
if (!is_hard_fork_at_least(nettype, hf::hf10_bulletproofs, height))
|
||||
result = difficulty_calc_mode::use_old_lwma;
|
||||
// HF12 switches to RandomX with a likely drastically reduced hashrate versus Turtle, so override
|
||||
// difficulty for the first difficulty window blocks:
|
||||
else if (auto randomx_start_height = get_hard_fork_heights(nettype, network_version_12_checkpointing).first;
|
||||
randomx_start_height && height >= *randomx_start_height && height <= *randomx_start_height + DIFFICULTY_WINDOW)
|
||||
else if (auto randomx_start_height = get_hard_fork_heights(nettype, hf::hf12_checkpointing).first;
|
||||
randomx_start_height && height >= *randomx_start_height && height <= *randomx_start_height + old::DIFFICULTY_WINDOW)
|
||||
result = difficulty_calc_mode::hf12_override;
|
||||
else if (auto pulse_start_height = get_hard_fork_heights(nettype, network_version_16_pulse).first;
|
||||
nettype == MAINNET && pulse_start_height && height >= *pulse_start_height && height <= *pulse_start_height + DIFFICULTY_WINDOW)
|
||||
else if (auto pulse_start_height = get_hard_fork_heights(nettype, hf::hf16_pulse).first;
|
||||
nettype == network_type::MAINNET && pulse_start_height && height >= *pulse_start_height && height <= *pulse_start_height + old::DIFFICULTY_WINDOW)
|
||||
result = difficulty_calc_mode::hf16_override;
|
||||
|
||||
return result;
|
||||
|
@ -187,7 +187,7 @@ namespace cryptonote {
|
|||
difficulty_calc_mode mode)
|
||||
{
|
||||
const int64_t T = static_cast<int64_t>(target_seconds);
|
||||
size_t N = DIFFICULTY_WINDOW;
|
||||
size_t N = old::DIFFICULTY_WINDOW;
|
||||
|
||||
// Return a difficulty of 1 for first 4 blocks if it's the start of the chain.
|
||||
if (timestamps.size() < 4) {
|
||||
|
|
|
@ -35,52 +35,57 @@ namespace cryptonote {
|
|||
// version 7 from the start of the blockchain, inhereted from Monero mainnet
|
||||
static constexpr std::array mainnet_hard_forks =
|
||||
{
|
||||
hard_fork{7, 0, 0, 1503046577 }, // Loki 0.1: Loki is born
|
||||
hard_fork{8, 0, 64324, 1533006000 /*2018-07-31 03:00 UTC*/ }, // Loki 0.2: New emissions schedule
|
||||
hard_fork{9, 0, 101250, 1537444800 /*2018-09-20 12:00 UTC*/ }, // Loki 1: Service nodes launched
|
||||
hard_fork{10, 0, 161849, 1544743800 /*2018-12-13 23:30 UTC*/ }, // Loki 2: Bulletproofs, gov fee batching
|
||||
hard_fork{11, 0, 234767, 1554170400 /*2019-03-26 13:00 AEDT*/ }, // Loki 3: Infinite staking, CN-Turtle
|
||||
hard_fork{12, 0, 321467, 1563940800 /*2019-07-24 14:00 AEDT*/ }, // Loki 4: Checkpointing, RandomXL, decommissioning, Storage Server launched
|
||||
hard_fork{13, 0, 385824, 1571850000 /*2019-10-23 19:00 AEDT*/ }, // Loki 5: Checkpointing enforced
|
||||
hard_fork{14, 0, 442333, 1578528000 /*2020-01-09 00:00 UTC*/ }, // Loki 6: Blink, Lokinet launched on mainnet
|
||||
hard_fork{15, 0, 496969, 1585105200 /*2020-03-25 14:00 AEDT (03:00 UTC)*/ }, // Loki 7: ONS (Session)
|
||||
hard_fork{16, 0, 641111, 1602464400 /*2020-10-12 12:00 AEDT (01:00 UTC)*/ }, // Loki 8: Pulse
|
||||
hard_fork{17, 0, 770711, 1618016400 /*Saturday, April 10, 2021 1:00:00 UTC*/ }, // Oxen 8: Eliminate 6/block emissions after 180 days (not a separate release)
|
||||
hard_fork{18, 0, 785000, 1619736143 /*Thursday, April 29, 2021 22:42:23 UTC*/ }, // Oxen 9: Timesync, new proofs, reasons, wallet ONS
|
||||
hard_fork{18, 1, 839009, 1626217200 /*Tuesday, July 13, 2021 23:00 UTC */ }, // Oxen 9.2: mandatory SS 2.2.0 & lokinet 0.9.5 updates
|
||||
hard_fork{hf::hf7, 0, 0, 1503046577 }, // Loki 0.1: Loki is born
|
||||
hard_fork{hf::hf8, 0, 64324, 1533006000 /*2018-07-31 03:00 UTC*/ }, // Loki 0.2: New emissions schedule
|
||||
hard_fork{hf::hf9_service_nodes, 0, 101250, 1537444800 /*2018-09-20 12:00 UTC*/ }, // Loki 1: Service nodes launched
|
||||
hard_fork{hf::hf10_bulletproofs, 0, 161849, 1544743800 /*2018-12-13 23:30 UTC*/ }, // Loki 2: Bulletproofs, gov fee batching
|
||||
hard_fork{hf::hf11_infinite_staking, 0, 234767, 1554170400 /*2019-03-26 13:00 AEDT*/ }, // Loki 3: Infinite staking, CN-Turtle
|
||||
hard_fork{hf::hf12_checkpointing, 0, 321467, 1563940800 /*2019-07-24 14:00 AEDT*/ }, // Loki 4: Checkpointing, RandomXL, decommissioning, Storage Server launched
|
||||
hard_fork{hf::hf13_enforce_checkpoints, 0, 385824, 1571850000 /*2019-10-23 19:00 AEDT*/ }, // Loki 5: Checkpointing enforced
|
||||
hard_fork{hf::hf14_blink, 0, 442333, 1578528000 /*2020-01-09 00:00 UTC*/ }, // Loki 6: Blink, Lokinet launched on mainnet
|
||||
hard_fork{hf::hf15_ons, 0, 496969, 1585105200 /*2020-03-25 14:00 AEDT (03:00 UTC)*/ }, // Loki 7: ONS (Session)
|
||||
hard_fork{hf::hf16_pulse, 0, 641111, 1602464400 /*2020-10-12 12:00 AEDT (01:00 UTC)*/ }, // Loki 8: Pulse
|
||||
hard_fork{hf::hf17, 0, 770711, 1618016400 /*Saturday, April 10, 2021 1:00:00 UTC*/ }, // Oxen 8: Eliminate 6/block emissions after 180 days (not a separate release)
|
||||
hard_fork{hf::hf18, 0, 785000, 1619736143 /*Thursday, April 29, 2021 22:42:23 UTC*/ }, // Oxen 9: Timesync, new proofs, reasons, wallet ONS
|
||||
hard_fork{hf::hf18, 1, 839009, 1626217200 /*Tuesday, July 13, 2021 23:00 UTC */ }, // Oxen 9.2: mandatory SS 2.2.0 & lokinet 0.9.5 updates
|
||||
hard_fork{hf::hf19_reward_batching, 0, 1080149, 1655154000 /*Monday, June 13, 2022 21:00 UTC */}, // Oxen 10.1: Service Node Reward Batching
|
||||
hard_fork{hf::hf19_reward_batching, 1, 1090229, 1656363600 /*Monday, June 27, 2022 21:00 UTC */}, // Minor hardfork, upgrades to session.
|
||||
};
|
||||
|
||||
static constexpr std::array testnet_hard_forks =
|
||||
{
|
||||
hard_fork{7, 0, 0, 1533631121 }, // Testnet was rebooted during Loki 3 development
|
||||
hard_fork{8, 0, 2, 1533631122 },
|
||||
hard_fork{9, 0, 3, 1533631123 },
|
||||
hard_fork{10, 0, 4, 1542681077 },
|
||||
hard_fork{11, 0, 5, 1551223964 },
|
||||
hard_fork{12, 0, 75471, 1561608000 }, // 2019-06-28 14:00 AEDT
|
||||
hard_fork{13, 0, 127028, 1568440800 }, // 2019-09-13 16:00 AEDT
|
||||
hard_fork{14, 0, 174630, 1575075600 }, // 2019-11-30 07:00 UTC
|
||||
hard_fork{15, 0, 244777, 1583940000 }, // 2020-03-11 15:20 UTC
|
||||
hard_fork{16, 0, 382222, 1600468200 }, // 2020-09-18 22:30 UTC
|
||||
hard_fork{17, 0, 447275, 1608276840 }, // 2020-12-18 05:34 UTC
|
||||
hard_fork{18, 0, 501750, 1616631051 }, // 2021-03-25 12:10 UTC
|
||||
hard_fork{18, 1, 578637, 1624040400 }, // 2021-06-18 18:20 UTC
|
||||
hard_fork{hf::hf7, 0, 0, 1653632397}, // Testnet was rebooted during HF19 - Oxen 10
|
||||
hard_fork{hf::hf11_infinite_staking, 0, 2, 1653632397},
|
||||
hard_fork{hf::hf12_checkpointing, 0, 3, 1653632397},
|
||||
hard_fork{hf::hf13_enforce_checkpoints, 0, 4, 1653632397},
|
||||
hard_fork{hf::hf14_blink, 0, 5, 1653632397},
|
||||
hard_fork{hf::hf15_ons, 0, 6, 1653632397},
|
||||
hard_fork{hf::hf16_pulse, 0, 200, 1653632397},
|
||||
hard_fork{hf::hf17, 0, 251, 1653632397},
|
||||
hard_fork{hf::hf18, 0, 252, 1653632397},
|
||||
hard_fork{hf::hf19_reward_batching, 0, 253, 1653632397},
|
||||
hard_fork{hf::hf19_reward_batching, 1, 254, 1653632397}, // 2022-05-27T06:19:57.000Z UTC
|
||||
};
|
||||
|
||||
static constexpr std::array devnet_hard_forks =
|
||||
{
|
||||
hard_fork{ 7, 0, 0, 1599848400 },
|
||||
hard_fork{ 11, 0, 2, 1599848400 },
|
||||
hard_fork{ 12, 0, 3, 1599848400 },
|
||||
hard_fork{ 13, 0, 4, 1599848400 },
|
||||
hard_fork{ 15, 0, 5, 1599848400 },
|
||||
hard_fork{ 16, 0, 99, 1599848400 },
|
||||
hard_fork{hf::hf7, 0, 0, 1653500577},
|
||||
hard_fork{hf::hf11_infinite_staking, 0, 2, 1653500577},
|
||||
hard_fork{hf::hf12_checkpointing, 0, 3, 1653500577},
|
||||
hard_fork{hf::hf13_enforce_checkpoints, 0, 4, 1653500577},
|
||||
hard_fork{hf::hf14_blink, 0, 5, 1653500577},
|
||||
hard_fork{hf::hf15_ons, 0, 6, 1653500577},
|
||||
hard_fork{hf::hf16_pulse, 0, 100, 1653500577},
|
||||
hard_fork{hf::hf17, 0, 151, 1653500577},
|
||||
hard_fork{hf::hf18, 0, 152, 1653500577},
|
||||
hard_fork{hf::hf19_reward_batching, 0, 153, 1653500577},
|
||||
hard_fork{hf::hf19_reward_batching, 1, 154, 1653500577},
|
||||
};
|
||||
|
||||
|
||||
template <size_t N>
|
||||
static constexpr bool is_ordered(const std::array<hard_fork, N>& forks) {
|
||||
if (N == 0 || forks[0].version < 7)
|
||||
if (N == 0 || forks[0].version < hf::hf7)
|
||||
return false;
|
||||
for (size_t i = 1; i < N; i++) {
|
||||
auto& hf = forks[i];
|
||||
|
@ -112,9 +117,8 @@ std::pair<const hard_fork*, const hard_fork*> get_hard_forks(network_type type)
|
|||
return {nullptr, nullptr};
|
||||
}
|
||||
|
||||
|
||||
std::pair<std::optional<uint64_t>, std::optional<uint64_t>>
|
||||
get_hard_fork_heights(network_type nettype, uint8_t version) {
|
||||
get_hard_fork_heights(network_type nettype, hf version) {
|
||||
std::pair<std::optional<uint64_t>, std::optional<uint64_t>> found;
|
||||
for (auto [it, end] = get_hard_forks(nettype); it != end; it++) {
|
||||
if (it->version > version) { // This (and anything else) are in the future
|
||||
|
@ -128,7 +132,7 @@ get_hard_fork_heights(network_type nettype, uint8_t version) {
|
|||
return found;
|
||||
}
|
||||
|
||||
uint8_t hard_fork_ceil(network_type nettype, uint8_t version) {
|
||||
hf hard_fork_ceil(network_type nettype, hf version) {
|
||||
auto [it, end] = get_hard_forks(nettype);
|
||||
for (; it != end; it++)
|
||||
if (it->version >= version)
|
||||
|
@ -137,9 +141,9 @@ uint8_t hard_fork_ceil(network_type nettype, uint8_t version) {
|
|||
return version;
|
||||
}
|
||||
|
||||
std::pair<uint8_t, uint8_t>
|
||||
std::pair<hf, uint8_t>
|
||||
get_network_version_revision(network_type nettype, uint64_t height) {
|
||||
std::pair<uint8_t, uint8_t> result;
|
||||
std::pair<hf, uint8_t> result;
|
||||
for (auto [it, end] = get_hard_forks(nettype); it != end; it++) {
|
||||
if (it->height <= height)
|
||||
result = {it->version, it->snode_revision};
|
||||
|
@ -149,22 +153,23 @@ get_network_version_revision(network_type nettype, uint64_t height) {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool is_hard_fork_at_least(network_type type, uint8_t version, uint64_t height) {
|
||||
bool is_hard_fork_at_least(network_type type, hf version, uint64_t height) {
|
||||
return get_network_version(type, height) >= version;
|
||||
}
|
||||
|
||||
std::pair<uint8_t, uint8_t>
|
||||
std::pair<hf, uint8_t>
|
||||
get_ideal_block_version(network_type nettype, uint64_t height)
|
||||
{
|
||||
std::pair<uint8_t, uint8_t> result;
|
||||
std::pair<hf, uint8_t> result;
|
||||
for (auto [it, end] = get_hard_forks(nettype); it != end; it++) {
|
||||
if (it->height <= height)
|
||||
if (it->height <= height) {
|
||||
result.first = it->version;
|
||||
result.second = it->version;
|
||||
result.second = it->snode_revision;
|
||||
}
|
||||
if (result.first < hf::hf19_reward_batching)
|
||||
result.second = static_cast<uint8_t>(it->version);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
} // namespace cryptonote
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace cryptonote
|
|||
|
||||
// Defines where hard fork (i.e. new minimum network versions) begin
|
||||
struct hard_fork {
|
||||
uint8_t version; // Blockchain major version
|
||||
hf version; // Blockchain major version
|
||||
uint8_t snode_revision; // Snode revision for enforcing non-blockchain-breaking mandatory service node updates
|
||||
uint64_t height;
|
||||
time_t time;
|
||||
|
@ -53,7 +53,7 @@ namespace cryptonote
|
|||
// outdated), and returns nullopt for B if the version indicates that top network version we know
|
||||
// about (i.e. there is no subsequent hardfork scheduled).
|
||||
std::pair<std::optional<uint64_t>, std::optional<uint64_t>>
|
||||
get_hard_fork_heights(network_type type, uint8_t version);
|
||||
get_hard_fork_heights(network_type type, hf version);
|
||||
|
||||
// Returns the lowest network version >= the given version, that is, it rounds up missing hf table
|
||||
// entries to the next largest entry. Typically this returns the network version itself, but if
|
||||
|
@ -68,18 +68,18 @@ namespace cryptonote
|
|||
// ...
|
||||
// hard_fork_ceil(14) == 14
|
||||
// hard_fork_ceil(15) == 15
|
||||
uint8_t hard_fork_ceil(network_type type, uint8_t version);
|
||||
hf hard_fork_ceil(network_type type, hf version);
|
||||
|
||||
// Returns true if the given height is sufficiently high to be at or after the given hard fork
|
||||
// version.
|
||||
bool is_hard_fork_at_least(network_type type, uint8_t version, uint64_t height);
|
||||
bool is_hard_fork_at_least(network_type type, hf version, uint64_t height);
|
||||
|
||||
// Returns the active network version and snode revision for the given height.
|
||||
std::pair<uint8_t, uint8_t>
|
||||
std::pair<hf, uint8_t>
|
||||
get_network_version_revision(network_type nettype, uint64_t height);
|
||||
|
||||
// Returns the network (i.e. block) version for the given height.
|
||||
inline uint8_t get_network_version(network_type nettype, uint64_t height) {
|
||||
inline hf get_network_version(network_type nettype, uint64_t height) {
|
||||
return get_network_version_revision(nettype, height).first;
|
||||
}
|
||||
|
||||
|
@ -87,14 +87,16 @@ namespace cryptonote
|
|||
// a shortcut for `get_hard_fork_heights(type, hard_fork_ceil(type, version)).first`, i.e. it
|
||||
// returns the first height at which `version` rules become active (even if they became active at
|
||||
// a hard fork > the given value).
|
||||
inline std::optional<uint64_t> hard_fork_begins(network_type type, uint8_t version) {
|
||||
inline std::optional<uint64_t> hard_fork_begins(network_type type, hf version) {
|
||||
return get_hard_fork_heights(type, hard_fork_ceil(type, version)).first;
|
||||
}
|
||||
|
||||
// Returns the "ideal" network version that we want to use on blocks we create, which is to use
|
||||
// the required major version for major version and the maximum major version we know about as
|
||||
// minor version. If this seems a bit silly, it is, and will be changed in the future.
|
||||
std::pair<uint8_t, uint8_t> get_ideal_block_version(network_type nettype, uint64_t height);
|
||||
// the required major version and current minor version. (Minor versions are sometimes used to
|
||||
// change network features, but do not change the blockchain rules).
|
||||
// Before HF19, the minor version must be >= the major version, and is set to the largest major
|
||||
// version we know about.
|
||||
std::pair<hf, uint8_t> get_ideal_block_version(network_type nettype, uint64_t height);
|
||||
|
||||
} // namespace cryptonote
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue