forked from lthn/blockchain
Merge branch 'release'
This commit is contained in:
commit
6b99449e21
249 changed files with 33327 additions and 9754 deletions
|
|
@ -4,22 +4,19 @@ AlignConsecutiveAssignments: 'true'
|
|||
AlignConsecutiveDeclarations: 'false'
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: 'false'
|
||||
AlignTrailingComments: 'true'
|
||||
AlignTrailingComments: 'false'
|
||||
AllowAllParametersOfDeclarationOnNextLine: 'false'
|
||||
AllowShortBlocksOnASingleLine: 'false'
|
||||
AllowShortCaseLabelsOnASingleLine: 'true'
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: 'true'
|
||||
AllowShortLoopsOnASingleLine: 'false'
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: 'false'
|
||||
AlwaysBreakTemplateDeclarations: 'true'
|
||||
BinPackArguments: 'true'
|
||||
BinPackParameters: 'true'
|
||||
BreakAfterJavaFieldAnnotations: 'true'
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Stroustrup
|
||||
BreakBeforeInheritanceComma: 'false'
|
||||
BreakBeforeBraces: Allman
|
||||
BreakBeforeTernaryOperators: 'false'
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakStringLiterals: 'false'
|
||||
|
|
@ -56,4 +53,4 @@ SpacesInParentheses: 'false'
|
|||
SpacesInSquareBrackets: 'false'
|
||||
Standard: Cpp11
|
||||
TabWidth: '2'
|
||||
UseTab: Never
|
||||
UseTab: Never
|
||||
|
|
|
|||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -5,4 +5,5 @@
|
|||
._.DS_Store
|
||||
Thumbs.db
|
||||
._*
|
||||
.idea
|
||||
.idea
|
||||
.vs/*
|
||||
|
|
@ -1,17 +1,21 @@
|
|||
cmake_minimum_required(VERSION 2.8.6)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
PROJECT(Zano)
|
||||
|
||||
|
||||
set(VERSION "1.0")
|
||||
|
||||
# if(POLICY CMP0043)
|
||||
# cmake_policy(SET CMP0043 OLD)
|
||||
# endif()
|
||||
if(POLICY CMP0043)
|
||||
cmake_policy(SET CMP0043 NEW)
|
||||
endif()
|
||||
if(POLICY CMP0043)
|
||||
cmake_policy(SET CMP0074 NEW)
|
||||
endif()
|
||||
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# if(POLICY CMP0020)
|
||||
# cmake_policy(SET CMP0020 OLD)
|
||||
# endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
add_definitions(-DMOBILE_WALLET_BUILD)
|
||||
|
|
@ -50,9 +54,12 @@ message("Generated with config types: ${CMAKE_CONFIGURATION_TYPES}, and built ty
|
|||
|
||||
enable_testing()
|
||||
|
||||
set(OPENSSL_USE_STATIC_LIBS TRUE) # link statically
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.10.5)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.12)
|
||||
endif()
|
||||
|
||||
set(USE_PCH FALSE CACHE BOOL "Use shared precompiled headers")
|
||||
|
|
@ -60,7 +67,7 @@ set(DISABLE_TOR FALSE CACHE BOOL "Disable TOR library(and related tor-connect su
|
|||
set(TESTNET FALSE CACHE BOOL "Compile for testnet")
|
||||
set(BUILD_GUI FALSE CACHE BOOL "Build qt-daemon")
|
||||
|
||||
include_directories(src contrib/eos_portable_archive contrib contrib/epee/include "${CMAKE_BINARY_DIR}/version" "${CMAKE_BINARY_DIR}/contrib/zlib")
|
||||
include_directories(src contrib/eos_portable_archive contrib contrib/epee/include ${OPENSSL_INCLUDE_DIR} "${CMAKE_BINARY_DIR}/version" "${CMAKE_BINARY_DIR}/contrib/zlib")
|
||||
|
||||
add_definitions(-DSTATICLIB)
|
||||
|
||||
|
|
@ -69,6 +76,11 @@ if(TESTNET)
|
|||
add_definitions(-DTESTNET)
|
||||
endif()
|
||||
|
||||
if(CAKEWALLET)
|
||||
message("NOTICE: Building libraries for CAKEWALLET")
|
||||
add_definitions(-DCAKEWALLET)
|
||||
endif()
|
||||
|
||||
set(OPENSSL_USE_STATIC_LIBS TRUE) # link statically
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
|
|
@ -90,9 +102,9 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
|||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions("/D_CRT_SECURE_NO_WARNINGS /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0 /D__SSE4_1__")
|
||||
add_definitions("/D_CRT_SECURE_NO_WARNINGS /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0")
|
||||
add_compile_options(/bigobj /Zm1000 /Z7 /MP2 /W3 /GS- /wd4996 /wd4503 /wd4345 /wd4091 /FIinline_c.h)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:10485760 /DEBUG dbghelp.lib")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:10485760 /DEBUG dbghelp.lib crypt32.lib")
|
||||
if(STATIC)
|
||||
foreach(VAR CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE)
|
||||
string(REPLACE "/MD" "/MT" ${VAR} "${${VAR}}")
|
||||
|
|
@ -106,7 +118,7 @@ else()
|
|||
else()
|
||||
set(ARCH_FLAG "-march=${ARCH}")
|
||||
endif()
|
||||
set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=deprecated-declarations -Wno-error=sign-compare -Wno-error=strict-aliasing -Wno-error=type-limits -Wno-unused-parameter -Wno-error=unused-variable -Wno-aggregate-return")
|
||||
set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=deprecated-declarations -Wno-error=sign-compare -Wno-error=strict-aliasing -Wno-error=type-limits -Wno-unused-parameter -Wno-error=unused-variable -Wno-aggregate-return -Wno-comment -Wno-unknown-pragmas -Wno-pragmas")
|
||||
# if(NOT APPLE)
|
||||
# set(WARNINGS "${WARNINGS} -Werror")
|
||||
# endif()
|
||||
|
|
@ -138,16 +150,16 @@ else()
|
|||
else()
|
||||
set(APPLE_FLAG "")
|
||||
endif()
|
||||
set(C_WARNINGS "-Waggregate-return -Wnested-externs -Wstrict-prototypes")
|
||||
set(C_WARNINGS "-Waggregate-return -Wnested-externs -Wstrict-prototypes -Wno-comment")
|
||||
set(CXX_WARNINGS "-Wno-reorder -Wno-missing-field-initializers")
|
||||
try_compile(STATIC_ASSERT_RES "${CMAKE_CURRENT_BINARY_DIR}/static-assert" "${CMAKE_CURRENT_SOURCE_DIR}/utils/test-static-assert.c" COMPILE_DEFINITIONS "-std=c11")
|
||||
try_compile(STATIC_ASSERT_RES "${CMAKE_CURRENT_BINARY_DIR}/static-assert" "${CMAKE_CURRENT_SOURCE_DIR}/utils/test-static-assert.c" COMPILE_DEFINITIONS "-std=c++14")
|
||||
if(STATIC_ASSERT_RES)
|
||||
set(STATIC_ASSERT_FLAG "")
|
||||
else()
|
||||
set(STATIC_ASSERT_FLAG "-Dstatic_assert=_Static_assert")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -ftemplate-depth-1024 -std=c++11 -D_GNU_SOURCE ${APPLE_FLAG} ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -ftemplate-depth-1024 -std=c++14 -D_GNU_SOURCE ${APPLE_FLAG} ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG}")
|
||||
if (NOT APPLE AND NOT MSVC)
|
||||
if (CLANG)
|
||||
set(LLVM_USE_LINKER "gold")
|
||||
|
|
@ -182,6 +194,11 @@ else()
|
|||
endif()
|
||||
|
||||
|
||||
# always use local Boost installation rather than the system-wide (unless ZANO_USE_SYSTEM_BOOST is defined for some reason, which is not recommended)
|
||||
if(NOT DEFINED ENV{ZANO_USE_SYSTEM_BOOST})
|
||||
set(Boost_NO_SYSTEM_PATHS ON)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
endif()
|
||||
|
|
@ -204,8 +221,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
|||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
set(Boost_LIBRARY_DIRS "${Boost_LIBRARY_DIRS}/${CMAKE_ANDROID_ARCH_ABI}/")
|
||||
set(Boost_LIBRARIES "${Boost_LIBRARY_DIRS}libboost_system.a;${Boost_LIBRARY_DIRS}libboost_filesystem.a;${Boost_LIBRARY_DIRS}libboost_thread.a;${Boost_LIBRARY_DIRS}libboost_timer.a;${Boost_LIBRARY_DIRS}libboost_date_time.a;${Boost_LIBRARY_DIRS}libboost_chrono.a;${Boost_LIBRARY_DIRS}libboost_regex.a;${Boost_LIBRARY_DIRS}libboost_serialization.a;${Boost_LIBRARY_DIRS}libboost_atomic.a;${Boost_LIBRARY_DIRS}libboost_program_options.a")
|
||||
elseif(APPLE)
|
||||
find_package(Boost 1.71 REQUIRED COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options locale)
|
||||
else()
|
||||
find_package(Boost 1.70 REQUIRED COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options locale)
|
||||
find_package(Boost 1.70 REQUIRED COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options locale log)
|
||||
endif()
|
||||
|
||||
|
||||
|
|
@ -227,7 +246,7 @@ elseif(NOT MSVC)
|
|||
endif()
|
||||
|
||||
if(BUILD_GUI)
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
endif()
|
||||
|
||||
|
|
|
|||
78
README.md
78
README.md
|
|
@ -13,13 +13,13 @@ Be sure to clone the repository properly:\
|
|||
### Dependencies
|
||||
| component / version | minimum <br>(not recommended but may work) | recommended | most recent of what we have ever tested |
|
||||
|--|--|--|--|
|
||||
| gcc (Linux) | 5.4.0 | 7.5.0 | 8.3.0 |
|
||||
| gcc (Linux) | 5.4.0 | 9.4.0 | 12.3.0 |
|
||||
| llvm/clang (Linux) | UNKNOWN | 7.0.1 | 8.0.0 |
|
||||
| [MSVC](https://visualstudio.microsoft.com/downloads/) (Windows) | 2015 (14.0 update 1) | 2017 (15.9.0) | 2022 (17.4.2) |
|
||||
| [XCode](https://developer.apple.com/downloads/) (macOS) | 9.2 | 12.3 | 12.3 |
|
||||
| [CMake](https://cmake.org/download/) | 2.8.6 | 3.15.5 | 3.26.3 |
|
||||
| [MSVC](https://visualstudio.microsoft.com/downloads/) (Windows) | 2017 (15.9.30) | 2017 (15.9.30) | 2022 (17.7.5) |
|
||||
| [XCode](https://developer.apple.com/downloads/) (macOS) | 12.3 | 14.3 | 14.3 |
|
||||
| [CMake](https://cmake.org/download/) | 3.15.5 | 3.22.1 | 3.26.3 |
|
||||
| [Boost](https://www.boost.org/users/download/) | 1.70 | 1.70 | 1.76 |
|
||||
| [OpenSSL](https://www.openssl.org/source/) [(win)](https://slproweb.com/products/Win32OpenSSL.html) | - | 1.1.1n | 1.1.1n |
|
||||
| [OpenSSL](https://www.openssl.org/source/) [(win)](https://slproweb.com/products/Win32OpenSSL.html) | 1.1.1n | 1.1.1w | 1.1.1w |
|
||||
| [Qt](https://download.qt.io/archive/qt/) (*only for GUI*) | 5.8.0 | 5.11.2 | 5.15.2 |
|
||||
|
||||
Note:\
|
||||
|
|
@ -30,27 +30,37 @@ Note:\
|
|||
|
||||
### Linux
|
||||
|
||||
Recommended OS version: Ubuntu 18.04 LTS.
|
||||
Recommended OS versions: Ubuntu 20.04, 22.04 LTS.
|
||||
|
||||
1. Prerequisites
|
||||
|
||||
[*server version*]
|
||||
|
||||
sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git screen checkinstall zlib1g-dev
|
||||
sudo apt-get install -y build-essential g++ curl autotools-dev libicu-dev libbz2-dev cmake git screen checkinstall zlib1g-dev
|
||||
|
||||
[*GUI version*]
|
||||
|
||||
sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git screen checkinstall zlib1g-dev mesa-common-dev libglu1-mesa-dev
|
||||
|
||||
2. Download and build Boost
|
||||
2. Clone Zano into a local folder\
|
||||
(If for some reason you need to use alternative Zano branch, change 'master' to the required branch name.)
|
||||
|
||||
git clone --recursive https://github.com/hyle-team/zano.git -b master
|
||||
|
||||
In the following steps we assume that you cloned Zano into '~/zano' folder in your home directory.
|
||||
|
||||
3. Download and build Boost\
|
||||
(Assuming you have cloned Zano into the 'zano' folder. If you used a different location for Zano, **edit line 4** accordingly.)
|
||||
|
||||
curl -OL https://boostorg.jfrog.io/artifactory/main/release/1.70.0/source/boost_1_70_0.tar.bz2
|
||||
echo "430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778 boost_1_70_0.tar.bz2" | shasum -c && tar -xjf boost_1_70_0.tar.bz2
|
||||
cd boost_1_70_0
|
||||
rm boost_1_70_0.tar.bz2 && cd boost_1_70_0
|
||||
patch -p0 < ../zano/utils/boost_1.70_gcc_8.patch || cd ..
|
||||
./bootstrap.sh --with-libraries=system,filesystem,thread,date_time,chrono,regex,serialization,atomic,program_options,locale,timer,log
|
||||
./b2
|
||||
./b2 && cd ..
|
||||
Make sure that you see "The Boost C++ Libraries were successfully built!" message at the end.
|
||||
|
||||
3. Install Qt\
|
||||
4. Install Qt\
|
||||
(*GUI version only, skip this step if you're building server version*)
|
||||
|
||||
[*GUI version*]
|
||||
|
|
@ -61,20 +71,19 @@ Recommended OS version: Ubuntu 18.04 LTS.
|
|||
Then follow the instructions in Wizard. Don't forget to tick the WebEngine module checkbox!
|
||||
|
||||
|
||||
4. Install OpenSSL
|
||||
5. Install OpenSSL
|
||||
|
||||
We recommend installing OpenSSL v1.1.1n locally unless you would like to use the same version system-wide. Adjust the local path `/home/user/openssl` in the commands below according to your needs.
|
||||
We recommend installing OpenSSL v1.1.1w locally unless you would like to use the same version system-wide.\
|
||||
(Assuming that `$HOME` environment variable is set to your home directory. Otherwise, edit line 4 accordingly.)
|
||||
|
||||
curl -OL https://www.openssl.org/source/openssl-1.1.1n.tar.gz
|
||||
echo "40dceb51a4f6a5275bde0e6bf20ef4b91bfc32ed57c0552e2e8e15463372b17a openssl-1.1.1n.tar.gz" | shasum -c && tar xaf openssl-1.1.1n.tar.gz
|
||||
cd openssl-1.1.1n/
|
||||
./config --prefix=/home/user/openssl --openssldir=/home/user/openssl shared zlib
|
||||
make
|
||||
make test
|
||||
make install
|
||||
curl -OL https://www.openssl.org/source/openssl-1.1.1w.tar.gz
|
||||
echo "cf3098950cb4d853ad95c0841f1f9c6d3dc102dccfcacd521d93925208b76ac8 openssl-1.1.1w.tar.gz" | shasum -c && tar xaf openssl-1.1.1w.tar.gz
|
||||
cd openssl-1.1.1w/
|
||||
./config --prefix=$HOME/openssl --openssldir=$HOME/openssl shared zlib
|
||||
make && make test && make install && cd ..
|
||||
|
||||
|
||||
5. Set environment variables properly\
|
||||
6. [*OPTIONAL*] Set global environment variables for convenient use\
|
||||
For instance, by adding the following lines to `~/.bashrc`
|
||||
|
||||
[*server version*]
|
||||
|
|
@ -89,18 +98,27 @@ For instance, by adding the following lines to `~/.bashrc`
|
|||
export OPENSSL_ROOT_DIR=/home/user/openssl
|
||||
export QT_PREFIX_PATH=/home/user/Qt5.11.2/5.11.2/gcc_64
|
||||
|
||||
|
||||
|
||||
6. Build the binaries
|
||||
1. Build daemon and simplewallet:
|
||||
|
||||
cd zano/ && make -j1
|
||||
or
|
||||
**NOTICE: Please edit the lines above according to your actual paths.**
|
||||
|
||||
**NOTICE 2:** Make sure you've restarted your terminal session (by reopening the terminal window or reconnecting the server) to apply these changes.
|
||||
|
||||
8. Build the binaries
|
||||
1. If you skipped step 6 and did not set the environment variables:
|
||||
|
||||
cd zano && mkdir build && cd build
|
||||
BOOST_ROOT=$HOME/boost_1_70_0 OPENSSL_ROOT_DIR=$HOME/openssl cmake ..
|
||||
make -j1 daemon simplewallet
|
||||
|
||||
2. If you set the variables in step 6:
|
||||
|
||||
cd zano && mkdir build && cd build
|
||||
cmake ..
|
||||
make -j1 daemon simplewallet
|
||||
|
||||
or simply:
|
||||
|
||||
cd zano && make -j1
|
||||
|
||||
**NOTICE**: If you are building on a machine with a relatively high amount of RAM or with the proper setting of virtual memory, then you can use `-j2` or `-j` option to speed up the building process. Use with caution.
|
||||
|
||||
**NOTICE 2**: If you'd like to build binaries for the testnet, use `cmake -D TESTNET=TRUE ..` instead of `cmake ..` .
|
||||
|
|
@ -110,12 +128,12 @@ For instance, by adding the following lines to `~/.bashrc`
|
|||
cd zano
|
||||
utils/build_script_linux.sh
|
||||
|
||||
7. Look for the binaries in `build` folder
|
||||
Look for the binaries in `build` folder
|
||||
|
||||
<br />
|
||||
|
||||
### Windows
|
||||
Recommended OS version: Windows 7 x64.
|
||||
Recommended OS version: Windows 7 x64, Windows 11 x64.
|
||||
1. Install required prerequisites (Boost, Qt, CMake, OpenSSL).
|
||||
2. Edit paths in `utils/configure_local_paths.cmd`.
|
||||
3. Run one of `utils/configure_win64_msvsNNNN_gui.cmd` according to your MSVC version.
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ endif()
|
|||
set_property(TARGET upnpc-static mdbx_chk mdbx_copy mdbx_dump mdbx_load mdbx_stat PROPERTY FOLDER "unused")
|
||||
|
||||
if(MSVC)
|
||||
set_property(TARGET ntdll_extra_target PROPERTY FOLDER "unused")
|
||||
#set_property(TARGET ntdll_extra_target PROPERTY FOLDER "unused")
|
||||
endif()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -45,61 +45,6 @@ if(CC_HAS_VISIBILITY AND (LTO_ENABLED OR INTERPROCEDURAL_OPTIMIZATION))
|
|||
set_target_properties(mdbx PROPERTIES LINK_FLAGS "-fvisibility=hidden")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
if(MSVC)
|
||||
if(NOT MSVC_LIB_EXE)
|
||||
# Find lib.exe
|
||||
get_filename_component(CL_NAME ${CMAKE_C_COMPILER} NAME)
|
||||
string(REPLACE cl.exe lib.exe MSVC_LIB_EXE ${CL_NAME})
|
||||
find_program(MSVC_LIB_EXE ${MSVC_LIB_EXE})
|
||||
endif()
|
||||
if(MSVC_LIB_EXE)
|
||||
message(STATUS "Found MSVC's lib tool: ${MSVC_LIB_EXE}")
|
||||
set(MDBX_NTDLL_EXTRA_IMPLIB ${CMAKE_CURRENT_BINARY_DIR}/mdbx_ntdll_extra.lib)
|
||||
add_custom_command(OUTPUT ${MDBX_NTDLL_EXTRA_IMPLIB}
|
||||
COMMENT "Create extra-import-library for ntdll.dll"
|
||||
MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/elements/ntdll.def"
|
||||
COMMAND ${MSVC_LIB_EXE} /def:"${CMAKE_CURRENT_SOURCE_DIR}/elements/ntdll.def" /out:"${MDBX_NTDLL_EXTRA_IMPLIB}" ${INITIAL_CMAKE_STATIC_LINKER_FLAGS})
|
||||
else()
|
||||
message(SEND_ERROR "MSVC's lib tool not found")
|
||||
endif()
|
||||
elseif(MINGW OR MINGW64)
|
||||
if(NOT DLLTOOL)
|
||||
# Find dlltool
|
||||
get_filename_component(GCC_NAME ${CMAKE_C_COMPILER} NAME)
|
||||
string(REPLACE gcc dlltool DLLTOOL_NAME ${GCC_NAME})
|
||||
find_program(DLLTOOL NAMES ${DLLTOOL_NAME})
|
||||
endif()
|
||||
if(DLLTOOL)
|
||||
message(STATUS "Found dlltool: ${DLLTOOL}")
|
||||
set(MDBX_NTDLL_EXTRA_IMPLIB "${CMAKE_CURRENT_BINARY_DIR}/mdbx_ntdll_extra.a")
|
||||
add_custom_command(OUTPUT ${MDBX_NTDLL_EXTRA_IMPLIB}
|
||||
COMMENT "Create extra-import-library for ntdll.dll"
|
||||
MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/elements/ntdll.def"
|
||||
COMMAND ${DLLTOOL} -d "${CMAKE_CURRENT_SOURCE_DIR}/elements/ntdll.def" -l "${MDBX_NTDLL_EXTRA_IMPLIB}")
|
||||
else()
|
||||
message(SEND_ERROR "dlltool not found")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries(mdbx ${MDBX_LIBDEP_MODE} ${CMAKE_THREAD_LIBS_INIT})
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
target_link_libraries(mdbx ${MDBX_LIBDEP_MODE} ntdll.lib)
|
||||
if(MDBX_NTDLL_EXTRA_IMPLIB)
|
||||
# LY: Sometimes Cmake requires a nightmarish magic for simple things.
|
||||
# 1) create a target out of the library compilation result
|
||||
add_custom_target(ntdll_extra_target DEPENDS ${MDBX_NTDLL_EXTRA_IMPLIB})
|
||||
# 2) create an library target out of the library compilation result
|
||||
add_library(ntdll_extra STATIC IMPORTED GLOBAL)
|
||||
add_dependencies(ntdll_extra ntdll_extra_target)
|
||||
# 3) specify where the library is (and where to find the headers)
|
||||
set_target_properties(ntdll_extra
|
||||
PROPERTIES
|
||||
IMPORTED_LOCATION ${MDBX_NTDLL_EXTRA_IMPLIB})
|
||||
target_link_libraries(mdbx ${MDBX_LIBDEP_MODE} ntdll_extra)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_target_properties(mdbx PROPERTIES
|
||||
INTERPROCEDURAL_OPTIMIZATION $<BOOL:${INTERPROCEDURAL_OPTIMIZATION}>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
#endif
|
||||
#if MDBX_DISABLE_GNU_SOURCE
|
||||
#undef _GNU_SOURCE
|
||||
#elif defined(__linux__) || defined(__gnu_linux__)
|
||||
#elif ( defined(__linux__) || defined(__gnu_linux__) ) && !defined(_GNU_SOURCE)
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -54,18 +54,19 @@
|
|||
catch(const std::exception& ex) \
|
||||
{ \
|
||||
(void)(ex); \
|
||||
LOG_ERROR("Exception at [" << location << "], what=" << ex.what()); \
|
||||
custom_code; \
|
||||
LOG_ERROR("Exception at [" << location << "], what=" << ex.what()); \
|
||||
return return_val; \
|
||||
} \
|
||||
catch(...) \
|
||||
{ \
|
||||
LOG_ERROR("Exception at [" << location << "], generic exception \"...\""); \
|
||||
custom_code; \
|
||||
LOG_ERROR("Exception at [" << location << "], generic exception \"...\""); \
|
||||
return return_val; \
|
||||
}
|
||||
#define CATCH_ENTRY(location, return_val) CATCH_ENTRY_CUSTOM(location, (void)0, return_val)
|
||||
#define CATCH_ENTRY2(return_val) CATCH_ENTRY_CUSTOM(LOCATION_SS, (void)0, return_val)
|
||||
#define CATCH_ENTRY_CUSTOM2(custom_code, return_val) CATCH_ENTRY_CUSTOM(LOCATION_SS, custom_code, return_val)
|
||||
|
||||
#define CATCH_ENTRY_L0(location, return_val) CATCH_ENTRY(location, return_val)
|
||||
#define CATCH_ENTRY_L1(location, return_val) CATCH_ENTRY(location, return_val)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/any.hpp>
|
||||
#include "include_base_utils.h"
|
||||
#include "auto_val_init.h"
|
||||
|
||||
|
|
@ -273,6 +274,21 @@ namespace misc_utils
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t get_avg() const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_lock);
|
||||
if (!queued_items.size())
|
||||
return 0;
|
||||
|
||||
uint64_t summ = 0;
|
||||
for (const auto& item : queued_items)
|
||||
{
|
||||
summ += *item.first;
|
||||
}
|
||||
|
||||
return summ / queued_items.size();
|
||||
}
|
||||
|
||||
template<typename key_t, typename associated_data_t>
|
||||
friend std::ostream & operator<< (std::ostream &out, median_helper<key_t, associated_data_t> const &mh);
|
||||
}; // class median_helper
|
||||
|
|
@ -291,26 +307,25 @@ namespace misc_utils
|
|||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
template<class type_vec_type>
|
||||
type_vec_type median(std::vector<type_vec_type> &v)
|
||||
template<typename container_t>
|
||||
typename container_t::value_type median(container_t &v)
|
||||
{
|
||||
//CRITICAL_REGION_LOCAL(m_lock);
|
||||
typename container_t::value_type median{};
|
||||
if(v.empty())
|
||||
return boost::value_initialized<type_vec_type>();
|
||||
return median;
|
||||
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;
|
||||
auto median_it = v.begin() + v.size() / 2;
|
||||
std::nth_element(v.begin(), median_it, v.end());
|
||||
median = *median_it;
|
||||
if (v.size() % 2 == 0)
|
||||
{
|
||||
auto max_it = std::max_element(v.begin(), median_it); // it's garanteed that after nth_element() the necessary element is in this interval
|
||||
median = (median + *max_it) / 2; // average of [size/2-1] and [size/2] elements
|
||||
}
|
||||
|
||||
return median;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
|
@ -372,6 +387,11 @@ namespace misc_utils
|
|||
virtual void do_call(){};
|
||||
};
|
||||
|
||||
template<typename param_t>
|
||||
struct call_basic_param
|
||||
{
|
||||
virtual void do_call(param_t& p) {};
|
||||
};
|
||||
|
||||
template<typename t_callback>
|
||||
struct call_specific: public call_basic
|
||||
|
|
@ -386,12 +406,34 @@ namespace misc_utils
|
|||
t_callback m_cb;
|
||||
};
|
||||
|
||||
template<typename param_t, typename t_callback>
|
||||
struct call_specific_param : public call_basic_param<param_t>
|
||||
{
|
||||
call_specific_param(t_callback cb) :m_cb(cb)
|
||||
{}
|
||||
virtual void do_call(const param_t& p)
|
||||
{
|
||||
m_cb(p);
|
||||
}
|
||||
private:
|
||||
t_callback m_cb;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename t_callback>
|
||||
auto build_abstract_callback(t_callback cb) -> std::shared_ptr<call_basic>
|
||||
{
|
||||
return std::shared_ptr<call_basic>(new call_specific<t_callback>(cb));
|
||||
}
|
||||
|
||||
|
||||
template<typename param_t, typename t_callback>
|
||||
auto build_abstract_callback_param(t_callback cb) -> std::shared_ptr<call_basic_param<param_t>>
|
||||
{
|
||||
return std::shared_ptr<call_basic_param<param_t>>(new call_specific_param<param_t, t_callback>(cb));
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class callback_type>
|
||||
|
|
@ -427,6 +469,71 @@ namespace misc_utils
|
|||
return res.first;
|
||||
}
|
||||
|
||||
|
||||
class events_dispatcher
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
template<typename param_t>
|
||||
struct callback_entry
|
||||
{
|
||||
std::shared_ptr<epee::misc_utils::call_basic_param<const param_t> > m_cb;
|
||||
};
|
||||
|
||||
std::map<std::type_index, boost::any> m_callbacks;
|
||||
|
||||
template<typename param_t, typename callback_t>
|
||||
void SUBSCIRBE_DEBUG_EVENT(callback_t cb)
|
||||
{
|
||||
std::type_index ti = typeid(param_t);
|
||||
auto it = m_callbacks.find(ti);
|
||||
if (it != m_callbacks.end())
|
||||
{
|
||||
throw std::runtime_error("Handler for this type already registered");
|
||||
}
|
||||
|
||||
callback_entry<const param_t> cb_entry = { epee::misc_utils::build_abstract_callback_param<const param_t>(cb) };
|
||||
|
||||
m_callbacks[ti] = cb_entry;
|
||||
}
|
||||
|
||||
template<typename param_t>
|
||||
void UNSUBSCRIBE_DEBUG_EVENT()
|
||||
{
|
||||
std::type_index ti = typeid(param_t);
|
||||
auto it = m_callbacks.find(ti);
|
||||
if (it != m_callbacks.end())
|
||||
{
|
||||
m_callbacks.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void UNSUBSCRIBE_ALL()
|
||||
{
|
||||
m_callbacks.clear();
|
||||
}
|
||||
|
||||
template<typename param_t>
|
||||
void RAISE_DEBUG_EVENT(const param_t& p)
|
||||
{
|
||||
std::type_index ti = typeid(param_t);
|
||||
auto it = m_callbacks.find(ti);
|
||||
if (it != m_callbacks.end())
|
||||
{
|
||||
callback_entry<const param_t >* pcallback_entry = boost::any_cast<callback_entry<const param_t >>(&it->second);
|
||||
if (!pcallback_entry)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error: registered tipe holding something else in boost::eny");
|
||||
}
|
||||
pcallback_entry->m_cb->do_call(p);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace misc_utils
|
||||
} // namespace epee
|
||||
|
||||
|
|
|
|||
|
|
@ -116,29 +116,29 @@ DISABLE_VS_WARNINGS(4100)
|
|||
|
||||
#define ENABLE_CHANNEL_BY_DEFAULT(ch_name) \
|
||||
static bool COMBINE(init_channel, __LINE__) UNUSED_ATTRIBUTE = epee::misc_utils::static_initializer([](){ \
|
||||
epee::log_space::log_singletone::enable_channel(ch_name); return true; \
|
||||
epee::log_space::log_singletone::enable_channel(ch_name, false); return true; \
|
||||
});
|
||||
|
||||
|
||||
|
||||
#if defined(ENABLE_LOGGING_INTERNAL)
|
||||
|
||||
#define LOG_PRINT_CHANNEL_NO_PREFIX2(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
#define LOG_PRINT_CHANNEL_NO_PREFIX2(log_channel, log_name, x, y) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
{TRY_ENTRY();std::stringstream ss________; ss________ << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str() , y, epee::log_space::console_color_default, false, log_name);CATCH_ALL_DO_NOTHING();}}
|
||||
|
||||
#define LOG_PRINT_CHANNEL_NO_PREFIX_NO_POSTFIX2(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
#define LOG_PRINT_CHANNEL_NO_PREFIX_NO_POSTFIX2(log_channel, log_name, x, y) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
{TRY_ENTRY();std::stringstream ss________; ss________ << x; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);CATCH_ALL_DO_NOTHING();}}
|
||||
|
||||
#define LOG_PRINT_CHANNEL_NO_POSTFIX2(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
#define LOG_PRINT_CHANNEL_NO_POSTFIX2(log_channel, log_name, x, y) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
{TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);CATCH_ALL_DO_NOTHING();}}
|
||||
|
||||
#define LOG_PRINT_CHANNEL2_CB(log_channel, log_name, x, y, cb) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
#define LOG_PRINT_CHANNEL2_CB(log_channel, log_name, x, y, cb) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
{TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);cb(ss________.str());CATCH_ALL_DO_NOTHING();}}
|
||||
|
||||
#define LOG_PRINT_CHANNEL_COLOR2_CB(log_channel, log_name, x, y, color, cb) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
#define LOG_PRINT_CHANNEL_COLOR2_CB(log_channel, log_name, x, y, color, cb) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
{TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, color, false, log_name); cb(ss________.str());CATCH_ALL_DO_NOTHING();}}
|
||||
|
||||
#define LOG_PRINT_CHANNEL_2_JORNAL(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
#define LOG_PRINT_CHANNEL_2_JORNAL(log_channel, log_name, x, y) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
{TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, true, log_name);CATCH_ALL_DO_NOTHING();}}
|
||||
|
||||
#define LOG_ERROR2_CB(log_name, x, cb) { \
|
||||
|
|
@ -556,8 +556,11 @@ namespace log_space
|
|||
else
|
||||
m_have_to_kill_console = false;
|
||||
|
||||
::AllocConsole();
|
||||
freopen("CONOUT$", "w", stdout);
|
||||
if (m_have_to_kill_console)
|
||||
{
|
||||
::AllocConsole();
|
||||
freopen("CONOUT$", "w", stdout);
|
||||
}
|
||||
std::cout.clear();
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1236,21 +1239,24 @@ namespace log_space
|
|||
return genabled_channels.find(ch_name) != genabled_channels.end();
|
||||
}
|
||||
|
||||
static void enable_channels(const std::string& channels_set)
|
||||
static void enable_channels(const std::string& channels_set, bool verbose = true)
|
||||
{
|
||||
std::set<std::string>& genabled_channels = get_enabled_channels();
|
||||
std::list<std::string> list_of_channels;
|
||||
boost::split(list_of_channels, channels_set, boost::is_any_of(",;: "), boost::token_compress_on);
|
||||
std::cout << "log channels: ";
|
||||
if (verbose)
|
||||
std::cout << "log channels: ";
|
||||
for (const auto& ch : list_of_channels)
|
||||
{
|
||||
genabled_channels.insert(ch);
|
||||
std::cout << ch << " ";
|
||||
if (verbose)
|
||||
std::cout << ch << " ";
|
||||
}
|
||||
std::cout << " enabled" << std::endl;
|
||||
if (verbose)
|
||||
std::cout << " enabled" << std::endl;
|
||||
}
|
||||
|
||||
static void enable_channel(const std::string& ch_name)
|
||||
static void enable_channel(const std::string& ch_name, bool verbose = true)
|
||||
{
|
||||
std::set<std::string>& genabled_channels = get_enabled_channels();
|
||||
//lazy synchronization: just replace with modified copy of whole set
|
||||
|
|
@ -1258,7 +1264,8 @@ namespace log_space
|
|||
enabled_channels_local.insert(ch_name);
|
||||
genabled_channels.swap(enabled_channels_local);
|
||||
#ifndef ANDROID_BUILD
|
||||
std::cout << "log channel '" << ch_name << "' enabled" << std::endl;
|
||||
if (verbose)
|
||||
std::cout << "log channel '" << ch_name << "' enabled" << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -29,13 +29,22 @@
|
|||
#include "serialization/keyvalue_serialization.h"
|
||||
#include "storages/portable_storage_template_helper.h"
|
||||
#include "http_base.h"
|
||||
#include "net/net_utils_base.h"
|
||||
|
||||
|
||||
|
||||
template<typename typename_t>
|
||||
typename_t get_documentation_json_struct()
|
||||
{
|
||||
return AUTO_VAL_INIT_T(typename_t);
|
||||
}
|
||||
|
||||
template<typename request_t, typename response_t>
|
||||
bool auto_doc_t(const std::string& prefix_name, std::string& generate_reference)
|
||||
{
|
||||
if (!generate_reference.size()) return true;
|
||||
request_t req = AUTO_VAL_INIT(req);
|
||||
response_t res = AUTO_VAL_INIT(res);
|
||||
request_t req = get_documentation_json_struct<request_t>();
|
||||
response_t res = get_documentation_json_struct<response_t>();
|
||||
std::stringstream ss;
|
||||
ss << prefix_name << ENDL
|
||||
<< "REQUEST: " << ENDL << epee::serialization::store_t_to_json(req) << ENDL << "--------------------------------" << ENDL
|
||||
|
|
@ -51,6 +60,20 @@ bool auto_doc(const std::string& prefix_name, std::string& generate_reference)
|
|||
return auto_doc_t<typename command_type_t::request, typename command_type_t::response>(prefix_name, generate_reference);
|
||||
}
|
||||
|
||||
namespace epee {
|
||||
namespace net_utils {
|
||||
namespace http {
|
||||
struct i_chain_handler
|
||||
{
|
||||
virtual bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, epee::net_utils::http::http_response_info& response_info,
|
||||
epee::net_utils::connection_context_base& m_conn_context, bool& call_found, std::string& generate_reference) = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define CHAIN_HTTP_TO_MAP2(context_type) bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, \
|
||||
epee::net_utils::http::http_response_info& response, \
|
||||
|
|
@ -73,6 +96,13 @@ bool auto_doc(const std::string& prefix_name, std::string& generate_reference)
|
|||
call_found = false; \
|
||||
if(false) return true; //just a stub to have "else if"
|
||||
|
||||
#define BEGIN_URI_MAP2_VIRTUAL() virtual bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, \
|
||||
epee::net_utils::http::http_response_info& response_info, \
|
||||
epee::net_utils::connection_context_base& m_conn_context, bool& call_found, std::string& generate_reference) { \
|
||||
call_found = false; \
|
||||
if(false) return true; //just a stub to have "else if"
|
||||
|
||||
|
||||
#define MAP_URI2(pattern, callback) else if(std::string::npos != query_info.m_URI.find(pattern)) return callback(query_info, response_info, m_conn_context);
|
||||
|
||||
#define MAP_URI_AUTO_XML2(s_pattern, callback_f, command_type) //TODO: don't think i ever again will use xml - ambiguous and "overtagged" format
|
||||
|
|
@ -117,6 +147,8 @@ bool auto_doc(const std::string& prefix_name, std::string& generate_reference)
|
|||
LOG_PRINT( "[HTTP/BIN][" << epee::string_tools::get_ip_string_from_int32(m_conn_context.m_remote_ip ) << "][" << query_info.m_URI << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); \
|
||||
}
|
||||
|
||||
#define CHAIN_TO_PHANDLER(pi_chain_handler) else if (pi_chain_handler && pi_chain_handler->handle_http_request_map(query_info, response_info, m_conn_context, call_found, generate_reference) && call_found) { return true;}
|
||||
|
||||
#define CHAIN_URI_MAP2(callback) else {callback(query_info, response_info, m_conn_context);call_found = true;}
|
||||
|
||||
#define END_URI_MAP2() return true;}
|
||||
|
|
@ -287,6 +319,7 @@ struct json_command_type_t
|
|||
#define MAP_JON_RPC_WE(method_name, callback_f, command_type) \
|
||||
else if(auto_doc<json_command_type_t<command_type>>("[" method_name "]", generate_reference) && callback_name == method_name) \
|
||||
{ \
|
||||
call_found = true; \
|
||||
PREPARE_OBJECTS_FROM_JSON(command_type) \
|
||||
epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \
|
||||
fail_resp.jsonrpc = "2.0"; \
|
||||
|
|
@ -304,6 +337,7 @@ struct json_command_type_t
|
|||
#define MAP_JON_RPC_WERI(method_name, callback_f, command_type) \
|
||||
else if(auto_doc<json_command_type_t<command_type>>("[" method_name "]", generate_reference) && callback_name == method_name) \
|
||||
{ \
|
||||
call_found = true; \
|
||||
PREPARE_OBJECTS_FROM_JSON(command_type) \
|
||||
epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \
|
||||
fail_resp.jsonrpc = "2.0"; \
|
||||
|
|
@ -321,6 +355,7 @@ struct json_command_type_t
|
|||
#define MAP_JON_RPC(method_name, callback_f, command_type) \
|
||||
else if(auto_doc<json_command_type_t<command_type>>(std::string("[") + method_name + "]", generate_reference) && callback_name == method_name) \
|
||||
{ \
|
||||
call_found = true; \
|
||||
PREPARE_OBJECTS_FROM_JSON(command_type) \
|
||||
if(!callback_f(req.params, resp.result, m_conn_context)) \
|
||||
{ \
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
|
||||
#include "net/http_server_cp2.h"
|
||||
#include "net/http_server_handlers_map2.h"
|
||||
|
|
@ -65,7 +65,7 @@ namespace epee
|
|||
bool res = m_net_server.init_server(bind_port, bind_ip);
|
||||
if(!res)
|
||||
{
|
||||
LOG_ERROR("Failed to bind server");
|
||||
LOG_ERROR("Failed to bind to " << bind_ip << ":" << bind_port);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -74,14 +74,14 @@ namespace epee
|
|||
bool run(size_t threads_count, bool wait = true)
|
||||
{
|
||||
//go to loop
|
||||
LOG_PRINT("Run net_service loop( " << threads_count << " threads)...", LOG_LEVEL_0);
|
||||
LOG_PRINT("Run net_service loop (" << threads_count << " threads)...", LOG_LEVEL_1);
|
||||
if(!m_net_server.run_server(threads_count, wait))
|
||||
{
|
||||
LOG_ERROR("Failed to run net tcp server!");
|
||||
}
|
||||
|
||||
if(wait)
|
||||
LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0);
|
||||
LOG_PRINT("net_service loop stopped.", LOG_LEVEL_1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -155,6 +155,13 @@ namespace net_utils
|
|||
{
|
||||
content.port = boost::lexical_cast<uint64_t>(result[6]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (content.schema == "http")
|
||||
content.port = 80;
|
||||
else if (content.schema == "https")
|
||||
content.port = 443;
|
||||
}
|
||||
if(result[7].matched)
|
||||
{
|
||||
content.uri = result[7];
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ namespace net_utils
|
|||
m_started(time(NULL))
|
||||
{}
|
||||
|
||||
connection_context_base(const connection_context_base& a) = default;
|
||||
|
||||
connection_context_base& operator=(const connection_context_base& a)
|
||||
{
|
||||
set_details(a.m_connection_id, a.m_remote_ip, a.m_remote_port, a.m_is_income);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright (c) 2006-2022, 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 "keyvalue_helpers.h"
|
||||
|
||||
|
||||
//should be done in global namespace
|
||||
#define KV_ENABLE_POD_SERIALIZATION_AS_HEX(type_name) \
|
||||
namespace epee \
|
||||
{ \
|
||||
namespace serialization \
|
||||
{ \
|
||||
template<class t_storage> \
|
||||
bool kv_serialize(const type_name& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) \
|
||||
{ \
|
||||
std::string s = epee::transform_t_pod_to_str(d); \
|
||||
return kv_serialize(s, stg, hparent_section, pname); \
|
||||
} \
|
||||
template<class t_storage> \
|
||||
bool kv_unserialize(type_name& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) \
|
||||
{ \
|
||||
std::string s; \
|
||||
bool r = kv_unserialize(s, stg, hparent_section, pname); \
|
||||
if (r) \
|
||||
{ \
|
||||
d = epee::transform_str_to_t_pod<type_name>(s); \
|
||||
} \
|
||||
return r; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
|
@ -62,6 +62,8 @@ namespace epee
|
|||
t_pod_type transform_str_to_t_pod(const std::string& a)
|
||||
{
|
||||
t_pod_type res = AUTO_VAL_INIT(res);
|
||||
if (a.empty())
|
||||
return res;
|
||||
if (!epee::string_tools::hex_to_pod(a, res))
|
||||
throw std::runtime_error(std::string("Unable to transform \"") + a + "\" to pod type " + typeid(t_pod_type).name());
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -429,6 +429,55 @@ namespace epee
|
|||
bool kv_unserialize(std::deque<t_type>& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname)
|
||||
{
|
||||
return kv_serialization_overloads_impl_is_base_serializable_types<boost::mpl::contains<base_serializable_types<t_storage>, typename std::remove_const<t_type>::type>::value>::kv_unserialize(d, stg, hparent_section, pname);
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
//boost::optional
|
||||
template<class t_type, class t_storage>
|
||||
bool kv_serialize(const boost::optional<t_type>& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname)
|
||||
{
|
||||
if(d != boost::none)
|
||||
{
|
||||
return kv_serialize(*d, stg, hparent_section, pname);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
template<class t_type, class t_storage>
|
||||
bool kv_unserialize(boost::optional<t_type>& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname)
|
||||
{
|
||||
d = t_type();
|
||||
bool r = kv_unserialize(*d, stg, hparent_section, pname);
|
||||
if (!r)
|
||||
{
|
||||
d = boost::none;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
//boost::shared_ptr
|
||||
template<class t_type, class t_storage>
|
||||
bool kv_serialize(const boost::shared_ptr<t_type>& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname)
|
||||
{
|
||||
if (d.get())
|
||||
{
|
||||
return kv_serialize(*d, stg, hparent_section, pname);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
template<class t_type, class t_storage>
|
||||
bool kv_unserialize(boost::shared_ptr<t_type>& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname)
|
||||
{
|
||||
d.reset();
|
||||
t_type* ptr = new t_type();
|
||||
bool r = kv_unserialize(*ptr, stg, hparent_section, pname);
|
||||
if (!r)
|
||||
{
|
||||
d.reset(ptr);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -29,11 +29,25 @@
|
|||
#include "portable_storage_template_helper.h"
|
||||
#include "net/http_base.h"
|
||||
#include "net/http_server_handlers_map2.h"
|
||||
#include "net/http_client.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace net_utils
|
||||
{
|
||||
|
||||
template<class t_response>
|
||||
bool get_http_json_t(const std::string& url, t_response& result_struct, unsigned int timeout = 5000, const std::string& method = "GET")
|
||||
{
|
||||
std::string body;
|
||||
if (!http::fetch_url(url, body, method, "", timeout))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return serialization::load_t_from_json(result_struct, body);
|
||||
}
|
||||
|
||||
|
||||
template<class t_request, class t_response, class t_transport>
|
||||
bool invoke_http_json_remote_command2(const std::string& url, t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& method = "GET")
|
||||
{
|
||||
|
|
@ -72,6 +86,8 @@ namespace epee
|
|||
if(!serialization::store_t_to_binary(out_struct, req_param))
|
||||
return false;
|
||||
|
||||
LOG_PRINT_L3("[HTTP_BIN] ---> " << "[" << &req_param << "][" << method << "][" << url << "] REQUEST BODY BASE64: " << ENDL << epee::string_encoding::base64_encode(req_param));
|
||||
|
||||
const http::http_response_info* pri = NULL;
|
||||
if(!invoke_request(url, transport, timeout, &pri, method, req_param))
|
||||
{
|
||||
|
|
@ -85,6 +101,8 @@ namespace epee
|
|||
return false;
|
||||
}
|
||||
|
||||
LOG_PRINT_L3("[HTTP_BIN] <--- " << "[" << &req_param << "][" << method << "][" << url << "] RESPONSE(" << pri->m_response_code << ") BODY BASE64: " << ENDL << epee::string_encoding::base64_encode(pri->m_body));
|
||||
|
||||
if(pri->m_response_code != 200)
|
||||
{
|
||||
LOG_PRINT_L1("Failed to invoke http request to " << url << ", wrong response code: " << pri->m_response_code);
|
||||
|
|
|
|||
|
|
@ -77,8 +77,7 @@ namespace epee
|
|||
bool insert_next_section(harray hSecArray, hsection& hinserted_childsection);
|
||||
//------------------------------------------------------------------------
|
||||
//delete entry (section, value or array)
|
||||
bool delete_entry(const std::string& pentry_name, hsection hparent_section = nullptr);
|
||||
|
||||
bool delete_entry(const std::string& pentry_name, hsection hparent_section = nullptr);
|
||||
//-------------------------------------------------------------------------------
|
||||
bool store_to_binary(binarybuffer& target);
|
||||
bool load_from_binary(const binarybuffer& target);
|
||||
|
|
@ -87,6 +86,8 @@ namespace epee
|
|||
bool dump_as_json(std::string& targetObj, size_t indent = 0, end_of_line_t eol = eol_crlf);
|
||||
bool load_from_json(const std::string& source);
|
||||
|
||||
template<typename cb_t>
|
||||
bool enum_entries(hsection hparent_section, cb_t cb);
|
||||
private:
|
||||
section m_root;
|
||||
hsection get_root_section() {return &m_root;}
|
||||
|
|
@ -384,6 +385,20 @@ namespace epee
|
|||
CATCH_ENTRY("portable_storage::insert_first_value", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<typename cb_t>
|
||||
bool portable_storage::enum_entries(hsection hparent_section, cb_t cb)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
if (!hparent_section) hparent_section = &m_root;
|
||||
for (const auto& e : hparent_section->m_entries)
|
||||
{
|
||||
if (!cb(e.first, e.second))
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::enum_entries", false);
|
||||
}
|
||||
|
||||
template<class t_value>
|
||||
bool portable_storage::insert_next_value(harray hval_array, const t_value& target)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
namespace epee
|
||||
{
|
||||
using namespace misc_utils::parse;
|
||||
namespace serialization
|
||||
{
|
||||
namespace json
|
||||
|
|
@ -86,7 +85,7 @@ namespace epee
|
|||
switch(*it)
|
||||
{
|
||||
case '"':
|
||||
match_string2(it, buf_end, name);
|
||||
misc_utils::parse::match_string2(it, buf_end, name);
|
||||
state = match_state_waiting_separator;
|
||||
break;
|
||||
case '}':
|
||||
|
|
@ -107,7 +106,7 @@ namespace epee
|
|||
if(*it == '"')
|
||||
{//just a named string value started
|
||||
std::string val;
|
||||
match_string2(it, buf_end, val);
|
||||
misc_utils::parse::match_string2(it, buf_end, val);
|
||||
//insert text value
|
||||
stg.set_value(name, val, current_section);
|
||||
state = match_state_wonder_after_value;
|
||||
|
|
@ -115,7 +114,7 @@ namespace epee
|
|||
{//just a named number value started
|
||||
std::string val;
|
||||
bool is_v_float = false;bool is_signed = false;
|
||||
match_number2(it, buf_end, val, is_v_float, is_signed);
|
||||
misc_utils::parse::match_number2(it, buf_end, val, is_v_float, is_signed);
|
||||
if(!is_v_float)
|
||||
{
|
||||
if(is_signed)
|
||||
|
|
@ -136,7 +135,7 @@ namespace epee
|
|||
}else if(isalpha(*it) )
|
||||
{// could be null, true or false
|
||||
std::string word;
|
||||
match_word2(it, buf_end, word);
|
||||
misc_utils::parse::match_word2(it, buf_end, word);
|
||||
if(boost::iequals(word, "null"))
|
||||
{
|
||||
state = match_state_wonder_after_value;
|
||||
|
|
@ -191,7 +190,7 @@ namespace epee
|
|||
{
|
||||
//mean array of strings
|
||||
std::string val;
|
||||
match_string2(it, buf_end, val);
|
||||
misc_utils::parse::match_string2(it, buf_end, val);
|
||||
h_array = stg.insert_first_value(name, val, current_section);
|
||||
CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values entry");
|
||||
state = match_state_array_after_value;
|
||||
|
|
@ -200,7 +199,7 @@ namespace epee
|
|||
{//array of numbers value started
|
||||
std::string val;
|
||||
bool is_v_float = false;bool is_signed_val = false;
|
||||
match_number2(it, buf_end, val, is_v_float, is_signed_val);
|
||||
misc_utils::parse::match_number2(it, buf_end, val, is_v_float, is_signed_val);
|
||||
if(!is_v_float)
|
||||
{
|
||||
int64_t nval = boost::lexical_cast<int64_t>(val);//bool res = string_tools::string_to_num_fast(val, nval);
|
||||
|
|
@ -222,7 +221,7 @@ namespace epee
|
|||
}else if(isalpha(*it) )
|
||||
{// array of booleans
|
||||
std::string word;
|
||||
match_word2(it, buf_end, word);
|
||||
misc_utils::parse::match_word2(it, buf_end, word);
|
||||
if(boost::iequals(word, "true"))
|
||||
{
|
||||
h_array = stg.insert_first_value(name, true, current_section);
|
||||
|
|
@ -266,7 +265,7 @@ namespace epee
|
|||
if(*it == '"')
|
||||
{
|
||||
std::string val;
|
||||
match_string2(it, buf_end, val);
|
||||
misc_utils::parse::match_string2(it, buf_end, val);
|
||||
bool res = stg.insert_next_value(h_array, val);
|
||||
CHECK_AND_ASSERT_THROW_MES(res, "failed to insert values");
|
||||
state = match_state_array_after_value;
|
||||
|
|
@ -277,7 +276,7 @@ namespace epee
|
|||
{//array of numbers value started
|
||||
std::string val;
|
||||
bool is_v_float = false;bool is_signed_val = false;
|
||||
match_number2(it, buf_end, val, is_v_float, is_signed_val);
|
||||
misc_utils::parse::match_number2(it, buf_end, val, is_v_float, is_signed_val);
|
||||
bool insert_res = false;
|
||||
if(!is_v_float)
|
||||
{
|
||||
|
|
@ -299,7 +298,7 @@ namespace epee
|
|||
if(isalpha(*it) )
|
||||
{// array of booleans
|
||||
std::string word;
|
||||
match_word2(it, buf_end, word);
|
||||
misc_utils::parse::match_word2(it, buf_end, word);
|
||||
if(boost::iequals(word, "true"))
|
||||
{
|
||||
bool r = stg.insert_next_value(h_array, true);
|
||||
|
|
|
|||
|
|
@ -129,7 +129,20 @@ POP_VS_WARNINGS
|
|||
template<typename from_type, typename to_type>
|
||||
struct convert_to_integral<from_type, to_type, false>
|
||||
{
|
||||
static void convert(const from_type& from, to_type& to)
|
||||
static void convert(const std::string& from, uint64_t& to)
|
||||
{
|
||||
//attempt to convert string to unsigned int
|
||||
try
|
||||
{
|
||||
to = std::stoull(from);
|
||||
}catch(...)
|
||||
{
|
||||
ASSERT_AND_THROW_WRONG_CONVERSION();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename from_type_t, typename to_type_t>
|
||||
static void convert(const from_type_t& from, to_type_t& to)
|
||||
{
|
||||
ASSERT_AND_THROW_WRONG_CONVERSION();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <cctype>
|
||||
#include "warnings.h"
|
||||
|
||||
|
||||
|
|
@ -310,7 +311,14 @@ namespace string_encoding
|
|||
return get_md5_as_hexstring(src.data(), src.size());
|
||||
}
|
||||
#endif
|
||||
|
||||
inline
|
||||
std::string toupper(std::string s)
|
||||
{
|
||||
std::transform(s.begin(), s.end(), s.begin(),
|
||||
[](unsigned char c) { return std::toupper(c); } // correct
|
||||
);
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,16 +23,12 @@
|
|||
// (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_TOOLS_H_
|
||||
#define _STRING_TOOLS_H_
|
||||
|
||||
//#include <objbase.h>
|
||||
#include <locale>
|
||||
#include <cstdlib>
|
||||
//#include <strsafe.h>
|
||||
#include <map>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
|
@ -212,7 +208,7 @@ namespace string_tools
|
|||
t_pod_type parse_tpod_from_hex_string(const std::string& str_hash)
|
||||
{
|
||||
t_pod_type t_pod = AUTO_VAL_INIT(t_pod);
|
||||
parse_tpod_from_hex_string(str_hash, t_pod);
|
||||
epee::string_tools::parse_tpod_from_hex_string(str_hash, t_pod); // using fully qualified name to avoid Argument-Dependent Lookup issues
|
||||
return t_pod;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
@ -322,13 +318,6 @@ POP_GCC_WARNINGS
|
|||
return true;
|
||||
}
|
||||
|
||||
/* template<typename t_type>
|
||||
bool get_xparam_from_command_line(const std::map<std::string, std::string>& res, const std::basic_string<typename t_string::value_type> & key, t_type& val)
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
template<class t_string, typename t_type>
|
||||
bool get_xparam_from_command_line(const std::map<t_string, t_string>& res, const t_string & key, t_type& val)
|
||||
{
|
||||
|
|
@ -803,6 +792,9 @@ POP_GCC_WARNINGS
|
|||
return buff;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} // namespace stringtools
|
||||
} // namwspace epee
|
||||
|
||||
namespace epst = epee::string_tools; // EPshort alias for convenience
|
||||
|
||||
#endif //_STRING_TOOLS_H_
|
||||
|
|
|
|||
|
|
@ -84,6 +84,8 @@ namespace epee
|
|||
template<typename t_proxy_object, typename t_proxy_lock_time_watching_policy>
|
||||
friend class locked_object_proxy;
|
||||
public:
|
||||
typedef std::shared_ptr<locked_object_proxy<t_object, lock_time_watching_policy>> lock_shared_ptr;
|
||||
|
||||
std::shared_ptr<locked_object_proxy<t_object, lock_time_watching_policy>> lock()
|
||||
{
|
||||
std::shared_ptr<locked_object_proxy<t_object, lock_time_watching_policy>> res;
|
||||
|
|
|
|||
|
|
@ -711,4 +711,4 @@ namespace epee
|
|||
#define EXCLUSIVE_CRITICAL_REGION_BEGIN(x) { EXCLUSIVE_CRITICAL_REGION_LOCAL(x)
|
||||
#define EXCLUSIVE_CRITICAL_REGION_END() }
|
||||
|
||||
}
|
||||
} // namespace epee
|
||||
|
|
|
|||
|
|
@ -12,9 +12,13 @@
|
|||
#define DISABLE_GCC_WARNING(w)
|
||||
#define DISABLE_CLANG_WARNING(w)
|
||||
#define DISABLE_GCC_AND_CLANG_WARNING(w)
|
||||
#define ATTRIBUTE_UNUSED
|
||||
|
||||
#else
|
||||
|
||||
|
||||
#define ATTRIBUTE_UNUSED __attribute__((unused))
|
||||
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
|
||||
#define PUSH_VS_WARNINGS
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ ENABLE_SHARED_PCH(currency_core CURRENCY_CORE)
|
|||
add_library(wallet ${WALLET})
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Android" )
|
||||
add_dependencies(wallet version ${PCH_LIB_NAME})
|
||||
target_link_libraries(wallet currency_core crypto common zlibstatic ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} android log)
|
||||
target_link_libraries(wallet currency_core crypto common zlibstatic ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} android log OpenSSL::SSL OpenSSL::Crypto)
|
||||
else()
|
||||
add_dependencies(wallet version ${PCH_LIB_NAME})
|
||||
ENABLE_SHARED_PCH(wallet WALLET)
|
||||
|
|
@ -162,19 +162,19 @@ target_link_libraries(currency_core lmdb mdbx)
|
|||
|
||||
add_executable(daemon ${DAEMON} ${P2P} ${CURRENCY_PROTOCOL})
|
||||
add_dependencies(daemon version)
|
||||
target_link_libraries(daemon rpc stratum currency_core crypto common libminiupnpc-static zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
target_link_libraries(daemon rpc stratum currency_core crypto common libminiupnpc-static zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||
ENABLE_SHARED_PCH(daemon DAEMON)
|
||||
ENABLE_SHARED_PCH_EXECUTABLE(daemon)
|
||||
|
||||
add_executable(connectivity_tool ${CONN_TOOL})
|
||||
add_dependencies(connectivity_tool version)
|
||||
target_link_libraries(connectivity_tool currency_core crypto common zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
target_link_libraries(connectivity_tool currency_core crypto common zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||
ENABLE_SHARED_PCH(connectivity_tool CONN_TOOL)
|
||||
ENABLE_SHARED_PCH_EXECUTABLE(connectivity_tool)
|
||||
|
||||
add_executable(simplewallet ${SIMPLEWALLET})
|
||||
add_dependencies(simplewallet version)
|
||||
target_link_libraries(simplewallet wallet rpc currency_core crypto common zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
target_link_libraries(simplewallet wallet rpc currency_core crypto common zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||
|
||||
ENABLE_SHARED_PCH(simplewallet SIMPLEWALLET)
|
||||
ENABLE_SHARED_PCH_EXECUTABLE(simplewallet)
|
||||
|
|
@ -199,7 +199,7 @@ if(BUILD_GUI)
|
|||
QT5_USE_MODULES(Zano WebEngineWidgets WebChannel)
|
||||
find_package(Qt5PrintSupport REQUIRED)
|
||||
|
||||
target_link_libraries(Zano wallet rpc currency_core crypto common zlibstatic ethash Qt5::WebEngineWidgets Qt5::PrintSupport ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
target_link_libraries(Zano wallet rpc currency_core crypto common zlibstatic ethash Qt5::WebEngineWidgets Qt5::PrintSupport ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||
if (UNIX AND NOT APPLE)
|
||||
target_link_libraries(Zano rt)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#define CHECK_PROJECT_NAME() std::string project_name = CURRENCY_NAME; ar & project_name; if(!(project_name == CURRENCY_NAME) ) {throw std::runtime_error(std::string("wrong storage file: project name in file: ") + project_name + ", expected: " + CURRENCY_NAME );}
|
||||
|
||||
|
||||
|
||||
namespace tools
|
||||
{
|
||||
template<class t_object>
|
||||
|
|
|
|||
47
src/common/boost_serialization_maps.h
Normal file
47
src/common/boost_serialization_maps.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) 2014-2022 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define BEGIN_BOOST_SERIALIZATION() template <class t_archive> inline void serialize(t_archive &_arch, const unsigned int ver) {
|
||||
|
||||
template<size_t A, size_t B> struct TAssertEquality {
|
||||
static_assert(A == B, "Serialization map is not updated, sizeof() missmatch");
|
||||
static constexpr bool _cResult = (A == B);
|
||||
};
|
||||
|
||||
//experemental feature: self-validated serialization map, needed to not forget add new members to serialization maps
|
||||
#define BEGIN_BOOST_SERIALIZATION_SV(sz) BEGIN_BOOST_SERIALIZATION() \
|
||||
static constexpr bool _cIsEqual = TAssertEquality<sz, sizeof(*this)>::_cResult;
|
||||
|
||||
|
||||
|
||||
#define BOOST_SERIALIZE(x) _arch & x;
|
||||
#define BOOST_SERIALIZE_BASE_CLASS(class_type) _arch & static_cast<class_type&>(*this);
|
||||
|
||||
#define BOOST_END_VERSION_UNDER(x) \
|
||||
if(ver < x ) {return;}
|
||||
|
||||
#define END_BOOST_SERIALIZATION() }
|
||||
|
||||
|
||||
/*
|
||||
example of use:
|
||||
|
||||
struct tx_extra_info
|
||||
{
|
||||
crypto::public_key m_tx_pub_key;
|
||||
extra_alias_entry m_alias;
|
||||
std::string m_user_data_blob;
|
||||
extra_attachment_info m_attachment_info;
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(m_tx_pub_key)
|
||||
BOOST_SERIALIZE(m_alias)
|
||||
if(ver < xxx) return;
|
||||
BOOST_SERIALIZE(m_user_data_blob)
|
||||
BOOST_SERIALIZE(m_attachment_info)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
*/
|
||||
|
|
@ -137,11 +137,17 @@ namespace tools
|
|||
|
||||
STACKFRAME64 frame;
|
||||
memset(&frame, 0, sizeof frame);
|
||||
#ifndef _M_ARM64
|
||||
frame.AddrPC.Offset = context.Rip;
|
||||
#endif
|
||||
frame.AddrPC.Mode = AddrModeFlat;
|
||||
#ifndef _M_ARM64
|
||||
frame.AddrStack.Offset = context.Rsp;
|
||||
#endif
|
||||
frame.AddrStack.Mode = AddrModeFlat;
|
||||
#ifndef _M_ARM64
|
||||
frame.AddrFrame.Offset = context.Rbp;
|
||||
#endif
|
||||
frame.AddrFrame.Mode = AddrModeFlat;
|
||||
|
||||
IMAGEHLP_LINE64 line = { 0 };
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ namespace command_line
|
|||
|
||||
const arg_descriptor<bool> arg_no_predownload ( "no-predownload", "Do not pre-download blockchain database");
|
||||
const arg_descriptor<bool> arg_force_predownload ( "force-predownload", "Pre-download blockchain database regardless of it's status");
|
||||
const arg_descriptor<std::string> arg_process_predownload_from_path("predownload-from-local-path", "Instead of downloading file use downloaded local file");
|
||||
const arg_descriptor<bool> arg_validate_predownload ( "validate-predownload", "Paranoid mode, re-validate each block from pre-downloaded database and rebuild own database");
|
||||
const arg_descriptor<std::string> arg_predownload_link ( "predownload-link", "Override url for blockchain database pre-downloading");
|
||||
|
||||
|
|
|
|||
|
|
@ -229,6 +229,7 @@ namespace command_line
|
|||
extern const arg_descriptor<std::string> arg_db_engine;
|
||||
extern const arg_descriptor<bool> arg_no_predownload;
|
||||
extern const arg_descriptor<bool> arg_force_predownload;
|
||||
extern const arg_descriptor<std::string> arg_process_predownload_from_path;
|
||||
extern const arg_descriptor<bool> arg_validate_predownload;
|
||||
extern const arg_descriptor<std::string> arg_predownload_link;
|
||||
extern const arg_descriptor<std::string> arg_deeplink;
|
||||
|
|
|
|||
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright (c) 2014-2018 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include <boost/serialization/utility.hpp>
|
||||
#include <boost/serialization/variant.hpp>
|
||||
#include <boost/serialization/set.hpp>
|
||||
#include <boost/serialization/map.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/serialization/is_bitwise_serializable.hpp>
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
//---------------------------------------------------
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, crypto::public_key &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & reinterpret_cast<char (&)[sizeof(crypto::public_key)]>(x);
|
||||
}
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, crypto::secret_key &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & reinterpret_cast<char (&)[sizeof(crypto::secret_key)]>(x);
|
||||
}
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, crypto::key_derivation &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & reinterpret_cast<char (&)[sizeof(crypto::key_derivation)]>(x);
|
||||
}
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, crypto::key_image &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & reinterpret_cast<char (&)[sizeof(crypto::key_image)]>(x);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, crypto::signature &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & reinterpret_cast<char (&)[sizeof(crypto::signature)]>(x);
|
||||
}
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, crypto::hash &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & reinterpret_cast<char (&)[sizeof(crypto::hash)]>(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//}
|
||||
300
src/common/crypto_serialization.h
Normal file
300
src/common/crypto_serialization.h
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#pragma once
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include <boost/serialization/utility.hpp>
|
||||
#include <boost/serialization/variant.hpp>
|
||||
#include <boost/serialization/set.hpp>
|
||||
#include <boost/serialization/map.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/serialization/is_bitwise_serializable.hpp>
|
||||
|
||||
#include "serialization/serialization.h"
|
||||
#include "serialization/debug_archive.h"
|
||||
#include "crypto/chacha8.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "crypto/range_proofs.h"
|
||||
#include "crypto/clsag.h"
|
||||
#include "crypto/zarcanum.h"
|
||||
#include "crypto/one_out_of_many_proofs.h"
|
||||
#include "boost_serialization_maps.h"
|
||||
#include "serialization/keyvalue_enable_POD_serialize_as_string.h"
|
||||
//
|
||||
// binary serialization
|
||||
//
|
||||
|
||||
namespace crypto
|
||||
{
|
||||
struct bpp_signature_serialized : public bpp_signature
|
||||
{
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(L)
|
||||
FIELD(R)
|
||||
FIELD(A0)
|
||||
FIELD(A)
|
||||
FIELD(B)
|
||||
FIELD(r)
|
||||
FIELD(s)
|
||||
FIELD(delta)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(L)
|
||||
BOOST_SERIALIZE(R)
|
||||
BOOST_SERIALIZE(A0)
|
||||
BOOST_SERIALIZE(A)
|
||||
BOOST_SERIALIZE(B)
|
||||
BOOST_SERIALIZE(r)
|
||||
BOOST_SERIALIZE(s)
|
||||
BOOST_SERIALIZE(delta)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct bppe_signature_serialized : public bppe_signature
|
||||
{
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(L)
|
||||
FIELD(R)
|
||||
FIELD(A0)
|
||||
FIELD(A)
|
||||
FIELD(B)
|
||||
FIELD(r)
|
||||
FIELD(s)
|
||||
FIELD(delta_1)
|
||||
FIELD(delta_2)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(L)
|
||||
BOOST_SERIALIZE(R)
|
||||
BOOST_SERIALIZE(A0)
|
||||
BOOST_SERIALIZE(A)
|
||||
BOOST_SERIALIZE(B)
|
||||
BOOST_SERIALIZE(r)
|
||||
BOOST_SERIALIZE(s)
|
||||
BOOST_SERIALIZE(delta_1)
|
||||
BOOST_SERIALIZE(delta_2)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct CLSAG_GG_signature_serialized : public CLSAG_GG_signature
|
||||
{
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(c)
|
||||
FIELD((std::vector<scalar_t>&)(r))
|
||||
FIELD(K1)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(c)
|
||||
BOOST_SERIALIZE((std::vector<scalar_t>&)(r))
|
||||
BOOST_SERIALIZE(K1)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct CLSAG_GGX_signature_serialized : public CLSAG_GGX_signature
|
||||
{
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(c)
|
||||
FIELD((std::vector<scalar_t>&)(r_g))
|
||||
FIELD((std::vector<scalar_t>&)(r_x))
|
||||
FIELD(K1)
|
||||
FIELD(K2)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(c)
|
||||
BOOST_SERIALIZE((std::vector<scalar_t>&)(r_g))
|
||||
BOOST_SERIALIZE((std::vector<scalar_t>&)(r_x))
|
||||
BOOST_SERIALIZE(K1)
|
||||
BOOST_SERIALIZE(K2)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct CLSAG_GGXXG_signature_serialized : public CLSAG_GGXXG_signature
|
||||
{
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(c)
|
||||
FIELD_N("r_g", (std::vector<scalar_t>&)(r_g))
|
||||
FIELD_N("r_x", (std::vector<scalar_t>&)(r_x))
|
||||
FIELD(K1)
|
||||
FIELD(K2)
|
||||
FIELD(K3)
|
||||
FIELD(K4)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(c)
|
||||
BOOST_SERIALIZE((std::vector<scalar_t>&)(r_g))
|
||||
BOOST_SERIALIZE((std::vector<scalar_t>&)(r_x))
|
||||
BOOST_SERIALIZE(K1)
|
||||
BOOST_SERIALIZE(K2)
|
||||
BOOST_SERIALIZE(K3)
|
||||
BOOST_SERIALIZE(K4)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct vector_UG_aggregation_proof_serialized : public vector_UG_aggregation_proof
|
||||
{
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(amount_commitments_for_rp_aggregation)
|
||||
FIELD((std::vector<scalar_t>&)(y0s))
|
||||
FIELD((std::vector<scalar_t>&)(y1s))
|
||||
FIELD(c)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(amount_commitments_for_rp_aggregation)
|
||||
BOOST_SERIALIZE((std::vector<scalar_t>&)(y0s))
|
||||
BOOST_SERIALIZE((std::vector<scalar_t>&)(y1s))
|
||||
BOOST_SERIALIZE(c)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct linear_composition_proof_s : public linear_composition_proof
|
||||
{
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(c)
|
||||
FIELD(y0)
|
||||
FIELD(y1)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(c)
|
||||
BOOST_SERIALIZE(y0)
|
||||
BOOST_SERIALIZE(y1)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct generic_schnorr_sig_s : public generic_schnorr_sig
|
||||
{
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(c)
|
||||
FIELD(y)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(c)
|
||||
BOOST_SERIALIZE(y)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct generic_double_schnorr_sig_s : public generic_double_schnorr_sig
|
||||
{
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(c)
|
||||
FIELD(y0)
|
||||
FIELD(y1)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(c)
|
||||
BOOST_SERIALIZE(y0)
|
||||
BOOST_SERIALIZE(y1)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct BGE_proof_s : public BGE_proof
|
||||
{
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(A)
|
||||
FIELD(B)
|
||||
FIELD(Pk)
|
||||
FIELD_N("f", (std::vector<scalar_t>&)(f))
|
||||
FIELD(y)
|
||||
FIELD(z)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(A)
|
||||
BOOST_SERIALIZE(B)
|
||||
BOOST_SERIALIZE(Pk)
|
||||
BOOST_SERIALIZE(f)
|
||||
BOOST_SERIALIZE(y)
|
||||
BOOST_SERIALIZE(z)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
} // namespace crypto
|
||||
|
||||
BLOB_SERIALIZER(crypto::chacha8_iv);
|
||||
BLOB_SERIALIZER(crypto::hash);
|
||||
BLOB_SERIALIZER(crypto::public_key);
|
||||
BLOB_SERIALIZER(crypto::secret_key);
|
||||
BLOB_SERIALIZER(crypto::key_derivation);
|
||||
BLOB_SERIALIZER(crypto::key_image);
|
||||
BLOB_SERIALIZER(crypto::signature);
|
||||
BLOB_SERIALIZER(crypto::scalar_t);
|
||||
BLOB_SERIALIZER(crypto::point_t);
|
||||
|
||||
VARIANT_TAG(debug_archive, crypto::hash, "hash");
|
||||
VARIANT_TAG(debug_archive, crypto::public_key, "public_key");
|
||||
VARIANT_TAG(debug_archive, crypto::secret_key, "secret_key");
|
||||
VARIANT_TAG(debug_archive, crypto::key_derivation, "key_derivation");
|
||||
VARIANT_TAG(debug_archive, crypto::key_image, "key_image");
|
||||
VARIANT_TAG(debug_archive, crypto::signature, "signature");
|
||||
|
||||
|
||||
//
|
||||
// Key-value serialization
|
||||
//
|
||||
|
||||
KV_ENABLE_POD_SERIALIZATION_AS_HEX(crypto::scalar_t);
|
||||
KV_ENABLE_POD_SERIALIZATION_AS_HEX(crypto::hash);
|
||||
|
||||
//
|
||||
// Boost serialization
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
//---------------------------------------------------
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, crypto::public_key &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & reinterpret_cast<char (&)[sizeof(crypto::public_key)]>(x);
|
||||
}
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, crypto::secret_key &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & reinterpret_cast<char (&)[sizeof(crypto::secret_key)]>(x);
|
||||
}
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, crypto::key_derivation &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & reinterpret_cast<char (&)[sizeof(crypto::key_derivation)]>(x);
|
||||
}
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, crypto::key_image &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & reinterpret_cast<char (&)[sizeof(crypto::key_image)]>(x);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, crypto::signature &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & reinterpret_cast<char (&)[sizeof(crypto::signature)]>(x);
|
||||
}
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, crypto::hash &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & reinterpret_cast<char (&)[sizeof(crypto::hash)]>(x);
|
||||
}
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, crypto::scalar_t &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & reinterpret_cast<char (&)[sizeof(crypto::scalar_t)]>(x);
|
||||
}
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, crypto::point_t &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & reinterpret_cast<char (&)[sizeof(crypto::point_t)]>(x);
|
||||
}
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
|
@ -291,6 +291,10 @@ namespace tools
|
|||
|
||||
if (res == MDB_NOTFOUND)
|
||||
return false;
|
||||
if (res != MDB_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_get, h: " << h << ", ks: " << ks);
|
||||
res_buff.assign((const char*)data.mv_data, data.mv_size);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../currency_core/basic_api_response_codes.h"
|
||||
|
||||
#define API_RETURN_CODE_OK BASIC_RESPONSE_STATUS_OK
|
||||
#define API_RETURN_CODE_FAIL BASIC_RESPONSE_STATUS_FAILED
|
||||
|
|
@ -23,6 +24,7 @@
|
|||
#define API_RETURN_CODE_WALLET_WRONG_ID "WALLET_WRONG_ID"
|
||||
#define API_RETURN_CODE_WALLET_WATCH_ONLY_NOT_SUPPORTED "WALLET_WATCH_ONLY_NOT_SUPPORTED"
|
||||
#define API_RETURN_CODE_WALLET_AUDITABLE_NOT_SUPPORTED "WALLET_AUDITABLE_NOT_SUPPORTED"
|
||||
#define API_RETURN_CODE_WALLET_FEE_TOO_LOW "API_RETURN_CODE_WALLET_FEE_TOO_LOW"
|
||||
#define API_RETURN_CODE_FILE_NOT_FOUND "FILE_NOT_FOUND"
|
||||
#define API_RETURN_CODE_ALREADY_EXISTS "ALREADY_EXISTS"
|
||||
#define API_RETURN_CODE_CANCELED "CANCELED"
|
||||
|
|
@ -40,4 +42,5 @@
|
|||
#define API_RETURN_CODE_TX_IS_TOO_BIG "TX_IS_TOO_BIG"
|
||||
#define API_RETURN_CODE_TX_REJECTED "TX_REJECTED"
|
||||
#define API_RETURN_CODE_HTLC_ORIGIN_HASH_MISSMATCHED "HTLC_ORIGIN_HASH_MISSMATCHED"
|
||||
#define API_RETURN_CODE_WRAP "WRAP"
|
||||
#define API_RETURN_CODE_WRAP "WRAP"
|
||||
#define API_RETURN_CODE_MISSING_ZC_INPUTS "MISSING_ZC_INPUTS"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2019 Zano Project
|
||||
// Copyright (c) 2019-2022 Zano Project
|
||||
|
||||
// Note: class udp_blocking_client is a slightly modified version of an example
|
||||
// taken from https://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/example/timeouts/blocking_udp_client.cpp
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/ip/udp.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <epee/include/misc_log_ex.h>
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ namespace tools
|
|||
};
|
||||
|
||||
#ifndef TESTNET
|
||||
static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.42.247/pre-download/zano_mdbx_95_2200000.pak", "c3bd64c62495c3f266759750952519f13f32fc161b59547beaa8202b6e26d516", 2628767033, 5100195840 };
|
||||
static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.42.247/pre-download/zano_lmdb_95_2200000.pak", "fcbf0ab3b23836e1a51fa675e719900fb94110cfb74790b3323cebce7fb9f5bd", 3426025872, 4954472448 };
|
||||
static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.42.247/pre-download/zano_mdbx_95_2500000.pak", "8ffa2cb4213f4f96f97033c65a9e52bc350f683237808597784e79b24d5bfee7", 3242348793, 5905489920 };
|
||||
static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.42.247/pre-download/zano_lmdb_95_2500000.pak", "5509650e12c8f901e6731a2bfaf3abfd64409e3e1366d3d94cd11db8beddb0c3", 4239505801, 5893566464 };
|
||||
#else
|
||||
static constexpr pre_download_entry c_pre_download_mdbx = { "", "", 0, 0 };
|
||||
static constexpr pre_download_entry c_pre_download_lmdb = { "", "", 0, 0 };
|
||||
|
|
@ -50,6 +50,7 @@ namespace tools
|
|||
|
||||
boost::system::error_code ec;
|
||||
uint64_t sz = boost::filesystem::file_size(db_main_file_path, ec);
|
||||
if (ec) sz = 0;
|
||||
bool flag_force_predownload = command_line::has_arg(vm, command_line::arg_force_predownload);
|
||||
if (pre_download.unpacked_size == 0 || !(ec || (pre_download.unpacked_size > sz && pre_download.unpacked_size - sz > pre_download_min_size_difference) || flag_force_predownload) )
|
||||
{
|
||||
|
|
@ -59,53 +60,59 @@ namespace tools
|
|||
|
||||
// okay, let's download
|
||||
|
||||
|
||||
std::string downloading_file_path = db_main_file_path + ".download";
|
||||
|
||||
LOG_PRINT_MAGENTA("Trying to download blockchain database from " << url << " ...", LOG_LEVEL_0);
|
||||
epee::net_utils::http::interruptible_http_client cl;
|
||||
|
||||
crypto::stream_cn_hash hash_stream;
|
||||
auto last_update = std::chrono::system_clock::now();
|
||||
|
||||
auto cb = [&hash_stream, &last_update, &cb_should_stop](const std::string& buff, uint64_t total_bytes, uint64_t received_bytes)
|
||||
if (!command_line::has_arg(vm, command_line::arg_process_predownload_from_path))
|
||||
{
|
||||
if (cb_should_stop(total_bytes, received_bytes))
|
||||
|
||||
LOG_PRINT_MAGENTA("Trying to download blockchain database from " << url << " ...", LOG_LEVEL_0);
|
||||
epee::net_utils::http::interruptible_http_client cl;
|
||||
|
||||
crypto::stream_cn_hash hash_stream;
|
||||
auto last_update = std::chrono::system_clock::now();
|
||||
|
||||
auto cb = [&hash_stream, &last_update, &cb_should_stop](const std::string& buff, uint64_t total_bytes, uint64_t received_bytes)
|
||||
{
|
||||
LOG_PRINT_MAGENTA(ENDL << "Interrupting download", LOG_LEVEL_0);
|
||||
return false;
|
||||
if (cb_should_stop(total_bytes, received_bytes))
|
||||
{
|
||||
LOG_PRINT_MAGENTA(ENDL << "Interrupting download", LOG_LEVEL_0);
|
||||
return false;
|
||||
}
|
||||
|
||||
hash_stream.update(buff.data(), buff.size());
|
||||
|
||||
auto dif = std::chrono::system_clock::now() - last_update;
|
||||
if (dif >= std::chrono::milliseconds(300))
|
||||
{
|
||||
boost::io::ios_flags_saver ifs(std::cout);
|
||||
std::cout << "Received " << received_bytes / 1048576 << " of " << total_bytes / 1048576 << " MiB ( " << std::fixed << std::setprecision(1) << 100.0 * received_bytes / total_bytes << " %)\r";
|
||||
last_update = std::chrono::system_clock::now();
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
tools::create_directories_if_necessary(working_folder);
|
||||
r = cl.download_and_unzip(cb, downloading_file_path, url, 5000 /* timout */, "GET", std::string(), 30 /* fails count */);
|
||||
if (!r)
|
||||
{
|
||||
LOG_PRINT_RED("Downloading failed", LOG_LEVEL_0);
|
||||
return !flag_force_predownload; // fatal error only if force-predownload
|
||||
}
|
||||
|
||||
hash_stream.update(buff.data(), buff.size());
|
||||
|
||||
auto dif = std::chrono::system_clock::now() - last_update;
|
||||
if (dif >= std::chrono::milliseconds(300))
|
||||
crypto::hash data_hash = hash_stream.calculate_hash();
|
||||
if (epee::string_tools::pod_to_hex(data_hash) != pre_download.hash)
|
||||
{
|
||||
boost::io::ios_flags_saver ifs(std::cout);
|
||||
std::cout << "Received " << received_bytes / 1048576 << " of " << total_bytes / 1048576 << " MiB ( " << std::fixed << std::setprecision(1) << 100.0 * received_bytes / total_bytes << " %)\r";
|
||||
last_update = std::chrono::system_clock::now();
|
||||
LOG_ERROR("hash missmatch in downloaded file, got: " << epee::string_tools::pod_to_hex(data_hash) << ", expected: " << pre_download.hash);
|
||||
return !flag_force_predownload; // fatal error only if force-predownload
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
tools::create_directories_if_necessary(working_folder);
|
||||
r = cl.download_and_unzip(cb, downloading_file_path, url, 5000 /* timout */, "GET", std::string(), 30 /* fails count */);
|
||||
if (!r)
|
||||
{
|
||||
LOG_PRINT_RED("Downloading failed", LOG_LEVEL_0);
|
||||
return !flag_force_predownload; // fatal error only if force-predownload
|
||||
LOG_PRINT_GREEN("Download succeeded, hash " << pre_download.hash << " is correct", LOG_LEVEL_0);
|
||||
}
|
||||
|
||||
crypto::hash data_hash = hash_stream.calculate_hash();
|
||||
if (epee::string_tools::pod_to_hex(data_hash) != pre_download.hash)
|
||||
else
|
||||
{
|
||||
LOG_ERROR("hash missmatch in downloaded file, got: " << epee::string_tools::pod_to_hex(data_hash) << ", expected: " << pre_download.hash);
|
||||
return !flag_force_predownload; // fatal error only if force-predownload
|
||||
downloading_file_path = command_line::get_arg(vm, command_line::arg_process_predownload_from_path);
|
||||
}
|
||||
|
||||
LOG_PRINT_GREEN("Download succeeded, hash " << pre_download.hash << " is correct" , LOG_LEVEL_0);
|
||||
|
||||
if (!command_line::has_arg(vm, command_line::arg_validate_predownload))
|
||||
{
|
||||
boost::filesystem::remove(db_main_file_path, ec);
|
||||
|
|
@ -138,11 +145,14 @@ namespace tools
|
|||
std::string path_to_temp_blockchain_file = path_to_temp_blockchain + "/" + dbbs.get_db_main_file_name();
|
||||
|
||||
tools::create_directories_if_necessary(path_to_temp_blockchain);
|
||||
boost::filesystem::rename(downloading_file_path, path_to_temp_blockchain_file, ec);
|
||||
if (ec)
|
||||
if (downloading_file_path != path_to_temp_blockchain_file)
|
||||
{
|
||||
LOG_ERROR("Rename failed: " << downloading_file_path << " -> " << path_to_temp_blockchain_file);
|
||||
return false;
|
||||
boost::filesystem::rename(downloading_file_path, path_to_temp_blockchain_file, ec);
|
||||
if (ec)
|
||||
{
|
||||
LOG_ERROR("Rename failed: " << downloading_file_path << " -> " << path_to_temp_blockchain_file);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// remove old blockchain database from disk
|
||||
|
|
@ -180,6 +190,28 @@ namespace tools
|
|||
r = target_core.init(target_core_vm);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to init target core");
|
||||
|
||||
if (true/*TODO: copnfigure with command line option*/)
|
||||
{
|
||||
//set checkpoints
|
||||
{
|
||||
currency::checkpoints checkpoints;
|
||||
bool res = currency::create_checkpoints(checkpoints);
|
||||
CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize checkpoints");
|
||||
res = source_core.set_checkpoints(std::move(checkpoints));
|
||||
CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize core");
|
||||
}
|
||||
{
|
||||
currency::checkpoints checkpoints;
|
||||
bool res = currency::create_checkpoints(checkpoints);
|
||||
CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize checkpoints");
|
||||
res = target_core.set_checkpoints(std::move(checkpoints));
|
||||
CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize core");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
CHECK_AND_ASSERT_MES(target_core.get_top_block_height() == 0, false, "Target blockchain initialized not empty");
|
||||
uint64_t total_blocks = source_core.get_current_blockchain_size();
|
||||
|
||||
|
|
|
|||
58
src/common/variant_helper.h
Normal file
58
src/common/variant_helper.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright (c) 2014-2018 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define VARIANT_SWITCH_BEGIN(v_type_obj) {auto & local_reference_eokcmeokmeokcm ATTRIBUTE_UNUSED = v_type_obj; if(false) {;
|
||||
#define VARIANT_CASE_CONST(v_type, typed_name) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { const v_type& typed_name ATTRIBUTE_UNUSED = boost::get<v_type>(local_reference_eokcmeokmeokcm);
|
||||
#define VARIANT_CASE(v_type, typed_name) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { v_type& typed_name ATTRIBUTE_UNUSED = boost::get<v_type>(local_reference_eokcmeokmeokcm);
|
||||
#define VARIANT_CASE_TV(v_type) VARIANT_CASE(v_type, tv)
|
||||
#define VARIANT_CASE_OTHER() } else {
|
||||
#define VARIANT_CASE_THROW_ON_OTHER() } else { ASSERT_MES_AND_THROW("Unknown type in switch statemet: " << local_reference_eokcmeokmeokcm.type().name());
|
||||
#define VARIANT_CASE_THROW_ON_OTHER_MSG(err_msg) } else { ASSERT_MES_AND_THROW(err_msg << local_reference_eokcmeokmeokcm.type().name());
|
||||
|
||||
#define VARIANT_SWITCH_END() } }
|
||||
|
||||
|
||||
/*
|
||||
|
||||
usage:
|
||||
|
||||
|
||||
VARIANT_SWITCH_BEGIN(o);
|
||||
VARIANT_CASE(tx_out_bare, o);
|
||||
|
||||
VARIANT_CASE_TV(tx_out_zarcanum);
|
||||
//@#@
|
||||
VARIANT_SWITCH_END();
|
||||
|
||||
VARIANT_SWITCH_BEGIN(o);
|
||||
VARIANT_CASE_CONST(txout_to_key, o);
|
||||
VARIANT_CASE_CONST(txout_multisig, ms);
|
||||
VARIANT_CASE_CONST(txout_htlc, htlc);
|
||||
VARIANT_CASE_THROW_ON_OTHER();
|
||||
VARIANT_SWITCH_END();
|
||||
|
||||
|
||||
|
||||
VARIANT_SWITCH_BEGIN(s);
|
||||
VARIANT_CASE(void_sig, v);
|
||||
VARIANT_CASE(NLSAG_sig, signatures);
|
||||
VARIANT_CASE(zarcanum_sig, s);
|
||||
//@#@
|
||||
VARIANT_CASE_THROW_ON_OTHER();
|
||||
VARIANT_SWITCH_END();
|
||||
|
||||
|
||||
VARIANT_SWITCH_BEGIN(o);
|
||||
VARIANT_CASE(tx_out_bare, o)
|
||||
|
||||
VARIANT_CASE_TV(tx_out_zarcanum)
|
||||
//@#@
|
||||
VARIANT_CASE_THROW_ON_OTHER();
|
||||
VARIANT_SWITCH_END();
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
|
@ -407,8 +407,12 @@ bool generate_genesis(const std::string& path_config, uint64_t premine_split_amo
|
|||
|
||||
ss.str("");
|
||||
ss.clear();
|
||||
const account_public_address dummy_address = AUTO_VAL_INIT(dummy_address);
|
||||
|
||||
std::cout << ENDL << "PROOF PHRASE: " << gcp.proof_string << ENDL;
|
||||
construct_miner_tx(0, 0, 0, 0, 0, destinations, bl.miner_tx, gcp.proof_string, CURRENCY_MINER_TX_MAX_OUTS);
|
||||
uint64_t block_reward_without_fee = 0;
|
||||
uint64_t block_reward = 0;
|
||||
construct_miner_tx(0, 0, 0, 0, 0, dummy_address, dummy_address, bl.miner_tx, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, gcp.proof_string, CURRENCY_MINER_TX_MAX_OUTS, false, pos_entry(), nullptr, nullptr, destinations);
|
||||
currency::blobdata txb = tx_to_blob(bl.miner_tx);
|
||||
|
||||
//self validate block
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
// Copyright (c) 2020 The Zano developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RIPEMD160_helper.h"
|
||||
#include "auto_val_init.h"
|
||||
extern "C" {
|
||||
|
|
@ -18,7 +15,7 @@ namespace crypto {
|
|||
{
|
||||
|
||||
dword MDbuf[RMDsize / 32] = {0}; /* contains (A, B, C, D(, E)) */
|
||||
byte* hashcode = (byte*)&h; /* hashcode[RMDsize / 8]; /* for final hash-value */
|
||||
byte* hashcode = (byte*)&h; /* hashcode[RMDsize / 8]; for final hash-value */
|
||||
dword X[16] = {0}; /* current 16-word chunk */
|
||||
unsigned int i = 0; /* counter */
|
||||
dword length = static_cast<dword>(length_size_t); /* length in bytes of message */
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "warnings.h"
|
||||
//#include <compat/cpuid.h>
|
||||
|
||||
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
|
||||
|
|
@ -462,6 +462,9 @@ namespace
|
|||
TransformD64Type TransformD64_4way = nullptr;
|
||||
TransformD64Type TransformD64_8way = nullptr;
|
||||
|
||||
PUSH_GCC_WARNINGS
|
||||
DISABLE_GCC_AND_CLANG_WARNING(unused-function)
|
||||
|
||||
bool SelfTest() {
|
||||
// Input state (equal to the initial SHA256 state)
|
||||
static const uint32_t init[8] = {
|
||||
|
|
@ -626,7 +629,7 @@ std::string SHA256AutoDetect()
|
|||
assert(SelfTest());
|
||||
return ret;
|
||||
}
|
||||
|
||||
POP_GCC_WARNINGS
|
||||
////// SHA-256
|
||||
|
||||
CSHA256::CSHA256() : bytes(0)
|
||||
|
|
|
|||
1132
src/crypto/clsag.cpp
Normal file
1132
src/crypto/clsag.cpp
Normal file
File diff suppressed because it is too large
Load diff
178
src/crypto/clsag.h
Normal file
178
src/crypto/clsag.h
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
// Copyright (c) 2022-2024 Zano Project
|
||||
// Copyright (c) 2022-2024 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
// This file contains implementation of the original d-CLSAG (s.a. https://eprint.iacr.org/2019/654.pdf by Goodel at el)
|
||||
// and the extended d/v-CLSAG version (s.a. https://github.com/hyle-team/docs/blob/master/zano/dv-CLSAG-extension/ by sowle)
|
||||
//
|
||||
#pragma once
|
||||
#include "crypto-sugar.h"
|
||||
|
||||
namespace crypto
|
||||
{
|
||||
// 2-CLSAG signature where both dimensions are with respect to the group element G (that's why 'GG')
|
||||
struct CLSAG_GG_signature
|
||||
{
|
||||
scalar_t c;
|
||||
scalar_vec_t r; // size = size of the ring
|
||||
public_key K1; // auxiliary key image for layer 1
|
||||
};
|
||||
|
||||
|
||||
inline bool operator==(const CLSAG_GG_signature& lhs, const CLSAG_GG_signature& rhs)
|
||||
{
|
||||
return
|
||||
lhs.c == rhs.c &&
|
||||
lhs.r == rhs.r &&
|
||||
lhs.K1 == rhs.K1;
|
||||
}
|
||||
|
||||
inline bool operator!=(const CLSAG_GG_signature& lhs, const CLSAG_GG_signature& rhs) { return !(lhs == rhs); }
|
||||
|
||||
struct CLSAG_GG_input_ref_t
|
||||
{
|
||||
CLSAG_GG_input_ref_t(const public_key& stealth_address, const public_key& amount_commitment)
|
||||
: stealth_address(stealth_address), amount_commitment(amount_commitment)
|
||||
{}
|
||||
|
||||
const public_key& stealth_address; // P, not premultiplied by 1/8, TODO @#@#: make sure it's okay
|
||||
const public_key& amount_commitment; // A, premultiplied by 1/8
|
||||
};
|
||||
|
||||
// pseudo_out_amount_commitment -- not premultiplied by 1/8
|
||||
bool generate_CLSAG_GG(const hash& m, const std::vector<CLSAG_GG_input_ref_t>& ring, const point_t& pseudo_out_amount_commitment, const key_image& ki,
|
||||
const scalar_t& secret_x, const scalar_t& secret_f, uint64_t secret_index, CLSAG_GG_signature& sig);
|
||||
|
||||
// pseudo_out_amount_commitment -- premultiplied by 1/8
|
||||
bool verify_CLSAG_GG(const hash& m, const std::vector<CLSAG_GG_input_ref_t>& ring, const public_key& pseudo_out_amount_commitment, const key_image& ki,
|
||||
const CLSAG_GG_signature& sig);
|
||||
|
||||
|
||||
//
|
||||
// Disclaimer: extensions to the CLSAG implemented below are non-standard and are in proof-of-concept state.
|
||||
// They shouldn't be used in production code until formal security proofs are done and (ideally) the code is peer-reviewed.
|
||||
// -- sowle
|
||||
//
|
||||
|
||||
|
||||
|
||||
//
|
||||
// 3/2-CLSAG
|
||||
//
|
||||
|
||||
|
||||
// 3/2-CLSAG signature (with respect to the group element G, G, X -- that's why 'GGX')
|
||||
struct CLSAG_GGX_signature
|
||||
{
|
||||
scalar_t c;
|
||||
scalar_vec_t r_g; // for G-components (layers 0, 1), size = size of the ring
|
||||
scalar_vec_t r_x; // for X-component (layer 2), size = size of the ring
|
||||
public_key K1; // auxiliary key image for layer 1 (G)
|
||||
public_key K2; // auxiliary key image for layer 2 (X)
|
||||
};
|
||||
|
||||
struct CLSAG_GGX_input_ref_t : public CLSAG_GG_input_ref_t
|
||||
{
|
||||
CLSAG_GGX_input_ref_t(const public_key& stealth_address, const public_key& amount_commitment, const public_key& blinded_asset_id)
|
||||
: CLSAG_GG_input_ref_t(stealth_address, amount_commitment)
|
||||
, blinded_asset_id(blinded_asset_id)
|
||||
{}
|
||||
|
||||
const public_key& blinded_asset_id; // T, premultiplied by 1/8
|
||||
};
|
||||
|
||||
// pseudo_out_amount_commitment -- not premultiplied by 1/8
|
||||
// pseudo_out_asset_id -- not premultiplied by 1/8
|
||||
bool generate_CLSAG_GGX(const hash& m, const std::vector<CLSAG_GGX_input_ref_t>& ring, const point_t& pseudo_out_amount_commitment, const point_t& pseudo_out_asset_id, const key_image& ki,
|
||||
const scalar_t& secret_0_xp, const scalar_t& secret_1_f, const scalar_t& secret_2_t, uint64_t secret_index, CLSAG_GGX_signature& sig);
|
||||
|
||||
// pseudo_out_amount_commitment -- premultiplied by 1/8
|
||||
// pseudo_out_asset_id -- premultiplied by 1/8
|
||||
// may throw an exception TODO @#@# make sure it's okay
|
||||
bool verify_CLSAG_GGX(const hash& m, const std::vector<CLSAG_GGX_input_ref_t>& ring, const public_key& pseudo_out_amount_commitment,
|
||||
const public_key& pseudo_out_asset_id, const key_image& ki, const CLSAG_GGX_signature& sig);
|
||||
|
||||
|
||||
/*
|
||||
//
|
||||
// 4/2-CLSAG (eventually, it's not used in Zano)
|
||||
//
|
||||
|
||||
|
||||
// 4/2-CLSAG signature (with respect to the group element G, G, X, G -- that's why 'GGXG')
|
||||
struct CLSAG_GGXG_signature
|
||||
{
|
||||
scalar_t c;
|
||||
scalar_vec_t r_g; // for G-components (layers 0, 1, 3), size = size of the ring
|
||||
scalar_vec_t r_x; // for X-component (layer 2), size = size of the ring
|
||||
public_key K1; // auxiliary key image for layer 1 (G)
|
||||
public_key K2; // auxiliary key image for layer 2 (X)
|
||||
public_key K3; // auxiliary key image for layer 3 (G)
|
||||
};
|
||||
|
||||
struct CLSAG_GGXG_input_ref_t : public CLSAG_GG_input_ref_t
|
||||
{
|
||||
CLSAG_GGXG_input_ref_t(const public_key& stealth_address, const public_key& amount_commitment, const public_key& concealing_point)
|
||||
: CLSAG_GG_input_ref_t(stealth_address, amount_commitment)
|
||||
, concealing_point(concealing_point)
|
||||
{}
|
||||
|
||||
const public_key& concealing_point; // Q, premultiplied by 1/8
|
||||
};
|
||||
|
||||
// pseudo_out_amount_commitment -- not premultiplied by 1/8
|
||||
// extended_amount_commitment -- not premultiplied by 1/8
|
||||
bool generate_CLSAG_GGXG(const hash& m, const std::vector<CLSAG_GGXG_input_ref_t>& ring, const point_t& pseudo_out_amount_commitment, const point_t& extended_amount_commitment, const key_image& ki,
|
||||
const scalar_t& secret_0_xp, const scalar_t& secret_1_f, const scalar_t& secret_2_x, const scalar_t& secret_3_q, uint64_t secret_index, CLSAG_GGXG_signature& sig);
|
||||
|
||||
// pseudo_out_amount_commitment -- premultiplied by 1/8
|
||||
// extended_amount_commitment -- premultiplied by 1/8
|
||||
// may throw an exception TODO @#@# make sure it's okay
|
||||
bool verify_CLSAG_GGXG(const hash& m, const std::vector<CLSAG_GGXG_input_ref_t>& ring, const public_key& pseudo_out_amount_commitment,
|
||||
const public_key& extended_amount_commitment, const key_image& ki, const CLSAG_GGXG_signature& sig);
|
||||
|
||||
*/
|
||||
|
||||
//
|
||||
// 5/2-CLSAG
|
||||
//
|
||||
|
||||
|
||||
// 5/2-CLSAG signature (with respect to the group element G, G, X, X, G -- that's why 'GGXXG')
|
||||
struct CLSAG_GGXXG_signature
|
||||
{
|
||||
scalar_t c;
|
||||
scalar_vec_t r_g; // for G-components (layers 0, 1, 4), size = size of the ring
|
||||
scalar_vec_t r_x; // for X-component (layers 2, 3), size = size of the ring
|
||||
public_key K1; // auxiliary key image for layer 1 (G)
|
||||
public_key K2; // auxiliary key image for layer 2 (X)
|
||||
public_key K3; // auxiliary key image for layer 2 (X)
|
||||
public_key K4; // auxiliary key image for layer 3 (G)
|
||||
};
|
||||
|
||||
struct CLSAG_GGXXG_input_ref_t : public CLSAG_GGX_input_ref_t
|
||||
{
|
||||
CLSAG_GGXXG_input_ref_t(const public_key& stealth_address, const public_key& amount_commitment, const public_key& blinded_asset_id, const public_key& concealing_point)
|
||||
: CLSAG_GGX_input_ref_t(stealth_address, amount_commitment, blinded_asset_id)
|
||||
, concealing_point(concealing_point)
|
||||
{}
|
||||
|
||||
const public_key& concealing_point; // Q, premultiplied by 1/8
|
||||
};
|
||||
|
||||
// pseudo_out_amount_commitment -- not premultiplied by 1/8
|
||||
// pseudo_out_asset_id -- not premultiplied by 1/8
|
||||
// extended_amount_commitment -- not premultiplied by 1/8
|
||||
bool generate_CLSAG_GGXXG(const hash& m, const std::vector<CLSAG_GGXXG_input_ref_t>& ring, const point_t& pseudo_out_amount_commitment, const point_t& pseudo_out_blinded_asset_id, const point_t& extended_amount_commitment, const key_image& ki,
|
||||
const scalar_t& secret_0_xp, const scalar_t& secret_1_f, const scalar_t& secret_2_r, const scalar_t& secret_3_x, const scalar_t& secret_4_q, uint64_t secret_index, CLSAG_GGXXG_signature& sig);
|
||||
|
||||
// pseudo_out_amount_commitment -- premultiplied by 1/8
|
||||
// pseudo_out_asset_id -- premultiplied by 1/8
|
||||
// extended_amount_commitment -- premultiplied by 1/8
|
||||
// may throw an exception TODO @#@# make sure it's okay
|
||||
bool verify_CLSAG_GGXXG(const hash& m, const std::vector<CLSAG_GGXXG_input_ref_t>& ring, const public_key& pseudo_out_amount_commitment, const public_key& pseudo_out_blinded_asset_id, const public_key& extended_amount_commitment, const key_image& ki,
|
||||
const CLSAG_GGXXG_signature& sig);
|
||||
|
||||
|
||||
} // namespace crypto
|
||||
|
|
@ -40,7 +40,6 @@ DISABLE_VS_WARNINGS(4146 4244)
|
|||
void fe_mul(fe, const fe, const fe);
|
||||
void fe_sq(fe, const fe);
|
||||
void fe_tobytes(unsigned char *, const fe);
|
||||
static void ge_madd(ge_p1p1 *, const ge_p3 *, const ge_precomp *);
|
||||
static void ge_msub(ge_p1p1 *, const ge_p3 *, const ge_precomp *);
|
||||
static void ge_p2_0(ge_p2 *);
|
||||
static void ge_p3_dbl(ge_p1p1 *, const ge_p3 *);
|
||||
|
|
@ -119,7 +118,7 @@ Postconditions:
|
|||
|h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
||||
*/
|
||||
|
||||
static void fe_add(fe h, const fe f, const fe g) {
|
||||
void fe_add(fe h, const fe f, const fe g) {
|
||||
int32_t f0 = f[0];
|
||||
int32_t f1 = f[1];
|
||||
int32_t f2 = f[2];
|
||||
|
|
@ -1425,7 +1424,7 @@ int ge_frombytes_vartime(ge_p3 *h, const unsigned char *s) {
|
|||
r = p + q
|
||||
*/
|
||||
|
||||
static void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
|
||||
void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
|
||||
fe t0;
|
||||
fe_add(r->X, p->Y, p->X);
|
||||
fe_sub(r->Y, p->Y, p->X);
|
||||
|
|
@ -4314,3 +4313,171 @@ void ge_cached_to_p2(ge_p2 *r, const ge_cached *c)
|
|||
|
||||
fe_copy(r->Z, c->Z);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// EXPERIMENTAL
|
||||
//
|
||||
|
||||
// With these select_vartime/ge_scalarmult_base_vartime I got ~25% speed up comparing to the select/ge_scalarmult_base -- sowle
|
||||
static void select_vartime(ge_precomp *t, int pos, signed char b)
|
||||
{
|
||||
unsigned char bnegative = negative(b);
|
||||
unsigned char babs = b - (((-bnegative) & b) << 1);
|
||||
const ge_precomp* base;
|
||||
|
||||
if (babs == 0)
|
||||
{
|
||||
ge_precomp_0(t);
|
||||
}
|
||||
else if (bnegative == 0)
|
||||
{
|
||||
base = &ge_base[pos][babs - 1];
|
||||
fe_copy(t->yplusx, base->yplusx);
|
||||
fe_copy(t->yminusx, base->yminusx);
|
||||
fe_copy(t->xy2d, base->xy2d);
|
||||
}
|
||||
else
|
||||
{
|
||||
base = &ge_base[pos][babs - 1];
|
||||
fe_copy(t->yplusx, base->yminusx);
|
||||
fe_copy(t->yminusx, base->yplusx);
|
||||
fe_neg(t->xy2d, base->xy2d);
|
||||
}
|
||||
}
|
||||
|
||||
void ge_scalarmult_base_vartime(ge_p3 *h, const unsigned char *a)
|
||||
{
|
||||
signed char e[64];
|
||||
signed char carry;
|
||||
ge_p1p1 r;
|
||||
ge_p2 s;
|
||||
ge_precomp t;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; ++i) {
|
||||
e[2 * i + 0] = (a[i] >> 0) & 15;
|
||||
e[2 * i + 1] = (a[i] >> 4) & 15;
|
||||
}
|
||||
/* each e[i] is between 0 and 15 */
|
||||
/* e[63] is between 0 and 7 */
|
||||
|
||||
carry = 0;
|
||||
for (i = 0; i < 63; ++i) {
|
||||
e[i] += carry;
|
||||
carry = e[i] + 8;
|
||||
carry >>= 4;
|
||||
e[i] -= carry << 4;
|
||||
}
|
||||
e[63] += carry;
|
||||
/* each e[i] is between -8 and 8 */
|
||||
|
||||
ge_p3_0(h);
|
||||
for (i = 1; i < 64; i += 2) {
|
||||
select_vartime(&t, i / 2, e[i]);
|
||||
ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r);
|
||||
}
|
||||
|
||||
ge_p3_dbl(&r, h); ge_p1p1_to_p2(&s, &r);
|
||||
ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r);
|
||||
ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r);
|
||||
ge_p2_dbl(&r, &s); ge_p1p1_to_p3(h, &r);
|
||||
|
||||
for (i = 0; i < 64; i += 2) {
|
||||
select_vartime(&t, i / 2, e[i]);
|
||||
ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void select_custom_precomp_vartime(ge_precomp *t, const precomp_data_t base_precomp, int pos, signed char b)
|
||||
{
|
||||
unsigned char bnegative = negative(b);
|
||||
unsigned char babs = b - (((-bnegative) & b) << 1);
|
||||
const ge_precomp* base;
|
||||
|
||||
if (babs == 0)
|
||||
{
|
||||
ge_precomp_0(t);
|
||||
}
|
||||
else if (bnegative == 0)
|
||||
{
|
||||
base = &base_precomp[pos][babs - 1];
|
||||
fe_copy(t->yplusx, base->yplusx);
|
||||
fe_copy(t->yminusx, base->yminusx);
|
||||
fe_copy(t->xy2d, base->xy2d);
|
||||
}
|
||||
else
|
||||
{
|
||||
base = &base_precomp[pos][babs - 1];
|
||||
fe_copy(t->yplusx, base->yminusx);
|
||||
fe_copy(t->yminusx, base->yplusx);
|
||||
fe_neg(t->xy2d, base->xy2d);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ge_scalarmult_precomp_vartime(ge_p3 *h, const precomp_data_t base_precomp, const unsigned char *a)
|
||||
{
|
||||
signed char e[64];
|
||||
signed char carry;
|
||||
ge_p1p1 r;
|
||||
ge_p2 s;
|
||||
ge_precomp t;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; ++i) {
|
||||
e[2 * i + 0] = (a[i] >> 0) & 15;
|
||||
e[2 * i + 1] = (a[i] >> 4) & 15;
|
||||
}
|
||||
/* each e[i] is between 0 and 15 */
|
||||
/* e[63] is between 0 and 7 */
|
||||
|
||||
carry = 0;
|
||||
for (i = 0; i < 63; ++i) {
|
||||
e[i] += carry;
|
||||
carry = e[i] + 8;
|
||||
carry >>= 4;
|
||||
e[i] -= carry << 4;
|
||||
}
|
||||
e[63] += carry;
|
||||
/* each e[i] is between -8 and 8 */
|
||||
|
||||
ge_p3_0(h);
|
||||
for (i = 1; i < 64; i += 2) {
|
||||
select_custom_precomp_vartime(&t, base_precomp, i / 2, e[i]);
|
||||
ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r);
|
||||
}
|
||||
|
||||
ge_p3_dbl(&r, h); ge_p1p1_to_p2(&s, &r);
|
||||
ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r);
|
||||
ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r);
|
||||
ge_p2_dbl(&r, &s); ge_p1p1_to_p3(h, &r);
|
||||
|
||||
for (i = 0; i < 64; i += 2) {
|
||||
select_custom_precomp_vartime(&t, base_precomp, i / 2, e[i]);
|
||||
ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r);
|
||||
}
|
||||
}
|
||||
|
||||
void ge_p3_to_precomp(ge_precomp *r, const ge_p3* p)
|
||||
{
|
||||
fe recip;
|
||||
fe x;
|
||||
fe y;
|
||||
//unsigned char s[32];
|
||||
|
||||
fe_invert(recip, p->Z);
|
||||
fe_mul(x, p->X, recip);
|
||||
fe_mul(y, p->Y, recip);
|
||||
fe_sub(r->yminusx, y, x);
|
||||
fe_add(r->yplusx, y, x);
|
||||
fe_mul(r->xy2d, x, y);
|
||||
fe_mul(r->xy2d, r->xy2d, fe_d2);
|
||||
|
||||
// to get canonical representation and obtain the very same beautiful numbers for ge_base in crypto-ops-data.c (maybe unnecessary, TODO -- sowle)
|
||||
//fe_tobytes(s, r->yminusx); fe_frombytes(r->yminusx, s);
|
||||
//fe_tobytes(s, r->yplusx); fe_frombytes(r->yplusx, s);
|
||||
//fe_tobytes(s, r->xy2d); fe_frombytes(r->xy2d, s);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ void ge_double_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const ge_
|
|||
|
||||
extern const fe fe_sqrtm1;
|
||||
extern const fe fe_d;
|
||||
extern const fe fe_d2;
|
||||
int ge_frombytes_vartime(ge_p3 *, const unsigned char *);
|
||||
|
||||
/* From ge_p1p1_to_p2.c */
|
||||
|
|
@ -112,12 +113,19 @@ void ge_p2_to_p3(ge_p3 *r, const ge_p2 *t);
|
|||
void ge_bytes_hash_to_ec(ge_p3 *, const void *, size_t);
|
||||
void ge_bytes_hash_to_ec_32(ge_p3 *, const unsigned char *);
|
||||
void ge_cached_to_p2(ge_p2 *r, const ge_cached *c);
|
||||
void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q);
|
||||
|
||||
void ge_p3_0(ge_p3 *h);
|
||||
void ge_sub(ge_p1p1 *, const ge_p3 *, const ge_cached *);
|
||||
void ge_double_scalarmult_base_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b);
|
||||
void ge_scalarmult_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A);
|
||||
void ge_scalarmult_vartime_p3_v2(ge_p3 *r, const unsigned char *a, const ge_p3 *A);
|
||||
void ge_scalarmult_base_vartime(ge_p3 *h, const unsigned char *a);
|
||||
|
||||
/* precomp_data[i][j] = (j + 1) * 256^i * G */
|
||||
typedef ge_precomp (precomp_data_t)[32][8];
|
||||
void ge_scalarmult_precomp_vartime(ge_p3 *h, const precomp_data_t base_precomp, const unsigned char *a);
|
||||
void ge_p3_to_precomp(ge_precomp *r, const ge_p3* p);
|
||||
|
||||
extern const fe fe_ma2;
|
||||
extern const fe fe_ma;
|
||||
|
|
@ -139,6 +147,7 @@ void sc_invert(unsigned char*, const unsigned char*);
|
|||
|
||||
void fe_sq(fe h, const fe f);
|
||||
int fe_isnonzero(const fe f);
|
||||
void fe_add(fe h, const fe f, const fe g);
|
||||
void fe_sub(fe h, const fe f, const fe g);
|
||||
void fe_mul(fe, const fe, const fe);
|
||||
void fe_frombytes(fe h, const unsigned char *s);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2020-2021 Zano Project
|
||||
// Copyright (c) 2020-2021 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Copyright (c) 2020-2024 Zano Project
|
||||
// Copyright (c) 2020-2024 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
|
|
@ -11,17 +11,45 @@
|
|||
|
||||
namespace crypto
|
||||
{
|
||||
namespace mp = boost::multiprecision;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "crypto/crypto-ops.h"
|
||||
} // extern "C"
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Helpers
|
||||
//
|
||||
|
||||
// returns greatest k, s.t. n**k <= v
|
||||
// tests in crypto_tests_range_proofs.h
|
||||
constexpr uint64_t constexpr_floor_log_n(uint64_t v, uint64_t n)
|
||||
{
|
||||
return (v < n || n <= 1) ? 0 : constexpr_floor_log_n(v / n, n) + 1;
|
||||
}
|
||||
|
||||
// returns smallest k, s.t. v <= n**k
|
||||
// tests in crypto_tests_range_proofs.h
|
||||
constexpr uint64_t constexpr_ceil_log_n(uint64_t v, uint64_t n)
|
||||
{
|
||||
return (v <= 1 || n <= 1) ? 0 : constexpr_floor_log_n(v - 1, n) + 1;
|
||||
}
|
||||
|
||||
// returns smallest k, s.t. v <= 2**k
|
||||
// tests in crypto_tests_range_proofs.h
|
||||
constexpr uint64_t constexpr_ceil_log2(uint64_t v)
|
||||
{
|
||||
return constexpr_ceil_log_n(v, 2);
|
||||
}
|
||||
|
||||
// returns base ** k
|
||||
constexpr uint64_t constexpr_pow(uint64_t k, uint64_t base)
|
||||
{
|
||||
return k == 0 ? 1 : base * constexpr_pow(k - 1, base);
|
||||
}
|
||||
|
||||
|
||||
template<class pod_t>
|
||||
std::string pod_to_hex_reversed(const pod_t &h)
|
||||
{
|
||||
|
|
@ -30,7 +58,8 @@ namespace crypto
|
|||
size_t len = sizeof h;
|
||||
|
||||
std::string s(len * 2, ' ');
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
s[2 * i] = hexmap[data[len - 1 - i] >> 4];
|
||||
s[2 * i + 1] = hexmap[data[len - 1 - i] & 0x0F];
|
||||
}
|
||||
|
|
@ -46,7 +75,8 @@ namespace crypto
|
|||
size_t len = sizeof h;
|
||||
|
||||
std::string s(len * 2, ' ');
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
s[2 * i] = hexmap[data[i] >> 4];
|
||||
s[2 * i + 1] = hexmap[data[i] & 0x0F];
|
||||
}
|
||||
|
|
@ -70,6 +100,22 @@ namespace crypto
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
template<class pod_t>
|
||||
std::string pod_to_comma_separated_chars(const pod_t &h)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::hex << std::setfill('0');
|
||||
size_t len = sizeof h;
|
||||
const unsigned char* p = (const unsigned char*)&h;
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
ss << "'\\x" << std::setw(2) << static_cast<unsigned int>(p[i]) << "'";
|
||||
if (i + 1 != len)
|
||||
ss << ", ";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<class pod_t>
|
||||
std::string pod_to_hex_comma_separated_uint64(const pod_t &h)
|
||||
{
|
||||
|
|
@ -87,6 +133,22 @@ namespace crypto
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
template<class pod_t>
|
||||
std::string pod_to_comma_separated_int32(const pod_t &h)
|
||||
{
|
||||
static_assert((sizeof h) % 4 == 0, "size of h should be a multiple of 32 bit");
|
||||
size_t len = (sizeof h) / 4;
|
||||
std::stringstream ss;
|
||||
const int32_t* p = (const int32_t*)&h;
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
ss << static_cast<int32_t>(p[i]);
|
||||
if (i + 1 != len)
|
||||
ss << ", ";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<typename t_pod_type>
|
||||
bool parse_tpod_from_hex_string(const std::string& hex_str, t_pod_type& t_pod)
|
||||
{
|
||||
|
|
@ -125,31 +187,28 @@ namespace crypto
|
|||
t_pod_type parse_tpod_from_hex_string(const std::string& hex_str)
|
||||
{
|
||||
t_pod_type t_pod = AUTO_VAL_INIT(t_pod);
|
||||
parse_tpod_from_hex_string(hex_str, t_pod);
|
||||
crypto::parse_tpod_from_hex_string(hex_str, t_pod); // using fully qualified name to avoid Argument-Dependent Lookup issues
|
||||
return t_pod;
|
||||
}
|
||||
|
||||
//
|
||||
// scalar_t - holds a 256-bit scalar, normally in [0..L-1]
|
||||
//
|
||||
struct alignas(32) scalar_t
|
||||
struct /* TODO alignas(32) */ scalar_t
|
||||
{
|
||||
union
|
||||
{
|
||||
uint64_t m_u64[4];
|
||||
unsigned char m_s[32];
|
||||
uint64_t m_u64[4];
|
||||
unsigned char m_s[32];
|
||||
crypto::secret_key m_sk;
|
||||
};
|
||||
|
||||
scalar_t()
|
||||
{}
|
||||
scalar_t() = default;
|
||||
|
||||
// won't check scalar range validity (< L)
|
||||
scalar_t(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3)
|
||||
constexpr scalar_t(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3) noexcept
|
||||
: m_u64{a0, a1, a2, a3}
|
||||
{
|
||||
m_u64[0] = a0;
|
||||
m_u64[1] = a1;
|
||||
m_u64[2] = a2;
|
||||
m_u64[3] = a3;
|
||||
}
|
||||
|
||||
// won't check scalar range validity (< L)
|
||||
|
|
@ -205,28 +264,22 @@ namespace crypto
|
|||
|
||||
crypto::secret_key &as_secret_key()
|
||||
{
|
||||
return *(crypto::secret_key*)&m_s[0];
|
||||
return m_sk;
|
||||
}
|
||||
|
||||
const crypto::secret_key& as_secret_key() const
|
||||
{
|
||||
return *(const crypto::secret_key*)&m_s[0];
|
||||
return m_sk;
|
||||
}
|
||||
|
||||
operator crypto::secret_key() const
|
||||
{
|
||||
crypto::secret_key result;
|
||||
memcpy(result.data, &m_s, sizeof result.data);
|
||||
return result;
|
||||
return m_sk;
|
||||
}
|
||||
|
||||
void from_secret_key(const crypto::secret_key& sk)
|
||||
{
|
||||
uint64_t *p_sk64 = (uint64_t*)&sk;
|
||||
m_u64[0] = p_sk64[0];
|
||||
m_u64[1] = p_sk64[1];
|
||||
m_u64[2] = p_sk64[2];
|
||||
m_u64[3] = p_sk64[3];
|
||||
m_sk = sk;
|
||||
// assuming secret key is correct (< L), so we don't need to call reduce here
|
||||
}
|
||||
|
||||
|
|
@ -315,6 +368,14 @@ namespace crypto
|
|||
return *this;
|
||||
}
|
||||
|
||||
scalar_t operator-() const
|
||||
{
|
||||
static unsigned char zero[32] = { 0 };
|
||||
scalar_t result;
|
||||
sc_sub(&result.m_s[0], zero, &m_s[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
// returns this = a * b
|
||||
scalar_t& assign_mul(const scalar_t& a, const scalar_t& b)
|
||||
{
|
||||
|
|
@ -325,7 +386,7 @@ namespace crypto
|
|||
/*
|
||||
I think it has bad symantic (operator-like), consider rename/reimplement -- sowle
|
||||
*/
|
||||
// returns this * b + c
|
||||
// returns c + this * b
|
||||
scalar_t muladd(const scalar_t& b, const scalar_t& c) const
|
||||
{
|
||||
scalar_t result;
|
||||
|
|
@ -333,13 +394,20 @@ namespace crypto
|
|||
return result;
|
||||
}
|
||||
|
||||
// returns this = a * b + c
|
||||
// returns this = c + a * b
|
||||
scalar_t& assign_muladd(const scalar_t& a, const scalar_t& b, const scalar_t& c)
|
||||
{
|
||||
sc_muladd(m_s, a.m_s, b.m_s, c.m_s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// returns this = c - a * b
|
||||
scalar_t& assign_mulsub(const scalar_t& a, const scalar_t& b, const scalar_t& c)
|
||||
{
|
||||
sc_mulsub(m_s, a.m_s, b.m_s, c.m_s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
scalar_t reciprocal() const
|
||||
{
|
||||
scalar_t result;
|
||||
|
|
@ -449,6 +517,25 @@ namespace crypto
|
|||
m_u64[bit_index >> 6] &= ~(1ull << (bit_index & 63));
|
||||
}
|
||||
|
||||
// the result is guaranteed to be within [ 0; 2 ^ bits_count )
|
||||
uint64_t get_bits(uint8_t bit_index_first, uint8_t bits_count) const
|
||||
{
|
||||
if (bits_count == 0 || bits_count > 64)
|
||||
return 0;
|
||||
uint8_t bits_count_m_1 = bits_count - 1;
|
||||
unsigned int bit_index_last = bit_index_first + bits_count_m_1;
|
||||
if (bit_index_last > 255)
|
||||
bit_index_last = 255;
|
||||
|
||||
uint64_t result = m_u64[bit_index_first >> 6] >> (bit_index_first & 63);
|
||||
if (bits_count_m_1 > (bit_index_last & 63))
|
||||
result |= m_u64[bit_index_last >> 6] << (bits_count_m_1 - (bit_index_last & 63));
|
||||
|
||||
uint64_t result_mask = ((1ull << bits_count_m_1) - 1) << 1 | 1; // (just because 1ull << 64 in undefined behaviour, not a 0 as one would expect)
|
||||
return result & result_mask;
|
||||
}
|
||||
|
||||
// does not reduce
|
||||
static scalar_t power_of_2(uint8_t exponent)
|
||||
{
|
||||
scalar_t result = 0;
|
||||
|
|
@ -459,16 +546,20 @@ namespace crypto
|
|||
}; // struct scalar_t
|
||||
|
||||
//
|
||||
// Global constants
|
||||
// Global constants (checked in crypto_constants)
|
||||
//
|
||||
|
||||
extern const scalar_t c_scalar_1;
|
||||
extern const scalar_t c_scalar_L;
|
||||
extern const scalar_t c_scalar_Lm1;
|
||||
extern const scalar_t c_scalar_P;
|
||||
extern const scalar_t c_scalar_Pm1;
|
||||
extern const scalar_t c_scalar_256m1;
|
||||
extern const scalar_t c_scalar_1div8;
|
||||
static constexpr scalar_t c_scalar_0 = { 0, 0, 0, 0 };
|
||||
static constexpr scalar_t c_scalar_1 = { 1, 0, 0, 0 };
|
||||
static constexpr scalar_t c_scalar_2p64 = { 0, 1, 0, 0 };
|
||||
static constexpr scalar_t c_scalar_L = { 0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0x0, 0x1000000000000000 };
|
||||
static constexpr scalar_t c_scalar_Lm1 = { 0x5812631a5cf5d3ec, 0x14def9dea2f79cd6, 0x0, 0x1000000000000000 };
|
||||
static constexpr scalar_t c_scalar_P = { 0xffffffffffffffed, 0xffffffffffffffff, 0xffffffffffffffff, 0x7fffffffffffffff };
|
||||
static constexpr scalar_t c_scalar_Pm1 = { 0xffffffffffffffec, 0xffffffffffffffff, 0xffffffffffffffff, 0x7fffffffffffffff };
|
||||
static constexpr scalar_t c_scalar_256m1 = { 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff };
|
||||
static constexpr scalar_t c_scalar_1div8 = { 0x6106e529e2dc2f79, 0x07d39db37d1cdad0, 0x0, 0x0600000000000000 };
|
||||
|
||||
static_assert(sizeof(scalar_t::m_sk) == sizeof(scalar_t::m_u64) && sizeof(scalar_t::m_u64) == sizeof(scalar_t::m_s), "size missmatch");
|
||||
|
||||
//
|
||||
//
|
||||
|
|
@ -481,31 +572,26 @@ namespace crypto
|
|||
// with x = X / Z, y = Y / Z, x * y = T / Z.
|
||||
ge_p3 m_p3;
|
||||
|
||||
point_t()
|
||||
point_t() = default;
|
||||
|
||||
explicit point_t(const crypto::public_key& pk) // can throw std::runtime_error
|
||||
{
|
||||
CRYPTO_CHECK_AND_THROW_MES(from_public_key(pk), "invalid public key");
|
||||
}
|
||||
|
||||
explicit point_t(const crypto::public_key& pk)
|
||||
{
|
||||
if (!from_public_key(pk))
|
||||
zero();
|
||||
}
|
||||
|
||||
point_t(const unsigned char(&v)[32])
|
||||
point_t(const unsigned char(&v)[32]) // can throw std::runtime_error
|
||||
{
|
||||
static_assert(sizeof(crypto::public_key) == sizeof v, "size missmatch");
|
||||
if (!from_public_key(*(const crypto::public_key*)v))
|
||||
zero();
|
||||
CRYPTO_CHECK_AND_THROW_MES(from_public_key(*(const crypto::public_key*)v), "invalid public key (char[32])");
|
||||
}
|
||||
|
||||
point_t(const uint64_t(&v)[4])
|
||||
point_t(const uint64_t(&v)[4]) // can throw std::runtime_error
|
||||
{
|
||||
static_assert(sizeof(crypto::public_key) == sizeof v, "size missmatch");
|
||||
if (!from_public_key(*(const crypto::public_key*)v))
|
||||
zero();
|
||||
CRYPTO_CHECK_AND_THROW_MES(from_public_key(*(const crypto::public_key*)v), "invalid public key (uint64_t[4])");
|
||||
}
|
||||
|
||||
point_t(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3)
|
||||
point_t(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3) // can throw std::runtime_error
|
||||
{
|
||||
crypto::public_key pk;
|
||||
((uint64_t*)&pk)[0] = a0;
|
||||
|
|
@ -513,8 +599,7 @@ namespace crypto
|
|||
((uint64_t*)&pk)[2] = a2;
|
||||
((uint64_t*)&pk)[3] = a3;
|
||||
|
||||
if (!from_public_key(pk))
|
||||
zero();
|
||||
CRYPTO_CHECK_AND_THROW_MES(from_public_key(pk), "invalid public key (four uint64_t)");
|
||||
}
|
||||
|
||||
explicit point_t(tag_zero&&)
|
||||
|
|
@ -522,6 +607,21 @@ namespace crypto
|
|||
zero();
|
||||
}
|
||||
|
||||
explicit point_t(const key_image& ki) // can throw std::runtime_error
|
||||
: point_t(static_cast<const public_key&>(static_cast<const ec_point&>(ki)))
|
||||
{
|
||||
}
|
||||
|
||||
explicit constexpr point_t(const int32_t(&v)[40]) noexcept
|
||||
: m_p3{
|
||||
{v[ 0], v[ 1], v[ 2], v[ 3], v[ 4], v[ 5], v[ 6], v[ 7], v[ 8], v[9]},
|
||||
{v[10], v[11], v[12], v[13], v[14], v[15], v[16], v[17], v[18], v[19]},
|
||||
{v[20], v[21], v[22], v[23], v[24], v[25], v[26], v[27], v[28], v[29]},
|
||||
{v[30], v[31], v[32], v[33], v[34], v[35], v[36], v[37], v[38], v[39]}
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
// as we're using additive notation, zero means identity group element (EC point (0, 1)) here and after
|
||||
void zero()
|
||||
{
|
||||
|
|
@ -530,9 +630,13 @@ namespace crypto
|
|||
|
||||
bool is_zero() const
|
||||
{
|
||||
// (0, 1) ~ (0, z, z, 0)
|
||||
// (0, 1) ~ (0, z, z, 0) for any non-zero z https://www.rfc-editor.org/rfc/rfc8032#page-17
|
||||
if (fe_isnonzero(m_p3.X) != 0)
|
||||
return false;
|
||||
return false; // x != 0
|
||||
if (fe_isnonzero(m_p3.Z) == 0)
|
||||
return false; // z == 0
|
||||
if (fe_isnonzero(m_p3.T) != 0)
|
||||
return false; // t != 0
|
||||
fe y_minus_z;
|
||||
fe_sub(y_minus_z, m_p3.Y, m_p3.Z);
|
||||
return fe_isnonzero(y_minus_z) == 0;
|
||||
|
|
@ -625,14 +729,15 @@ namespace crypto
|
|||
friend point_t operator*(const scalar_t& lhs, const point_t& rhs)
|
||||
{
|
||||
point_t result;
|
||||
ge_scalarmult_p3(&result.m_p3, lhs.m_s, &rhs.m_p3);
|
||||
//ge_scalarmult_p3(&result.m_p3, lhs.m_s, &rhs.m_p3);
|
||||
ge_scalarmult_vartime_p3(&result.m_p3, lhs.m_s, &rhs.m_p3);
|
||||
return result;
|
||||
}
|
||||
|
||||
point_t& operator*=(const scalar_t& rhs)
|
||||
{
|
||||
// TODO: ge_scalarmult_vartime_p3
|
||||
ge_scalarmult_p3(&m_p3, rhs.m_s, &m_p3);
|
||||
//ge_scalarmult_p3(&m_p3, rhs.m_s, &m_p3);
|
||||
ge_scalarmult_vartime_p3(&m_p3, rhs.m_s, &m_p3);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -641,7 +746,17 @@ namespace crypto
|
|||
point_t result;
|
||||
scalar_t reciprocal;
|
||||
sc_invert(&reciprocal.m_s[0], &rhs.m_s[0]);
|
||||
ge_scalarmult_p3(&result.m_p3, &reciprocal.m_s[0], &lhs.m_p3);
|
||||
//ge_scalarmult_p3(&result.m_p3, &reciprocal.m_s[0], &lhs.m_p3);
|
||||
ge_scalarmult_vartime_p3(&result.m_p3, &reciprocal.m_s[0], &lhs.m_p3);
|
||||
return result;
|
||||
}
|
||||
|
||||
point_t operator-() const
|
||||
{
|
||||
point_t result = *this;
|
||||
fe zero = {0};
|
||||
fe_sub(result.m_p3.Y, zero, result.m_p3.Y);
|
||||
fe_sub(result.m_p3.Z, zero, result.m_p3.Z);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -651,6 +766,24 @@ namespace crypto
|
|||
return *this;
|
||||
}
|
||||
|
||||
point_t modify_mul_pow_2(size_t power)
|
||||
{
|
||||
if (power > 0)
|
||||
{
|
||||
ge_p1p1 p1;
|
||||
ge_p2 p2;
|
||||
ge_p3_to_p2(&p2, &m_p3);
|
||||
for (size_t i = 1; i < power; ++i)
|
||||
{
|
||||
ge_p2_dbl(&p1, &p2);
|
||||
ge_p1p1_to_p2(&p2, &p1);
|
||||
}
|
||||
ge_p2_dbl(&p1, &p2);
|
||||
ge_p1p1_to_p3(&m_p3, &p1);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// returns a * this + G
|
||||
point_t mul_plus_G(const scalar_t& a) const
|
||||
{
|
||||
|
|
@ -678,6 +811,8 @@ namespace crypto
|
|||
|
||||
friend bool operator==(const point_t& lhs, const point_t& rhs)
|
||||
{
|
||||
// TODO: @#@# (performance) consider checking (lhs - rhs).is_zero() instead
|
||||
|
||||
// convert to xy form, then compare components (because (x, y, z, t) representation is not unique)
|
||||
fe lrecip, lx, ly;
|
||||
fe rrecip, rx, ry;
|
||||
|
|
@ -696,12 +831,32 @@ namespace crypto
|
|||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
friend bool operator!=(const point_t& lhs, const point_t& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
};
|
||||
}
|
||||
|
||||
friend bool operator==(const point_t& lhs, const public_key& rhs)
|
||||
{
|
||||
return lhs.to_public_key() == rhs;
|
||||
}
|
||||
|
||||
friend bool operator!=(const point_t& lhs, const public_key& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
friend bool operator==(const public_key& lhs, const point_t& rhs)
|
||||
{
|
||||
return lhs == rhs.to_public_key();
|
||||
}
|
||||
|
||||
friend bool operator!=(const public_key& lhs, const point_t& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& ss, const point_t &v)
|
||||
{
|
||||
|
|
@ -733,6 +888,11 @@ namespace crypto
|
|||
return pod_to_hex_comma_separated_uint64(pk);
|
||||
}
|
||||
|
||||
std::string to_comma_separated_int32_str() const
|
||||
{
|
||||
return pod_to_comma_separated_int32(m_p3);
|
||||
}
|
||||
|
||||
}; // struct point_t
|
||||
|
||||
|
||||
|
|
@ -741,16 +901,16 @@ namespace crypto
|
|||
//
|
||||
struct point_g_t : public point_t
|
||||
{
|
||||
point_g_t()
|
||||
explicit constexpr point_g_t(const int32_t(&v)[40]) noexcept
|
||||
: point_t(v)
|
||||
{
|
||||
scalar_t one(1);
|
||||
ge_scalarmult_base(&m_p3, &one.m_s[0]);
|
||||
}
|
||||
|
||||
friend point_t operator*(const scalar_t& lhs, const point_g_t&)
|
||||
{
|
||||
point_t result;
|
||||
ge_scalarmult_base(&result.m_p3, &lhs.m_s[0]);
|
||||
//ge_scalarmult_base(&result.m_p3, &lhs.m_s[0]);
|
||||
ge_scalarmult_base_vartime(&result.m_p3, &lhs.m_s[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -759,7 +919,8 @@ namespace crypto
|
|||
point_t result;
|
||||
scalar_t reciprocal;
|
||||
sc_invert(&reciprocal.m_s[0], &rhs.m_s[0]);
|
||||
ge_scalarmult_base(&result.m_p3, &reciprocal.m_s[0]);
|
||||
//ge_scalarmult_base(&result.m_p3, &reciprocal.m_s[0]);
|
||||
ge_scalarmult_base_vartime(&result.m_p3, &reciprocal.m_s[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -768,6 +929,42 @@ namespace crypto
|
|||
}; // struct point_g_t
|
||||
|
||||
|
||||
void construct_precomp_data(precomp_data_t precomp_data, const point_t& point);
|
||||
|
||||
//
|
||||
// point_pc_t -- point with 30kB of precomputed data, which make possible to do very fast single scalar multiplication
|
||||
//
|
||||
struct point_pc_t : public point_t
|
||||
{
|
||||
constexpr point_pc_t(const int32_t(&v)[40], const precomp_data_t* precomp_data_p)
|
||||
: point_t(v)
|
||||
, m_precomp_data_p(precomp_data_p)
|
||||
{
|
||||
//construct_precomp_data(m_precomp_data, *this);
|
||||
}
|
||||
|
||||
friend point_t operator*(const scalar_t& lhs, const point_pc_t& self)
|
||||
{
|
||||
point_t result;
|
||||
ge_scalarmult_precomp_vartime(&result.m_p3, *self.m_precomp_data_p, &lhs.m_s[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
friend point_t operator/(const point_pc_t& self, const scalar_t& rhs)
|
||||
{
|
||||
point_t result;
|
||||
scalar_t reciprocal;
|
||||
sc_invert(&reciprocal.m_s[0], &rhs.m_s[0]);
|
||||
ge_scalarmult_precomp_vartime(&result.m_p3, *self.m_precomp_data_p, &reciprocal.m_s[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
static_assert(sizeof(crypto::public_key) == 32, "size error");
|
||||
|
||||
const precomp_data_t* m_precomp_data_p;
|
||||
}; // struct point_pc_t
|
||||
|
||||
|
||||
//
|
||||
// vector of scalars
|
||||
//
|
||||
|
|
@ -845,8 +1042,11 @@ namespace crypto
|
|||
// zeroes all elements
|
||||
void zero()
|
||||
{
|
||||
PUSH_GCC_WARNINGS
|
||||
DISABLE_GCC_AND_CLANG_WARNING(class-memaccess)
|
||||
size_t size_bytes = sizeof(scalar_t) * size();
|
||||
memset(data(), 0, size_bytes);
|
||||
POP_GCC_WARNINGS
|
||||
}
|
||||
|
||||
// invert all elements in-place efficiently: 4*N muptiplications + 1 inversion
|
||||
|
|
@ -885,6 +1085,19 @@ namespace crypto
|
|||
|
||||
scalar_t calc_hs() const;
|
||||
|
||||
void make_random()
|
||||
{
|
||||
for(size_t size = this->size(), i = 0; i < size; ++i)
|
||||
at(i).make_random();
|
||||
}
|
||||
|
||||
void resize_and_make_random(size_t size)
|
||||
{
|
||||
this->resize(size);
|
||||
make_random();
|
||||
}
|
||||
|
||||
|
||||
}; // scalar_vec_t
|
||||
|
||||
|
||||
|
|
@ -909,14 +1122,29 @@ namespace crypto
|
|||
|
||||
|
||||
//
|
||||
// Global constants
|
||||
// Global constants (checked in crypto_constants and crypto_generators_precomp tests)
|
||||
//
|
||||
|
||||
extern const point_g_t c_point_G;
|
||||
namespace xdetails
|
||||
{
|
||||
extern const precomp_data_t c_point_H_precomp_data;
|
||||
extern const precomp_data_t c_point_H2_precomp_data;
|
||||
extern const precomp_data_t c_point_U_precomp_data;
|
||||
extern const precomp_data_t c_point_X_precomp_data;
|
||||
extern const precomp_data_t c_point_H_plus_G_precomp_data;
|
||||
extern const precomp_data_t c_point_H_minus_G_precomp_data;
|
||||
};
|
||||
|
||||
inline constexpr point_t c_point_0 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }};
|
||||
inline constexpr point_g_t c_point_G {{ 25485296, 5318399, 8791791, -8299916, -14349720, 6939349, -3324311, -7717049, 7287234, -6577708, -758052, -1832720, 13046421, -4857925, 6576754, 14371947, -13139572, 6845540, -2198883, -4003719, -947565, 6097708, -469190, 10704810, -8556274, -15589498, -16424464, -16608899, 14028613, -5004649, 6966464, -2456167, 7033433, 6781840, 28785542, 12262365, -2659449, 13959020, -21013759, -5262166 }};
|
||||
|
||||
inline constexpr point_pc_t c_point_H {{ 20574939, 16670001, -29137604, 14614582, 24883426, 3503293, 2667523, 420631, 2267646, -4769165, -11764015, -12206428, -14187565, -2328122, -16242653, -788308, -12595746, -8251557, -10110987, 853396, -4982135, 6035602, -21214320, 16156349, 977218, 2807645, 31002271, 5694305, -16054128, 5644146, -15047429, -568775, -22568195, -8089957, -27721961, -10101877, -29459620, -13359100, -31515170, -6994674 }, &xdetails::c_point_H_precomp_data };
|
||||
inline constexpr point_pc_t c_point_H2 {{ 1318371, 14804112, 12545972, -13482561, -12089798, -16020744, -21221907, -8410994, -33080606, 11275578, 3807637, 11185450, -23227561, -12892068, 1356866, -1025012, -8022738, -8139671, -20315029, -13916324, -6475650, -7025596, 12403179, -5139984, -12068178, 10445584, -14826705, -4927780, 13964546, 12525942, -2314107, -10566315, 32243863, 15603849, 5154154, 4276633, -20918372, -15718796, -26386151, 8434696 }, &xdetails::c_point_H2_precomp_data };
|
||||
inline constexpr point_pc_t c_point_U {{ 30807552, 984924, 23426137, -5598760, 7545909, 16325843, 993742, 2594106, -31962071, -959867, 16454190, -4091093, 1197656, 13586872, -9269020, -14133290, 1869274, 13360979, -24627258, -10663086, 2212027, 1198856, 20515811, 15870563, -23833732, 9839517, -19416306, 11567295, -4212053, 348531, -2671541, 484270, -19128078, 1236698, -16002690, 9321345, 9776066, 10711838, 11187722, -16371275 }, &xdetails::c_point_U_precomp_data };
|
||||
inline constexpr point_pc_t c_point_X {{ 25635916, -5459446, 5768861, 5666160, -6357364, -12939311, 29490001, -4543704, -31266450, -2582476, 23705213, 9562626, -716512, 16560168, 7947407, 2039790, -2752711, 4742449, 3356761, 16338966, 17303421, -5790717, -5684800, 12062431, -3307947, 8139265, -26544839, 12058874, 3452748, 3359034, 26514848, -6060876, 31255039, 11154418, -21741975, -3782423, -19871841, 5729859, 21754676, -12454027 }, &xdetails::c_point_X_precomp_data };
|
||||
inline constexpr point_pc_t c_point_H_plus_G {{ 12291435, 3330843, -3390294, 13894858, -1099584, -6848191, 12040668, -15950068, -7494633, 12566672, -5526901, -16645799, -31081168, -1095427, -13082463, 4573480, -11255691, 4344628, 33477173, 11137213, -3837023, -12436594, -8471924, -814016, 10785607, 9492721, 10992667, 7406385, -5687296, -127915, -6229107, -9324867, 558657, 6493750, 4895261, 12642545, 9549220, 696086, 21894285, -10521807 }, &xdetails::c_point_H_plus_G_precomp_data };
|
||||
inline constexpr point_pc_t c_point_H_minus_G {{ -28347682, 3523701, -3380175, -14453727, 4238027, -6032522, 20235758, 4091609, 12557126, -8064113, 4212476, -13419094, -114185, -7650727, -24238, 16663404, 23676363, -6819610, 18286466, 8714527, -3837023, -12436594, -8471924, -814016, 10785607, 9492721, 10992667, 7406385, -5687296, -127915, -20450317, 13815641, -11604061, -447489, 27380225, 9400847, -8551293, -1173627, -28110171, 14241295 }, &xdetails::c_point_H_minus_G_precomp_data };
|
||||
|
||||
extern const point_t c_point_H;
|
||||
extern const point_t c_point_H2;
|
||||
extern const point_t c_point_0;
|
||||
|
||||
//
|
||||
// hash functions' helper
|
||||
|
|
@ -938,11 +1166,17 @@ namespace crypto
|
|||
return scalar_t(crypto::cn_fast_hash(str.c_str(), str.size())); // will reduce mod L
|
||||
}
|
||||
|
||||
static hash h(const std::string& str)
|
||||
{
|
||||
return crypto::cn_fast_hash(str.c_str(), str.size());
|
||||
}
|
||||
|
||||
struct hs_t
|
||||
{
|
||||
hs_t()
|
||||
hs_t(size_t size_to_reserve = 0)
|
||||
{
|
||||
static_assert(sizeof(scalar_t) == sizeof(crypto::public_key), "unexpected size of data");
|
||||
m_elements.reserve(size_to_reserve);
|
||||
}
|
||||
|
||||
void reserve(size_t elements_count)
|
||||
|
|
@ -984,6 +1218,11 @@ namespace crypto
|
|||
m_elements.emplace_back(pk);
|
||||
}
|
||||
|
||||
void add_key_image(const crypto::key_image& ki)
|
||||
{
|
||||
m_elements.emplace_back(ki);
|
||||
}
|
||||
|
||||
scalar_t& access_scalar(size_t index)
|
||||
{
|
||||
return m_elements[index].scalar;
|
||||
|
|
@ -1012,6 +1251,16 @@ namespace crypto
|
|||
m_elements.emplace_back(key_image_array[i]);
|
||||
}
|
||||
|
||||
void add_hash(const hash& h)
|
||||
{
|
||||
m_elements.emplace_back(h);
|
||||
}
|
||||
|
||||
void add_32_chars(const char(&str32)[32])
|
||||
{
|
||||
m_elements.emplace_back(str32);
|
||||
}
|
||||
|
||||
scalar_t calc_hash(bool clear = true)
|
||||
{
|
||||
size_t data_size_bytes = m_elements.size() * sizeof(item_t);
|
||||
|
|
@ -1022,6 +1271,16 @@ namespace crypto
|
|||
return scalar_t(hash); // this will reduce to L
|
||||
}
|
||||
|
||||
hash calc_hash_no_reduce(bool clear = true)
|
||||
{
|
||||
size_t data_size_bytes = m_elements.size() * sizeof(item_t);
|
||||
hash result;
|
||||
crypto::cn_fast_hash(m_elements.data(), data_size_bytes, result);
|
||||
if (clear)
|
||||
this->clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
void assign_calc_hash(scalar_t& result, bool clear = true)
|
||||
{
|
||||
static_assert(sizeof result == sizeof(crypto::hash), "size missmatch");
|
||||
|
|
@ -1038,17 +1297,24 @@ namespace crypto
|
|||
item_t(const scalar_t& scalar) : scalar(scalar) {}
|
||||
item_t(const crypto::public_key& pk) : pk(pk) {}
|
||||
item_t(const crypto::key_image& ki) : ki(ki) {}
|
||||
item_t(const crypto::hash& h) : h(h) {}
|
||||
item_t(const char(&str32)[32]) { memcpy(c, str32, sizeof c); }
|
||||
scalar_t scalar;
|
||||
crypto::public_key pk;
|
||||
crypto::key_image ki;
|
||||
crypto::hash h;
|
||||
char c[32];
|
||||
};
|
||||
|
||||
static_assert(sizeof(item_t::c) == sizeof(item_t::pk), "size missmatch");
|
||||
static_assert(sizeof(item_t::h) == sizeof(item_t::pk), "size missmatch");
|
||||
|
||||
std::vector<item_t> m_elements;
|
||||
};
|
||||
|
||||
static scalar_t hs(const scalar_t& s, const std::vector<point_t>& ps0, const std::vector<point_t>& ps1)
|
||||
{
|
||||
hs_t hs_calculator;
|
||||
hs_t hs_calculator(3);
|
||||
hs_calculator.add_scalar(s);
|
||||
hs_calculator.add_points_array(ps0);
|
||||
hs_calculator.add_points_array(ps1);
|
||||
|
|
@ -1058,7 +1324,7 @@ namespace crypto
|
|||
static scalar_t hs(const crypto::hash& s, const std::vector<crypto::public_key>& ps0, const std::vector<crypto::key_image>& ps1)
|
||||
{
|
||||
static_assert(sizeof(crypto::hash) == sizeof(scalar_t), "size missmatch");
|
||||
hs_t hs_calculator;
|
||||
hs_t hs_calculator(3);
|
||||
hs_calculator.add_scalar(*reinterpret_cast<const scalar_t*>(&s));
|
||||
hs_calculator.add_pub_keys_array(ps0);
|
||||
hs_calculator.add_key_images_array(ps1);
|
||||
|
|
@ -1067,12 +1333,79 @@ namespace crypto
|
|||
|
||||
static scalar_t hs(const std::vector<point_t>& ps0, const std::vector<point_t>& ps1)
|
||||
{
|
||||
hs_t hs_calculator;
|
||||
hs_t hs_calculator(2);
|
||||
hs_calculator.add_points_array(ps0);
|
||||
hs_calculator.add_points_array(ps1);
|
||||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static scalar_t hs(const char(&str32)[32], const scalar_t& s)
|
||||
{
|
||||
hs_t hs_calculator(2);
|
||||
hs_calculator.add_32_chars(str32);
|
||||
hs_calculator.add_scalar(s);
|
||||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static scalar_t hs(const char(&str32)[32], const scalar_t& s, const crypto::public_key& pk)
|
||||
{
|
||||
hs_t hs_calculator(2);
|
||||
hs_calculator.add_32_chars(str32);
|
||||
hs_calculator.add_scalar(s);
|
||||
hs_calculator.add_pub_key(pk);
|
||||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static scalar_t hs(const crypto::public_key& pk, const uint64_t i)
|
||||
{
|
||||
hs_t hs_calculator(2);
|
||||
hs_calculator.add_pub_key(pk);
|
||||
hs_calculator.add_scalar(scalar_t(i));
|
||||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static scalar_t hs(const crypto::secret_key& sk, const uint64_t i)
|
||||
{
|
||||
hs_t hs_calculator(2);
|
||||
hs_calculator.add_scalar(sk);
|
||||
hs_calculator.add_scalar(scalar_t(i));
|
||||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static scalar_t hs(const char(&str32)[32], const crypto::public_key& pk, const uint64_t i)
|
||||
{
|
||||
hs_t hs_calculator(3);
|
||||
hs_calculator.add_32_chars(str32);
|
||||
hs_calculator.add_pub_key(pk);
|
||||
hs_calculator.add_scalar(scalar_t(i));
|
||||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static scalar_t hs(const char(&str32)[32], const crypto::hash& h)
|
||||
{
|
||||
hs_t hs_calculator(2);
|
||||
hs_calculator.add_32_chars(str32);
|
||||
hs_calculator.add_hash(h);
|
||||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static scalar_t hs(const char(&str32)[32], const crypto::point_t& p)
|
||||
{
|
||||
hs_t hs_calculator(2);
|
||||
hs_calculator.add_32_chars(str32);
|
||||
hs_calculator.add_point(p);
|
||||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static scalar_t hs(const char(&str32)[32], const crypto::key_derivation& derivation, uint64_t index)
|
||||
{
|
||||
hs_t hs_calculator(3);
|
||||
hs_calculator.add_32_chars(str32);
|
||||
hs_calculator.add_pub_key(reinterpret_cast<const crypto::public_key&>(derivation));
|
||||
hs_calculator.add_scalar(index);
|
||||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static point_t hp(const point_t& p)
|
||||
{
|
||||
point_t result;
|
||||
|
|
@ -1104,6 +1437,13 @@ namespace crypto
|
|||
return result;
|
||||
}
|
||||
|
||||
static point_t hp(const std::string& str)
|
||||
{
|
||||
point_t result;
|
||||
ge_bytes_hash_to_ec(&result.m_p3, str.data(), str.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
}; // hash_helper_t struct
|
||||
|
||||
|
||||
|
|
@ -1111,7 +1451,6 @@ namespace crypto
|
|||
{
|
||||
// hs won't touch memory if size is 0, so it's safe
|
||||
return hash_helper_t::hs(data(), sizeof(scalar_t) * size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace crypto
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2019 Zano Project
|
||||
// Copyright (c) 2014-2022 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
|
@ -19,9 +19,9 @@
|
|||
#include "hash.h"
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
# define crypto_assert(expression) assert(expression)
|
||||
# define crypto_assert(expression) assert(expression); CRYPTO_CHECK_AND_THROW_MES(expression, #expression)
|
||||
#else
|
||||
# define crypto_assert(expression) ((void)0)
|
||||
# define crypto_assert(expression) CRYPTO_CHECK_AND_THROW_MES(expression, #expression)
|
||||
#endif
|
||||
|
||||
namespace crypto {
|
||||
|
|
@ -187,7 +187,8 @@ namespace crypto {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) {
|
||||
void crypto_ops::derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
|
||||
{
|
||||
struct {
|
||||
key_derivation derivation;
|
||||
char output_index[(sizeof(size_t) * 8 + 6) / 7];
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@
|
|||
#include "hash.h"
|
||||
#include "warnings.h"
|
||||
|
||||
#define CRYPTO_STR_(X) #X
|
||||
#define CRYPTO_STR(X) CRYPTO_STR_(X)
|
||||
#define CRYPTO_CHECK_AND_THROW_MES(cond, msg) if (!(cond)) { throw std::runtime_error(msg " @ " __FILE__ ":" CRYPTO_STR(__LINE__)); }
|
||||
|
||||
PUSH_GCC_WARNINGS
|
||||
DISABLE_CLANG_WARNING(unused-private-field)
|
||||
|
|
@ -86,6 +89,8 @@ namespace crypto {
|
|||
friend bool secret_key_to_public_key(const secret_key &, public_key &);
|
||||
static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
|
||||
friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
|
||||
static void derivation_to_scalar(const key_derivation &, size_t, ec_scalar &);
|
||||
friend void derivation_to_scalar(const key_derivation &, size_t, ec_scalar &);
|
||||
static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
|
||||
friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
|
||||
static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
|
||||
|
|
@ -174,6 +179,10 @@ namespace crypto {
|
|||
inline bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) {
|
||||
return crypto_ops::generate_key_derivation(key1, key2, derivation);
|
||||
}
|
||||
inline void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &result) {
|
||||
crypto::crypto_ops::derivation_to_scalar(derivation, output_index, result);
|
||||
}
|
||||
|
||||
inline bool derive_public_key(const key_derivation &derivation, std::size_t output_index,
|
||||
const public_key &base, public_key &derived_key) {
|
||||
return crypto_ops::derive_public_key(derivation, output_index, base, derived_key);
|
||||
|
|
|
|||
25
src/crypto/msm.cpp
Normal file
25
src/crypto/msm.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) 2023-2023 Zano Project
|
||||
// Copyright (c) 2023-2023 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
#include "epee/include/misc_log_ex.h"
|
||||
//#include "zarcanum.h"
|
||||
#include "msm.h"
|
||||
//#include "../currency_core/crypto_config.h" // TODO: move it to the crypto
|
||||
//#include "../common/crypto_stream_operators.h" // TODO: move it to the crypto
|
||||
|
||||
#if 0
|
||||
# define DBG_VAL_PRINT(x) std::cout << std::setw(30) << std::left << #x ": " << x << std::endl
|
||||
# define DBG_PRINT(x) std::cout << x << std::endl
|
||||
#else
|
||||
# define DBG_VAL_PRINT(x) (void(0))
|
||||
# define DBG_PRINT(x) (void(0))
|
||||
#endif
|
||||
|
||||
namespace crypto
|
||||
{
|
||||
|
||||
|
||||
|
||||
} // namespace crypto
|
||||
173
src/crypto/msm.h
Normal file
173
src/crypto/msm.h
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
// Copyright (c) 2023-2023 Zano Project (https://zano.org/)
|
||||
// Copyright (c) 2023-2023 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#pragma once
|
||||
|
||||
// This file contains Multi-Scalar Multiplication routines
|
||||
|
||||
#include "epee/include/misc_log_ex.h"
|
||||
#include "crypto-sugar.h"
|
||||
|
||||
namespace crypto
|
||||
{
|
||||
|
||||
template<typename CT>
|
||||
bool msm_and_check_zero_naive(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(g_scalars.size() <= CT::c_bpp_mn_max, false, "g_scalars oversized");
|
||||
CHECK_AND_ASSERT_MES(h_scalars.size() <= CT::c_bpp_mn_max, false, "h_scalars oversized");
|
||||
|
||||
point_t result = summand;
|
||||
|
||||
for (size_t i = 0; i < g_scalars.size(); ++i)
|
||||
result += g_scalars[i] * CT::get_generator(false, i);
|
||||
|
||||
for (size_t i = 0; i < h_scalars.size(); ++i)
|
||||
result += h_scalars[i] * CT::get_generator(true, i);
|
||||
|
||||
if (!result.is_zero())
|
||||
{
|
||||
LOG_PRINT_L0("msm result is non zero: " << result);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// https://eprint.iacr.org/2022/999.pdf
|
||||
// "Pippenger algorithm [1], and its variant that is widely used in the ZK space is called the bucket method"
|
||||
template<typename CT>
|
||||
bool msm_and_check_zero_pippenger_v3(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand, uint8_t c)
|
||||
{
|
||||
// TODO: with c = 8 and with direct access got much worse result than with c = 7 and get_bits() for N = 128..256, consider checking again for bigger datasets (N>256)
|
||||
// TODO: consider preparing a cached generators' points
|
||||
|
||||
CHECK_AND_ASSERT_MES(g_scalars.size() <= CT::c_bpp_mn_max, false, "g_scalars oversized");
|
||||
CHECK_AND_ASSERT_MES(h_scalars.size() <= CT::c_bpp_mn_max, false, "h_scalars oversized");
|
||||
CHECK_AND_ASSERT_MES(c < 10, false, "c is too big");
|
||||
|
||||
size_t C = 1ull << c;
|
||||
|
||||
// k_max * c + (c-1) >= max_bit_idx
|
||||
//
|
||||
// max_bit_idx - (c - 1) max_bit_idx - (c - 1) + (c - 1) max_bit_idx
|
||||
// k_max = ceil ( --------------------- ) = floor ( ------------------------------ ) = floor ( ----------- )
|
||||
// c c c
|
||||
const size_t b = 253; // the maximum number of bits in x https://eprint.iacr.org/2022/999.pdf TODO: we may also scan for maximum bit used in all the scalars if all the scalars are small
|
||||
const size_t max_bit_idx = b - 1;
|
||||
const size_t k_max = max_bit_idx / c;
|
||||
const size_t K = k_max + 1;
|
||||
|
||||
std::vector<point_t> buckets(C * K);
|
||||
std::vector<bool> buckets_inited(C * K);
|
||||
std::vector<point_t> Sk(K);
|
||||
std::vector<bool> Sk_inited(K);
|
||||
std::vector<point_t> Gk(K);
|
||||
std::vector<bool> Gk_inited(K);
|
||||
|
||||
// first loop, calculate partial bucket sums
|
||||
for (size_t n = 0; n < g_scalars.size(); ++n)
|
||||
{
|
||||
for (size_t k = 0; k < K; ++k)
|
||||
{
|
||||
uint64_t l = g_scalars[n].get_bits((uint8_t)(k * c), c); // l in [0; 2^c-1]
|
||||
if (l != 0)
|
||||
{
|
||||
size_t bucket_id = l * K + k;
|
||||
if (buckets_inited[bucket_id])
|
||||
buckets[bucket_id] += CT::get_generator(false, n);
|
||||
else
|
||||
{
|
||||
buckets[bucket_id] = CT::get_generator(false, n);
|
||||
buckets_inited[bucket_id] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// still the first loop (continued)
|
||||
for (size_t n = 0; n < h_scalars.size(); ++n)
|
||||
{
|
||||
for (size_t k = 0; k < K; ++k)
|
||||
{
|
||||
uint64_t l = h_scalars[n].get_bits((uint8_t)(k * c), c); // l in [0; 2^c-1]
|
||||
if (l != 0)
|
||||
{
|
||||
size_t bucket_id = l * K + k;
|
||||
if (buckets_inited[bucket_id])
|
||||
buckets[bucket_id] += CT::get_generator(true, n);
|
||||
else
|
||||
{
|
||||
buckets[bucket_id] = CT::get_generator(true, n);
|
||||
buckets_inited[bucket_id] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the second loop
|
||||
for (size_t l = C - 1; l > 0; --l)
|
||||
{
|
||||
for (size_t k = 0; k < K; ++k)
|
||||
{
|
||||
size_t bucket_id = l * K + k;
|
||||
if (buckets_inited[bucket_id])
|
||||
{
|
||||
if (Sk_inited[k])
|
||||
Sk[k] += buckets[bucket_id];
|
||||
else
|
||||
{
|
||||
Sk[k] = buckets[bucket_id];
|
||||
Sk_inited[k] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (Sk_inited[k])
|
||||
{
|
||||
if (Gk_inited[k])
|
||||
Gk[k] += Sk[k];
|
||||
else
|
||||
{
|
||||
Gk[k] = Sk[k];
|
||||
Gk_inited[k] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the third loop: Horner’s rule
|
||||
point_t result = Gk_inited[K - 1] ? Gk[K - 1] : c_point_0;
|
||||
for (size_t k = K - 2; k != SIZE_MAX; --k)
|
||||
{
|
||||
result.modify_mul_pow_2(c);
|
||||
if (Gk_inited[k])
|
||||
result += Gk[k];
|
||||
}
|
||||
|
||||
result += summand;
|
||||
|
||||
if (!result.is_zero())
|
||||
{
|
||||
LOG_PRINT_L0("multiexp result is non zero: " << result);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Just switcher
|
||||
|
||||
template<typename CT>
|
||||
bool msm_and_check_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand)
|
||||
{
|
||||
//return msm_and_check_zero_naive<CT>(g_scalars, h_scalars, summand);
|
||||
return msm_and_check_zero_pippenger_v3<CT>(g_scalars, h_scalars, summand, 7);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace crypto
|
||||
322
src/crypto/one_out_of_many_proofs.cpp
Normal file
322
src/crypto/one_out_of_many_proofs.cpp
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
// Copyright (c) 2023 Zano Project
|
||||
// Copyright (c) 2023 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
#include "one_out_of_many_proofs.h"
|
||||
#include "../currency_core/crypto_config.h"
|
||||
#include "epee/include/misc_log_ex.h"
|
||||
|
||||
//DISABLE_GCC_AND_CLANG_WARNING(unused-function)
|
||||
|
||||
#if 0
|
||||
# define DBG_VAL_PRINT(x) std::cout << std::setw(30) << std::left << #x ": " << x << std::endl
|
||||
# define DBG_PRINT(x) std::cout << x << std::endl
|
||||
#else
|
||||
# define DBG_VAL_PRINT(x) (void(0))
|
||||
# define DBG_PRINT(x) (void(0))
|
||||
#endif
|
||||
|
||||
namespace crypto
|
||||
{
|
||||
static const size_t N_max = 256;
|
||||
static const size_t mn_max = 16;
|
||||
|
||||
const point_t& get_BGE_generator(size_t index, bool& ok)
|
||||
{
|
||||
static std::vector<point_t> precalculated_generators;
|
||||
if (precalculated_generators.empty())
|
||||
{
|
||||
precalculated_generators.resize(mn_max * 2);
|
||||
|
||||
scalar_t hash_buf[2] = { hash_helper_t::hs("Zano BGE generator"), 0 };
|
||||
|
||||
for(size_t i = 0; i < precalculated_generators.size(); ++i)
|
||||
{
|
||||
hash_buf[1].m_u64[0] = i;
|
||||
precalculated_generators[i] = hash_helper_t::hp(&hash_buf, sizeof hash_buf);
|
||||
}
|
||||
}
|
||||
|
||||
if (index >= mn_max * 2)
|
||||
{
|
||||
ok = false;
|
||||
return c_point_0;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
return precalculated_generators[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("generate_BGE_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
bool generate_BGE_proof(const hash& context_hash, const std::vector<point_t>& ring, const scalar_t& secret, const size_t secret_index, BGE_proof& result, uint8_t* p_err /* = nullptr */)
|
||||
{
|
||||
static constexpr size_t n = 4; // TODO: @#@# move it out
|
||||
|
||||
DBG_PRINT(" - - - generate_BGE_proof - - -");
|
||||
size_t ring_size = ring.size();
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(ring_size > 0, 0);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(secret_index < ring_size, 1);
|
||||
|
||||
#ifndef NDEBUG
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(ring[secret_index] == secret * crypto::c_point_X, 2);
|
||||
#endif
|
||||
|
||||
|
||||
const size_t m = std::max(static_cast<uint64_t>(1), constexpr_ceil_log_n(ring_size, n));
|
||||
const size_t N = constexpr_pow(m, n);
|
||||
const size_t mn = m * n;
|
||||
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(N <= N_max, 3);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(mn <= mn_max, 4);
|
||||
|
||||
scalar_mat_t<n> a_mat(mn); // m x n matrix
|
||||
a_mat.zero();
|
||||
std::vector<size_t> l_digits(m); // l => n-ary gidits
|
||||
size_t l = secret_index;
|
||||
for(size_t j = 0; j < m; ++j)
|
||||
{
|
||||
for(size_t i = n - 1; i != 0; --i) // [n - 1; 1]
|
||||
{
|
||||
a_mat(j, i).make_random();
|
||||
a_mat(j, 0) -= a_mat(j, i); // a[j; 0] = -sum( a[j; i] ), i in [1; n-1]
|
||||
}
|
||||
|
||||
size_t digit = l % n; // j-th digit of secret_index
|
||||
l_digits[j] = digit;
|
||||
l = l / n;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
for(size_t j = 0; j < m; ++j)
|
||||
{
|
||||
scalar_t a_sum{};
|
||||
for(size_t i = 0; i != n; ++i)
|
||||
a_sum += a_mat(j, i);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(a_sum.is_zero(), 230);
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// coeffs calculation (naive implementation, consider optimization in future)
|
||||
//
|
||||
scalar_vec_t coeffs(N * m); // m x N matrix
|
||||
coeffs.zero();
|
||||
for(size_t i = 0; i < N; ++i)
|
||||
{
|
||||
coeffs[i] = c_scalar_1; // first row is (1, ..., 1)
|
||||
size_t i_tmp = i;
|
||||
size_t m_bound = 1;
|
||||
for(size_t j = 0; j < m; ++j)
|
||||
{
|
||||
size_t i_j = i_tmp % n; // j-th digit of i
|
||||
i_tmp /= n;
|
||||
|
||||
if (i_j == l_digits[j]) // true if j-th digits of i and l matches
|
||||
{
|
||||
scalar_t carry{};
|
||||
for(size_t k = 0; k < m_bound; ++k)
|
||||
{
|
||||
scalar_t old = coeffs[k * N + i];
|
||||
coeffs[k * N + i] *= a_mat(j, i_j);
|
||||
coeffs[k * N + i] += carry;
|
||||
carry = old;
|
||||
}
|
||||
if (m_bound < m)
|
||||
coeffs[m_bound * N + i] += carry;
|
||||
++m_bound;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_t k = 0; k < m_bound; ++k)
|
||||
coeffs[k * N + i] *= a_mat(j, i_j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scalar_t r_A = scalar_t::random();
|
||||
scalar_t r_B = scalar_t::random();
|
||||
scalar_vec_t ro(m);
|
||||
ro.make_random();
|
||||
|
||||
point_t A = c_point_0;
|
||||
point_t B = c_point_0;
|
||||
|
||||
result.Pk.clear();
|
||||
|
||||
bool r = false, r2 = false;
|
||||
for(size_t j = 0; j < m; ++j)
|
||||
{
|
||||
for(size_t i = 0; i < n; ++i)
|
||||
{
|
||||
const point_t& gen_1 = get_BGE_generator((j * n + i) * 2 + 0, r);
|
||||
const point_t& gen_2 = get_BGE_generator((j * n + i) * 2 + 1, r2);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(r && r2, 5);
|
||||
const scalar_t& a = a_mat(j, i);
|
||||
A += a * gen_1 - a * a * gen_2;
|
||||
if (l_digits[j] == i)
|
||||
B += gen_1 - a * gen_2;
|
||||
else
|
||||
B += a * gen_2;
|
||||
}
|
||||
|
||||
point_t Pk = c_point_0;
|
||||
for(size_t i = 0; i < ring_size; ++i)
|
||||
Pk += coeffs[j * N + i] * ring[i];
|
||||
for(size_t i = ring_size; i < N; ++i)
|
||||
Pk += coeffs[j * N + i] * ring[ring_size - 1];
|
||||
|
||||
Pk += ro[j] * c_point_X;
|
||||
result.Pk.emplace_back(std::move((c_scalar_1div8 * Pk).to_public_key()));
|
||||
}
|
||||
|
||||
A += r_A * c_point_X;
|
||||
result.A = (c_scalar_1div8 * A).to_public_key();
|
||||
B += r_B * c_point_X;
|
||||
result.B = (c_scalar_1div8 * B).to_public_key();
|
||||
|
||||
hash_helper_t::hs_t hsc(1 + ring_size + 2 + m);
|
||||
hsc.add_hash(context_hash);
|
||||
for(auto& ring_el : ring)
|
||||
hsc.add_point(c_scalar_1div8 * ring_el);
|
||||
hsc.add_pub_key(result.A);
|
||||
hsc.add_pub_key(result.B);
|
||||
hsc.add_pub_keys_array(result.Pk);
|
||||
scalar_t x = hsc.calc_hash();
|
||||
DBG_VAL_PRINT(x);
|
||||
|
||||
result.f.resize(m * (n - 1));
|
||||
for(size_t j = 0; j < m; ++j)
|
||||
{
|
||||
for(size_t i = 1; i < n; ++i)
|
||||
{
|
||||
result.f[j * (n - 1) + i - 1] = a_mat(j, i);
|
||||
if (l_digits[j] == i)
|
||||
result.f[j * (n - 1) + i - 1] += x;
|
||||
}
|
||||
}
|
||||
|
||||
result.y = r_A + x * r_B;
|
||||
|
||||
result.z = 0;
|
||||
scalar_t x_power = c_scalar_1;
|
||||
for(size_t k = 0; k < m; ++k)
|
||||
{
|
||||
result.z -= x_power * ro[k];
|
||||
x_power *= x;
|
||||
}
|
||||
result.z += secret * x_power;
|
||||
|
||||
return true;
|
||||
}
|
||||
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
|
||||
|
||||
//---------------------------------------------------------------
|
||||
|
||||
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("generate_BGE_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
bool verify_BGE_proof(const hash& context_hash, const std::vector<const public_key*>& ring, const BGE_proof& sig, uint8_t* p_err /* = nullptr */)
|
||||
{
|
||||
static constexpr size_t n = 4; // TODO: @#@# move it out
|
||||
|
||||
DBG_PRINT(" - - - verify_BGE_proof - - -");
|
||||
size_t ring_size = ring.size();
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(ring_size > 0, 0);
|
||||
|
||||
const size_t m = std::max(static_cast<uint64_t>(1), constexpr_ceil_log_n(ring_size, n));
|
||||
const size_t N = constexpr_pow(m, n);
|
||||
//const size_t mn = m * n;
|
||||
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.Pk.size() == m, 1);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.f.size() == m * (n - 1), 2);
|
||||
|
||||
hash_helper_t::hs_t hsc(1 + ring_size + 2 + m);
|
||||
hsc.add_hash(context_hash);
|
||||
for(const public_key* ppk : ring)
|
||||
hsc.add_pub_key(*ppk);
|
||||
hsc.add_pub_key(sig.A);
|
||||
hsc.add_pub_key(sig.B);
|
||||
hsc.add_pub_keys_array(sig.Pk);
|
||||
scalar_t x = hsc.calc_hash();
|
||||
DBG_VAL_PRINT(x);
|
||||
|
||||
scalar_vec_t f0(m); // the first column f_{i,0} = x - sum{j=1}{n-1}( f_{i,j} )
|
||||
for(size_t j = 0; j < m; ++j)
|
||||
{
|
||||
f0[j] = x;
|
||||
for(size_t i = 1; i < n; ++i)
|
||||
f0[j] -= sig.f[j * (n - 1) + i - 1];
|
||||
}
|
||||
|
||||
//
|
||||
// 1
|
||||
//
|
||||
point_t A = point_t(sig.A).modify_mul8();
|
||||
point_t B = point_t(sig.B).modify_mul8();
|
||||
|
||||
point_t Z = A + x * B;
|
||||
|
||||
bool r = false, r2 = false;
|
||||
for(size_t j = 0; j < m; ++j)
|
||||
{
|
||||
for(size_t i = 0; i < n; ++i)
|
||||
{
|
||||
const point_t& gen_1 = get_BGE_generator((j * n + i) * 2 + 0, r);
|
||||
const point_t& gen_2 = get_BGE_generator((j * n + i) * 2 + 1, r2);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(r && r2, 5);
|
||||
const scalar_t& f_ji = (i == 0) ? f0[j] : sig.f[j * (n - 1) + i - 1];
|
||||
|
||||
Z -= f_ji * gen_1 + f_ji * (x - f_ji) * gen_2;
|
||||
}
|
||||
}
|
||||
Z -= sig.y * c_point_X;
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(Z.is_zero(), 100);
|
||||
|
||||
//
|
||||
// 2
|
||||
//
|
||||
scalar_vec_t p_vec(N);
|
||||
for(size_t i = 0; i < N; ++i)
|
||||
{
|
||||
p_vec[i] = c_scalar_1;
|
||||
size_t i_tmp = i;
|
||||
for(size_t j = 0; j < m; ++j)
|
||||
{
|
||||
size_t i_j = i_tmp % n; // j-th digit of i
|
||||
i_tmp /= n;
|
||||
const scalar_t& f_jij = (i_j == 0) ? f0[j] : sig.f[j * (n - 1) + i_j - 1];
|
||||
p_vec[i] *= f_jij;
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < ring_size; ++i)
|
||||
Z += p_vec[i] * point_t(*ring[i]).modify_mul8();
|
||||
for(size_t i = ring_size; i < N; ++i)
|
||||
Z += p_vec[i] * point_t(*ring[ring_size - 1]).modify_mul8();
|
||||
|
||||
scalar_t x_power = c_scalar_1;
|
||||
for(size_t k = 0; k < m; ++k)
|
||||
{
|
||||
Z -= x_power * point_t(sig.Pk[k]).modify_mul8();
|
||||
x_power *= x;
|
||||
}
|
||||
|
||||
Z -= sig.z * c_point_X;
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(Z.is_zero(), 101);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
|
||||
|
||||
|
||||
} // namespace crypto
|
||||
47
src/crypto/one_out_of_many_proofs.h
Normal file
47
src/crypto/one_out_of_many_proofs.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) 2023 Zano Project
|
||||
// Copyright (c) 2023 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
#pragma once
|
||||
#include "crypto-sugar.h"
|
||||
|
||||
namespace crypto
|
||||
{
|
||||
//
|
||||
// BGE stands for Bootle, Groth, Esgin
|
||||
//
|
||||
// This is a proof-of-concept implementation of a log-size one-out-of-many proof based on ideas and approaches by Bootle et al, Groth et al and Esgin et al
|
||||
//
|
||||
// https://eprint.iacr.org/2014/764
|
||||
// https://eprint.iacr.org/2015/643
|
||||
// https://eprint.iacr.org/2019/1287
|
||||
//
|
||||
// Disclaimer: shouldn't be used in production code until the security proofs and the code are peer-reviewed.
|
||||
//
|
||||
|
||||
// m+2 group elements, m(n-1)+2 field elements.
|
||||
// Assuming fixed n=4, m = log4(ring_sz) the size is (log4(ring_sz) + 2) group elements and (3*log4(ring_sz) + 2) or, in total, (4*log4(ring_sz) + 4) 32-bytes words
|
||||
|
||||
// ring_sz = m (inputs number)
|
||||
// sig_count = k (outputs number)
|
||||
// thus:
|
||||
// k * (log4(m) + 2) group elements and k * (3*log4(m) + 2) field elements
|
||||
|
||||
struct BGE_proof
|
||||
{
|
||||
public_key A; // premultiplied by 1/8
|
||||
public_key B; // premultiplied by 1/8
|
||||
std::vector<public_key> Pk; // premultiplied by 1/8, size = m
|
||||
scalar_vec_t f; // size = m * (n - 1)
|
||||
scalar_t y;
|
||||
scalar_t z;
|
||||
};
|
||||
|
||||
bool generate_BGE_proof(const hash& context_hash, const std::vector<point_t>& ring, const scalar_t& secret, const size_t secret_index, BGE_proof& result, uint8_t* p_err = nullptr);
|
||||
|
||||
|
||||
bool verify_BGE_proof(const hash& context_hash, const std::vector<const public_key*>& ring, const BGE_proof& sig, uint8_t* p_err = nullptr);
|
||||
|
||||
|
||||
} // namespace crypto
|
||||
|
|
@ -23,18 +23,26 @@ namespace crypto
|
|||
scalar_t delta;
|
||||
};
|
||||
|
||||
#define DBG_VAL_PRINT(x) std::cout << #x ": " << x << ENDL
|
||||
#define DBG_PRINT(x) std::cout << x << ENDL
|
||||
#if 0
|
||||
# define DBG_VAL_PRINT(x) std::cout << std::setw(30) << std::left << #x ": " << x << std::endl
|
||||
# define DBG_PRINT(x) std::cout << x << std::endl
|
||||
#else
|
||||
# define DBG_VAL_PRINT(x) (void(0))
|
||||
# define DBG_PRINT(x) (void(0))
|
||||
#endif
|
||||
|
||||
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("bpp_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
|
||||
template<typename CT>
|
||||
bool bpp_gen(const scalar_vec_t& values, const scalar_vec_t& masks, bpp_signature& sig, std::vector<point_t>& commitments, uint8_t* p_err = nullptr)
|
||||
bool bpp_gen(const scalar_vec_t& values, const scalar_vec_t& masks, const std::vector<const crypto::public_key*>& commitments_1div8, bpp_signature& sig, uint8_t* p_err = nullptr)
|
||||
{
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("bpp_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
// Note: commitments_1div8 are supposed to be already calculated
|
||||
static_assert(CT::c_bpp_n <= 255, "too big N");
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() > 0 && values.size() <= CT::c_bpp_values_max && values.size() == masks.size(), 1);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() > 0 && values.size() <= CT::c_bpp_values_max && values.size() == masks.size() && values.size() == commitments_1div8.size(), 1);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(masks.is_reduced(), 3);
|
||||
|
||||
const size_t c_bpp_log2_m = constexpr_ceil_log2(values.size());
|
||||
|
|
@ -42,14 +50,14 @@ namespace crypto
|
|||
const size_t c_bpp_mn = c_bpp_m * CT::c_bpp_n;
|
||||
const size_t c_bpp_log2_mn = c_bpp_log2_m + CT::c_bpp_log2_n;
|
||||
|
||||
// pre-multiply all output points by c_scalar_1div8
|
||||
// in order to enforce these points to be in the prime-order subgroup (after mul by 8 in bpp_verify())
|
||||
|
||||
// calc commitments vector as commitments[i] = 1/8 * values[i] * G + 1/8 * masks[i] * H
|
||||
commitments.resize(values.size());
|
||||
for (size_t i = 0; i < values.size(); ++i)
|
||||
CT::calc_pedersen_commitment(values[i] * c_scalar_1div8, masks[i] * c_scalar_1div8, commitments[i]);
|
||||
|
||||
#ifndef NDEBUG
|
||||
for(size_t i = 0; i < values.size(); ++i)
|
||||
{
|
||||
point_t V{};
|
||||
CT::calc_pedersen_commitment(values[i], masks[i], V);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(point_t(*commitments_1div8[i]).modify_mul8() == V, 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
// s.a. BP+ paper, page 15, eq. 11
|
||||
// decompose v into aL and aR:
|
||||
|
|
@ -85,7 +93,7 @@ namespace crypto
|
|||
DBG_PRINT("initial transcript: " << e);
|
||||
|
||||
hash_helper_t::hs_t hsc;
|
||||
CT::update_transcript(hsc, e, commitments);
|
||||
CT::update_transcript(hsc, e, commitments_1div8);
|
||||
|
||||
// BP+ paper, page 15: The prover begins with sending A = g^aL h^aR h^alpha (group element)
|
||||
// so we calculate A0 = alpha * H + SUM(aL_i * G_i) + SUM(aR_i * H_i)
|
||||
|
|
@ -96,7 +104,8 @@ namespace crypto
|
|||
for (size_t i = 0; i < c_bpp_mn; ++i)
|
||||
A0 += aLs[i] * CT::get_generator(false, i) + aRs[i] * CT::get_generator(true, i);
|
||||
|
||||
// part of 1/8 defense scheme
|
||||
// pre-multiply all output points by c_scalar_1div8
|
||||
// in order to enforce these points to be in the prime-order subgroup (after mul by 8 in bpp_verify())
|
||||
A0 *= c_scalar_1div8;
|
||||
A0.to_public_key(sig.A0);
|
||||
|
||||
|
|
@ -147,7 +156,7 @@ namespace crypto
|
|||
|
||||
// aL_hat = aL - 1*z
|
||||
scalar_vec_t aLs_hat = aLs - z;
|
||||
// aL_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3)
|
||||
// aR_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3)
|
||||
scalar_vec_t aRs_hat = aRs + z;
|
||||
for (size_t i = 0; i < c_bpp_mn; ++i)
|
||||
aRs_hat[i] += d[i] * y_powers[c_bpp_mn - i];
|
||||
|
|
@ -324,9 +333,27 @@ namespace crypto
|
|||
DBG_VAL_PRINT(sig.delta);
|
||||
|
||||
return true;
|
||||
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
|
||||
} // bpp_gen()
|
||||
|
||||
|
||||
// convenient overload for tests
|
||||
template<typename CT>
|
||||
bool bpp_gen(const scalar_vec_t& values, const scalar_vec_t& masks, bpp_signature& sig, std::vector<point_t>& commitments_1div8_to_be_generated, uint8_t* p_err = nullptr)
|
||||
{
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() == masks.size(), 91);
|
||||
commitments_1div8_to_be_generated.resize(values.size());
|
||||
std::vector<crypto::public_key> commitments_1div8(values.size());
|
||||
std::vector<const crypto::public_key*> commitments_1div8_pointers(values.size());
|
||||
for(size_t i = 0; i < values.size(); ++i)
|
||||
{
|
||||
CT::calc_pedersen_commitment(c_scalar_1div8 * values[i], c_scalar_1div8 * masks[i], commitments_1div8_to_be_generated[i]);
|
||||
commitments_1div8[i] = (commitments_1div8_to_be_generated[i]).to_public_key();
|
||||
commitments_1div8_pointers[i] = &commitments_1div8[i];
|
||||
}
|
||||
return bpp_gen<CT>(values, masks, commitments_1div8_pointers, sig, p_err);
|
||||
}
|
||||
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
|
||||
|
||||
|
||||
struct bpp_sig_commit_ref_t
|
||||
{
|
||||
|
|
@ -335,7 +362,7 @@ namespace crypto
|
|||
, commitments(commitments)
|
||||
{}
|
||||
const bpp_signature& sig;
|
||||
const std::vector<point_t>& commitments;
|
||||
const std::vector<point_t>& commitments; // assumed to be premultiplied by 1/8
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -343,7 +370,7 @@ namespace crypto
|
|||
bool bpp_verify(const std::vector<bpp_sig_commit_ref_t>& sigs, uint8_t* p_err = nullptr)
|
||||
{
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("bpp_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \
|
||||
if (!(cond)) { LOG_PRINT_RED("bpp_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
DBG_PRINT(ENDL << " . . . . bpp_verify() . . . . ");
|
||||
|
|
@ -689,11 +716,14 @@ namespace crypto
|
|||
|
||||
point_t GH_exponents = c_point_0;
|
||||
CT::calc_pedersen_commitment(G_scalar, H_scalar, GH_exponents);
|
||||
bool result = multiexp_and_check_being_zero<CT>(g_scalars, h_scalars, summand + GH_exponents);
|
||||
bool result = msm_and_check_zero<CT>(g_scalars, h_scalars, summand + GH_exponents);
|
||||
if (result)
|
||||
DBG_PRINT(ENDL << " . . . . bpp_verify() -- SUCCEEDED!!!" << ENDL);
|
||||
return result;
|
||||
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
|
||||
}
|
||||
|
||||
#undef DBG_VAL_PRINT
|
||||
#undef DBG_PRINT
|
||||
|
||||
} // namespace crypto
|
||||
|
|
|
|||
|
|
@ -24,18 +24,25 @@ namespace crypto
|
|||
scalar_t delta_2;
|
||||
};
|
||||
|
||||
#define DBG_VAL_PRINT(x) std::cout << #x ": " << x << ENDL
|
||||
#define DBG_PRINT(x) std::cout << x << ENDL
|
||||
#if 0
|
||||
# define DBG_VAL_PRINT(x) std::cout << std::setw(30) << std::left << #x ": " << x << std::endl
|
||||
# define DBG_PRINT(x) std::cout << x << std::endl
|
||||
#else
|
||||
# define DBG_VAL_PRINT(x) (void(0))
|
||||
# define DBG_PRINT(x) (void(0))
|
||||
#endif
|
||||
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("bppe_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
|
||||
template<typename CT>
|
||||
bool bppe_gen(const scalar_vec_t& values, const scalar_vec_t& masks, const scalar_vec_t& masks2, bppe_signature& sig, std::vector<point_t>& commitments, uint8_t* p_err = nullptr)
|
||||
bool bppe_gen(const scalar_vec_t& values, const scalar_vec_t& masks, const scalar_vec_t& masks2, const std::vector<const crypto::public_key*>& commitments_1div8, bppe_signature& sig, uint8_t* p_err = nullptr)
|
||||
{
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("bppe_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
// Note: commitments_1div8 are supposed to be already calculated
|
||||
static_assert(CT::c_bpp_n <= 255, "too big N");
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() > 0 && values.size() <= CT::c_bpp_values_max && values.size() == masks.size() && masks.size() == masks2.size(), 1);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() > 0 && values.size() <= CT::c_bpp_values_max && values.size() == masks.size() && masks.size() == masks2.size() && values.size() == commitments_1div8.size(), 1);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(masks.is_reduced() && masks2.is_reduced(), 3);
|
||||
|
||||
const size_t c_bpp_log2_m = constexpr_ceil_log2(values.size());
|
||||
|
|
@ -43,14 +50,14 @@ namespace crypto
|
|||
const size_t c_bpp_mn = c_bpp_m * CT::c_bpp_n;
|
||||
const size_t c_bpp_log2_mn = c_bpp_log2_m + CT::c_bpp_log2_n;
|
||||
|
||||
// pre-multiply all output points by c_scalar_1div8
|
||||
// in order to enforce these points to be in the prime-order subgroup (after mul by 8 in bpp_verify())
|
||||
|
||||
// calc commitments vector as commitments[i] = 1/8 * values[i] * G + 1/8 * masks[i] * H + 1/8 * masks2[i] * H2
|
||||
commitments.resize(values.size());
|
||||
for (size_t i = 0; i < values.size(); ++i)
|
||||
CT::calc_pedersen_commitment_2(values[i] * c_scalar_1div8, masks[i] * c_scalar_1div8, masks2[i] * c_scalar_1div8, commitments[i]);
|
||||
|
||||
#ifndef NDEBUG
|
||||
for(size_t i = 0; i < values.size(); ++i)
|
||||
{
|
||||
point_t V{};
|
||||
CT::calc_pedersen_commitment_2(values[i], masks[i], masks2[i], V);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(point_t(*commitments_1div8[i]).modify_mul8() == V, 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
// s.a. BP+ paper, page 15, eq. 11
|
||||
// decompose v into aL and aR:
|
||||
|
|
@ -86,7 +93,7 @@ namespace crypto
|
|||
DBG_PRINT("initial transcript: " << e);
|
||||
|
||||
hash_helper_t::hs_t hsc;
|
||||
CT::update_transcript(hsc, e, commitments);
|
||||
CT::update_transcript(hsc, e, commitments_1div8);
|
||||
|
||||
// Zarcanum paper, page 33, Fig. D.3: The prover chooses alpha_1, alpha_2 and computes A = g^aL h^aR h_1^alpha_1 h_2^alpha_2
|
||||
// so we calculate A0 = alpha_1 * H + alpha_2 * H_2 + SUM(aL_i * G_i) + SUM(aR_i * H_i)
|
||||
|
|
@ -149,7 +156,7 @@ namespace crypto
|
|||
|
||||
// aL_hat = aL - 1*z
|
||||
scalar_vec_t aLs_hat = aLs - z;
|
||||
// aL_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3)
|
||||
// aR_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3)
|
||||
scalar_vec_t aRs_hat = aRs + z;
|
||||
for (size_t i = 0; i < c_bpp_mn; ++i)
|
||||
aRs_hat[i] += d[i] * y_powers[c_bpp_mn - i];
|
||||
|
|
@ -336,10 +343,28 @@ namespace crypto
|
|||
DBG_VAL_PRINT(sig.delta_2);
|
||||
|
||||
return true;
|
||||
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
|
||||
} // bppe_gen()
|
||||
|
||||
|
||||
// convenient overload for tests
|
||||
template<typename CT>
|
||||
bool bppe_gen(const scalar_vec_t& values, const scalar_vec_t& masks, const scalar_vec_t& masks2, bppe_signature& sig, std::vector<point_t>& commitments_1div8_to_be_generated, uint8_t* p_err = nullptr)
|
||||
{
|
||||
// calc commitments vector as commitments[i] = 1/8 * values[i] * G + 1/8 * masks[i] * H + 1/8 * masks2[i] * H2
|
||||
commitments_1div8_to_be_generated.resize(values.size());
|
||||
std::vector<crypto::public_key> commitments_1div8(values.size());
|
||||
std::vector<const crypto::public_key*> commitments_1div8_pointers(values.size());
|
||||
for (size_t i = 0; i < values.size(); ++i)
|
||||
{
|
||||
CT::calc_pedersen_commitment_2(values[i] * c_scalar_1div8, masks[i] * c_scalar_1div8, masks2[i] * c_scalar_1div8, commitments_1div8_to_be_generated[i]);
|
||||
commitments_1div8[i] = (commitments_1div8_to_be_generated[i]).to_public_key();
|
||||
commitments_1div8_pointers[i] = &commitments_1div8[i];
|
||||
}
|
||||
return bppe_gen<CT>(values, masks, masks2, commitments_1div8_pointers, sig, p_err);
|
||||
}
|
||||
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
|
||||
|
||||
|
||||
struct bppe_sig_commit_ref_t
|
||||
{
|
||||
bppe_sig_commit_ref_t(const bppe_signature& sig, const std::vector<point_t>& commitments)
|
||||
|
|
@ -347,7 +372,7 @@ namespace crypto
|
|||
, commitments(commitments)
|
||||
{}
|
||||
const bppe_signature& sig;
|
||||
const std::vector<point_t>& commitments;
|
||||
const std::vector<point_t>& commitments; // assumed to be premultiplied by 1/8
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -355,7 +380,7 @@ namespace crypto
|
|||
bool bppe_verify(const std::vector<bppe_sig_commit_ref_t>& sigs, uint8_t* p_err = nullptr)
|
||||
{
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("bppe_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \
|
||||
if (!(cond)) { LOG_PRINT_RED("bppe_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
DBG_PRINT(ENDL << " . . . . bppe_verify() . . . . ");
|
||||
|
|
@ -709,11 +734,14 @@ namespace crypto
|
|||
|
||||
point_t GH_exponents = c_point_0;
|
||||
CT::calc_pedersen_commitment_2(G_scalar, H_scalar, H2_scalar, GH_exponents);
|
||||
bool result = multiexp_and_check_being_zero<CT>(g_scalars, h_scalars, summand + GH_exponents);
|
||||
bool result = msm_and_check_zero<CT>(g_scalars, h_scalars, summand + GH_exponents);
|
||||
if (result)
|
||||
DBG_PRINT(ENDL << " . . . . bppe_verify() -- SUCCEEDED!!!" << ENDL);
|
||||
return result;
|
||||
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
|
||||
}
|
||||
|
||||
#undef DBG_VAL_PRINT
|
||||
#undef DBG_PRINT
|
||||
|
||||
} // namespace crypto
|
||||
|
|
|
|||
|
|
@ -6,4 +6,12 @@
|
|||
|
||||
namespace crypto
|
||||
{
|
||||
// TODO @#@# redesign needed, consider changing to inline constexpr
|
||||
const point_t& bpp_ct_generators_HGX::bpp_G = c_point_H;
|
||||
const point_t& bpp_ct_generators_HGX::bpp_H = c_point_G;
|
||||
const point_t& bpp_ct_generators_HGX::bpp_H2 = c_point_X;
|
||||
|
||||
const point_t& bpp_ct_generators_UGX::bpp_G = c_point_U;
|
||||
const point_t& bpp_ct_generators_UGX::bpp_H = c_point_G;
|
||||
const point_t& bpp_ct_generators_UGX::bpp_H2 = c_point_X;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2021-2022 Zano Project (https://zano.org/)
|
||||
// Copyright (c) 2021-2022 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Copyright (c) 2021-2023 Zano Project (https://zano.org/)
|
||||
// Copyright (c) 2021-2023 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#pragma once
|
||||
|
|
@ -23,23 +23,6 @@ namespace crypto
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
// returns greatest k, s.t. 2**k <= v
|
||||
// tests in crypto_tests_range_proofs.h
|
||||
constexpr size_t constexpr_floor_log2(size_t v)
|
||||
{
|
||||
return v <= 1 ? 0 : constexpr_floor_log2(v >> 1) + 1;
|
||||
}
|
||||
|
||||
// returns smallest k, s.t. v <= 2**k
|
||||
// tests in crypto_tests_range_proofs.h
|
||||
constexpr size_t constexpr_ceil_log2(size_t v)
|
||||
{
|
||||
return v <= 1 ? 0 : constexpr_floor_log2(v - 1) + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// returns least significant bit uing de Bruijn sequence
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html
|
||||
inline uint8_t calc_lsb_32(uint32_t v)
|
||||
|
|
@ -56,8 +39,25 @@ namespace crypto
|
|||
////////////////////////////////////////
|
||||
// crypto trait for Zano
|
||||
////////////////////////////////////////
|
||||
template<size_t N = 64, size_t values_max = 16>
|
||||
struct bpp_crypto_trait_zano
|
||||
struct bpp_ct_generators_HGX
|
||||
{
|
||||
// NOTE! This notation follows the original BP+ whitepaper, see mapping to Zano's generators in range_proofs.cpp
|
||||
static const point_t& bpp_G;
|
||||
static const point_t& bpp_H;
|
||||
static const point_t& bpp_H2;
|
||||
};
|
||||
|
||||
struct bpp_ct_generators_UGX
|
||||
{
|
||||
// NOTE! This notation follows the original BP+ whitepaper, see mapping to Zano's generators in range_proofs.cpp
|
||||
static const point_t& bpp_G;
|
||||
static const point_t& bpp_H;
|
||||
static const point_t& bpp_H2;
|
||||
};
|
||||
|
||||
|
||||
template<typename gen_trait_t, size_t N = 64, size_t values_max = 32>
|
||||
struct bpp_crypto_trait_zano : gen_trait_t
|
||||
{
|
||||
static constexpr size_t c_bpp_n = N; // the upper bound for the witness's range
|
||||
static constexpr size_t c_bpp_values_max = values_max; // maximum number of elements in BP+ proof, i.e. max allowed BP+ outputs
|
||||
|
|
@ -66,12 +66,14 @@ namespace crypto
|
|||
|
||||
static void calc_pedersen_commitment(const scalar_t& value, const scalar_t& mask, point_t& commitment)
|
||||
{
|
||||
commitment = value * c_point_G + mask * c_point_H;
|
||||
// commitment = value * bpp_G + mask * bpp_H
|
||||
commitment = operator*(value, bpp_G) + mask * bpp_H;
|
||||
}
|
||||
|
||||
static void calc_pedersen_commitment_2(const scalar_t& value, const scalar_t& mask1, const scalar_t& mask2, point_t& commitment)
|
||||
{
|
||||
commitment = value * c_point_G + mask1 * c_point_H + mask2 * c_point_H2;
|
||||
// commitment = value * bpp_G + mask1 * bpp_H * mask2 * bpp_H2
|
||||
commitment = operator*(value, bpp_G) + mask1 * bpp_H + mask2 * bpp_H2;
|
||||
}
|
||||
|
||||
static const scalar_t& get_initial_transcript()
|
||||
|
|
@ -88,7 +90,17 @@ namespace crypto
|
|||
e = hsc.calc_hash();
|
||||
}
|
||||
|
||||
// assumes hsc is cleared
|
||||
static void update_transcript(hash_helper_t::hs_t& hsc, scalar_t& e, const std::vector<const public_key*>& pub_keys)
|
||||
{
|
||||
hsc.add_scalar(e);
|
||||
for(auto p : pub_keys)
|
||||
hsc.add_pub_key(*p);
|
||||
e = hsc.calc_hash();
|
||||
}
|
||||
|
||||
// TODO: refactor with proper OOB handling
|
||||
// TODO: @#@# add domain separation
|
||||
static const point_t& get_generator(bool select_H, size_t index)
|
||||
{
|
||||
if (index >= c_bpp_mn_max)
|
||||
|
|
@ -116,42 +128,21 @@ namespace crypto
|
|||
return result;
|
||||
}
|
||||
|
||||
static const point_t& bpp_H;
|
||||
static const point_t& bpp_H2;
|
||||
using gen_trait_t::bpp_G;
|
||||
using gen_trait_t::bpp_H;
|
||||
using gen_trait_t::bpp_H2;
|
||||
}; // struct bpp_crypto_trait_zano
|
||||
|
||||
template<size_t N, size_t values_max>
|
||||
const point_t& bpp_crypto_trait_zano<N, values_max>::bpp_H = c_point_H;
|
||||
|
||||
template<size_t N, size_t values_max>
|
||||
const point_t& bpp_crypto_trait_zano<N, values_max>::bpp_H2 = c_point_H2;
|
||||
typedef bpp_crypto_trait_zano<bpp_ct_generators_UGX, 64, 32> bpp_crypto_trait_ZC_out;
|
||||
|
||||
|
||||
// efficient multiexponentiation (naive stub implementation atm, TODO)
|
||||
template<typename CT>
|
||||
bool multiexp_and_check_being_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(g_scalars.size() < CT::c_bpp_mn_max, false, "g_scalars oversized");
|
||||
CHECK_AND_ASSERT_MES(h_scalars.size() < CT::c_bpp_mn_max, false, "h_scalars oversized");
|
||||
|
||||
point_t result = summand;
|
||||
|
||||
for (size_t i = 0; i < g_scalars.size(); ++i)
|
||||
result += g_scalars[i] * CT::get_generator(false, i);
|
||||
|
||||
for (size_t i = 0; i < h_scalars.size(); ++i)
|
||||
result += h_scalars[i] * CT::get_generator(true, i);
|
||||
|
||||
if (!result.is_zero())
|
||||
{
|
||||
LOG_PRINT_L0("multiexp result is non zero: " << result);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
typedef bpp_crypto_trait_zano<bpp_ct_generators_HGX, 128, 16> bpp_crypto_trait_Zarcanum;
|
||||
|
||||
|
||||
} // namespace crypto
|
||||
|
||||
#include "epee/include/profile_tools.h" // <- remove this, sowle
|
||||
|
||||
#include "msm.h"
|
||||
#include "range_proof_bpp.h"
|
||||
#include "range_proof_bppe.h"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "hash-ops.h"
|
||||
|
||||
#ifdef _M_ARM64
|
||||
#include "malloc.h"
|
||||
#endif
|
||||
void tree_hash(const char (*hashes)[HASH_SIZE], size_t count, char *root_hash) {
|
||||
assert(count > 0);
|
||||
if (count == 1) {
|
||||
|
|
|
|||
425
src/crypto/zarcanum.cpp
Normal file
425
src/crypto/zarcanum.cpp
Normal file
|
|
@ -0,0 +1,425 @@
|
|||
// Copyright (c) 2022-2023 Zano Project
|
||||
// Copyright (c) 2022-2023 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
// Note: This file originates from tests/functional_tests/crypto_tests.cpp
|
||||
#include "epee/include/misc_log_ex.h"
|
||||
#include "zarcanum.h"
|
||||
#include "range_proofs.h"
|
||||
#include "../currency_core/crypto_config.h" // TODO: move it to the crypto
|
||||
#include "../common/crypto_stream_operators.h" // TODO: move it to the crypto
|
||||
|
||||
#if 0
|
||||
# define DBG_VAL_PRINT(x) std::cout << std::setw(30) << std::left << #x ": " << x << std::endl
|
||||
# define DBG_PRINT(x) std::cout << x << std::endl
|
||||
#else
|
||||
# define DBG_VAL_PRINT(x) (void(0))
|
||||
# define DBG_PRINT(x) (void(0))
|
||||
#endif
|
||||
|
||||
namespace crypto
|
||||
{
|
||||
const scalar_t c_zarcanum_z_coeff_s = { 0, 1, 0, 0 }; // c_scalar_2p64
|
||||
const mp::uint256_t c_zarcanum_z_coeff_mp = c_zarcanum_z_coeff_s.as_boost_mp_type<mp::uint256_t>();
|
||||
|
||||
template<typename T>
|
||||
inline std::ostream &operator <<(std::ostream &o, const std::vector<T> &v)
|
||||
{
|
||||
for(size_t i = 0, n = v.size(); i < n; ++i)
|
||||
o << ENDL << " [" << std::setw(2) << i << "]: " << v[i];
|
||||
return o;
|
||||
}
|
||||
|
||||
mp::uint256_t zarcanum_precalculate_l_div_z_D(const mp::uint128_t& pos_difficulty)
|
||||
{
|
||||
//LOG_PRINT_GREEN_L0(ENDL << "floor( l / (z * D) ) = " << c_scalar_L.as_boost_mp_type<mp::uint256_t>() / (c_zarcanum_z_coeff_mp * pos_difficulty));
|
||||
return c_scalar_L.as_boost_mp_type<mp::uint256_t>() / (c_zarcanum_z_coeff_mp * pos_difficulty); // == floor( l / (z * D) )
|
||||
}
|
||||
|
||||
mp::uint256_t zarcanum_precalculate_z_l_div_z_D(const mp::uint128_t& pos_difficulty)
|
||||
{
|
||||
//LOG_PRINT_GREEN_L0(ENDL << "z * floor( l / (z * D) ) = " << c_zarcanum_z_coeff_mp * (c_scalar_L.as_boost_mp_type<mp::uint256_t>() / (c_zarcanum_z_coeff_mp * pos_difficulty)));
|
||||
return c_zarcanum_z_coeff_mp * (c_scalar_L.as_boost_mp_type<mp::uint256_t>() / (c_zarcanum_z_coeff_mp * pos_difficulty)); // == z * floor( l / (z * D) )
|
||||
}
|
||||
|
||||
bool zarcanum_check_main_pos_inequality(const hash& kernel_hash, const scalar_t& blinding_mask, const scalar_t& secret_q,
|
||||
const scalar_t& last_pow_block_id_hashed, const mp::uint256_t& z_l_div_z_D, uint64_t stake_amount, mp::uint256_t& lhs, mp::uint512_t& rhs)
|
||||
{
|
||||
scalar_t lhs_s = scalar_t(kernel_hash) * (blinding_mask + secret_q + last_pow_block_id_hashed); // == h * (f + q + f') mod l
|
||||
lhs = lhs_s.as_boost_mp_type<mp::uint256_t>();
|
||||
rhs = static_cast<mp::uint512_t>(z_l_div_z_D) * stake_amount; // == floor( l / (z * D) ) * z * a
|
||||
|
||||
//LOG_PRINT_GREEN_L0(ENDL <<
|
||||
// "z_l_div_z_D = " << z_l_div_z_D << ENDL <<
|
||||
// "stake_amount = " << stake_amount << ENDL <<
|
||||
// "lhs = " << lhs << ENDL <<
|
||||
// "rhs = " << rhs);
|
||||
|
||||
return lhs < rhs; // h * (f + q + f') mod l < floor( l / (z * D) ) * z * a
|
||||
}
|
||||
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("zarcanum_generate_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
bool zarcanum_generate_proof(const hash& m, const hash& kernel_hash, const std::vector<CLSAG_GGXXG_input_ref_t>& ring,
|
||||
const scalar_t& last_pow_block_id_hashed, const key_image& stake_ki,
|
||||
const scalar_t& secret_x, const scalar_t& secret_q, uint64_t secret_index, uint64_t stake_amount,
|
||||
const scalar_t& stake_out_asset_id_blinding_mask, const scalar_t& stake_out_amount_blinding_mask, const scalar_t& pseudo_out_amount_blinding_mask,
|
||||
zarcanum_proof& result, uint8_t* p_err /* = nullptr */)
|
||||
{
|
||||
DBG_PRINT("zarcanum_generate_proof");
|
||||
const scalar_t a = stake_amount;
|
||||
const scalar_t h = scalar_t(kernel_hash);
|
||||
const scalar_t f_plus_q = stake_out_amount_blinding_mask + secret_q;
|
||||
const scalar_t f_plus_q_plus_fp = f_plus_q + last_pow_block_id_hashed;
|
||||
const scalar_t lhs = h * f_plus_q_plus_fp; // == h * (f + q + f') mod l
|
||||
const mp::uint256_t d_mp = lhs.as_boost_mp_type<mp::uint256_t>() / (c_zarcanum_z_coeff_mp * stake_amount) + 1;
|
||||
result.d = scalar_t(d_mp);
|
||||
|
||||
const scalar_t dz = result.d * c_zarcanum_z_coeff_s;
|
||||
|
||||
const scalar_t ba = dz * a - lhs; // b_a = dza - h(f + q + f')
|
||||
|
||||
const scalar_t bf = dz * f_plus_q - h * a; // b_f = dz(f + q) - ha
|
||||
|
||||
const scalar_t x0 = scalar_t::random(), x1 = scalar_t::random(), x2 = scalar_t::random();
|
||||
|
||||
const scalar_t bx = x2 - h * x1 + dz * x0; // b_x = x'' - hx' + dzx
|
||||
|
||||
point_t C = x0 * c_point_X + a * c_point_H + f_plus_q * c_point_G;
|
||||
point_t C_prime = x1 * c_point_X + f_plus_q * c_point_H + a * c_point_G;
|
||||
point_t E = bx * c_point_X + ba * c_point_H + bf * c_point_G;
|
||||
|
||||
result.C = (c_scalar_1div8 * C).to_public_key();
|
||||
result.C_prime = (c_scalar_1div8 * C_prime).to_public_key();
|
||||
result.E = (c_scalar_1div8 * E).to_public_key();
|
||||
|
||||
// three proofs with a shared Fiat-Shamir challenge c
|
||||
// 1) linear composition proof for the fact, that C + C' = lin(X, H + G) = (x + x') X + (a + f + q) (H + G)
|
||||
// 2) linear composition proof for the fact, that C - C' = lin(X, H - G) = (x - x') X + (a - f - q) (H - G)
|
||||
// 3) Schnorr proof for the fact, that hC' - dzC + E + f'hH = lin(X) = x'' X
|
||||
|
||||
point_t F = h * C_prime - dz * C + E + last_pow_block_id_hashed * h * c_point_H;
|
||||
|
||||
DBG_VAL_PRINT(h); DBG_VAL_PRINT(last_pow_block_id_hashed); DBG_VAL_PRINT(dz);
|
||||
DBG_VAL_PRINT(C); DBG_VAL_PRINT(C_prime); DBG_VAL_PRINT(E); DBG_VAL_PRINT(F);
|
||||
|
||||
scalar_t r0 = scalar_t::random();
|
||||
scalar_t r1 = scalar_t::random();
|
||||
scalar_t r2 = scalar_t::random();
|
||||
scalar_t r3 = scalar_t::random();
|
||||
scalar_t r4 = scalar_t::random();
|
||||
|
||||
point_t R_01 = r0 * c_point_X + r1 * c_point_H_plus_G;
|
||||
point_t R_23 = r2 * c_point_X + r3 * c_point_H_minus_G;
|
||||
point_t R_4 = r4 * c_point_X;
|
||||
|
||||
hash_helper_t::hs_t hash_calc(7);
|
||||
hash_calc.add_32_chars(CRYPTO_HDS_ZARCANUM_PROOF_HASH);
|
||||
hash_calc.add_point(R_01);
|
||||
hash_calc.add_point(R_23);
|
||||
hash_calc.add_point(R_4);
|
||||
hash_calc.add_point(C + C_prime);
|
||||
hash_calc.add_point(C - C_prime);
|
||||
hash_calc.add_point(F);
|
||||
result.c = hash_calc.calc_hash();
|
||||
|
||||
result.y0 = r0 + result.c * (x0 + x1); // y_0 = r_0 + c (x + x')
|
||||
result.y1 = r1 + result.c * (a + f_plus_q); // y_1 = r_1 + c (a + f + q)
|
||||
result.y2 = r2 + result.c * (x0 - x1); // y_2 = r_2 + c (x - x')
|
||||
result.y3 = r3 + result.c * (a - f_plus_q); // y_3 = r_3 + c (a - f - q)
|
||||
result.y4 = r4 + result.c * x2; // y_4 = r_4 + c x''
|
||||
|
||||
// range proof for E
|
||||
const scalar_vec_t values = { ba }; // H component
|
||||
const scalar_vec_t masks = { bf }; // G component
|
||||
const scalar_vec_t masks2 = { bx }; // X component
|
||||
const std::vector<const public_key*> E_1div8_vec_ptr = { &result.E };
|
||||
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(bppe_gen<bpp_crypto_trait_Zarcanum>(values, masks, masks2, E_1div8_vec_ptr, result.E_range_proof), 10);
|
||||
|
||||
// = five-layers ring signature data outline =
|
||||
// (j in [0, ring_size-1])
|
||||
// layer 0 ring
|
||||
// A[j] ( = ring[j].stealth_address)
|
||||
// layer 0 secret (with respect to G)
|
||||
// secret_x
|
||||
// layer 0 linkability
|
||||
// stake_ki
|
||||
//
|
||||
// layer 1 ring
|
||||
// ring[j].amount_commitment - pseudo_out_amount_commitment
|
||||
// layer 1 secret (with respect to G)
|
||||
// stake_out_amount_blinding_mask - pseudo_out_amount_blinding_mask ( = f_i - f'_i )
|
||||
//
|
||||
// additional layer for confidential assets:
|
||||
//
|
||||
// layer 2 ring
|
||||
// ring[j].blinded_asset_id - pseudo_out_blinded_asset_id
|
||||
// layer 2 secret (with respect to X)
|
||||
// -pseudo_out_asset_id_blinding_mask ( = -r'_i )
|
||||
//
|
||||
// additional layers for Zarcanum:
|
||||
//
|
||||
// layer 3 ring
|
||||
// C - A[j] - Q[j]
|
||||
// layer 3 secret (with respect to X)
|
||||
// x0 - a * stake_out_asset_id_blinding_mask ( = x - a * r_i )
|
||||
//
|
||||
// layer 4 ring
|
||||
// Q[j]
|
||||
// layer 4 secret (with respect to G)
|
||||
// secret_q
|
||||
|
||||
// such pseudo_out_asset_id_blinding_mask effectively makes pseudo_out_blinded_asset_id == currency::native_coin_asset_id_pt == point_H
|
||||
scalar_t pseudo_out_asset_id_blinding_mask = -stake_out_asset_id_blinding_mask; // T^p_i = T_i + (-r_i) * X = H
|
||||
|
||||
point_t stake_out_asset_id = c_point_H + stake_out_asset_id_blinding_mask * c_point_X; // T_i = H + r_i * X
|
||||
|
||||
point_t pseudo_out_amount_commitment = a * stake_out_asset_id + pseudo_out_amount_blinding_mask * c_point_G; // A^p_i = a_i * T_i + f'_i * G
|
||||
result.pseudo_out_amount_commitment = (c_scalar_1div8 * pseudo_out_amount_commitment).to_public_key();
|
||||
|
||||
TRY_ENTRY()
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(generate_CLSAG_GGXXG(m, ring, pseudo_out_amount_commitment, c_point_H, C, stake_ki,
|
||||
secret_x, stake_out_amount_blinding_mask - pseudo_out_amount_blinding_mask, -pseudo_out_asset_id_blinding_mask, x0 - a * stake_out_asset_id_blinding_mask, secret_q, secret_index,
|
||||
result.clsag_ggxxg), 20);
|
||||
CATCH_ENTRY2(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
|
||||
|
||||
|
||||
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("zarcanum_verify_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
bool zarcanum_verify_proof(const hash& m, const hash& kernel_hash, const std::vector<CLSAG_GGXXG_input_ref_t>& ring,
|
||||
const scalar_t& last_pow_block_id_hashed, const key_image& stake_ki,
|
||||
const mp::uint128_t& pos_difficulty,
|
||||
const zarcanum_proof& sig, uint8_t* p_err /* = nullptr */) noexcept
|
||||
{
|
||||
TRY_ENTRY()
|
||||
{
|
||||
DBG_PRINT("zarcanum_verify_proof");
|
||||
//bool r = false;
|
||||
|
||||
//std::cout << "===== zarcanum_verify_proof =====" << ENDL
|
||||
// << "m: " << m << ENDL
|
||||
// << "kernel_hash: " << kernel_hash << ENDL
|
||||
// << "last_pow_block_id_hashed: " << last_pow_block_id_hashed << ENDL
|
||||
// << "stake_ki: " << stake_ki << ENDL
|
||||
// << "pos_difficulty: " << pos_difficulty << ENDL;
|
||||
//size_t ii = 0;
|
||||
//for(const auto& el : ring)
|
||||
//{
|
||||
// std::cout << "[" << ii << "]" << ENDL
|
||||
// << " amount_commitment: " << el.amount_commitment << ENDL
|
||||
// << " blinded_asset_id: " << el.blinded_asset_id << ENDL
|
||||
// << " concealing_point: " << el.concealing_point << ENDL
|
||||
// << " stealth_address: " << el.stealth_address << ENDL;
|
||||
//}
|
||||
|
||||
// make sure 0 < d <= l / floor(z * D)
|
||||
const mp::uint256_t l_div_z_D_mp = zarcanum_precalculate_l_div_z_D(pos_difficulty);
|
||||
const scalar_t l_div_z_D(l_div_z_D_mp);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(!sig.d.is_zero() && sig.d < l_div_z_D, 2);
|
||||
const scalar_t dz = sig.d * c_zarcanum_z_coeff_s;
|
||||
|
||||
// calculate h
|
||||
const scalar_t h = scalar_t(kernel_hash);
|
||||
|
||||
// calculate F
|
||||
point_t C_prime = point_t(sig.C_prime);
|
||||
C_prime.modify_mul8();
|
||||
point_t C = point_t(sig.C);
|
||||
C.modify_mul8();
|
||||
point_t E = point_t(sig.E);
|
||||
E.modify_mul8();
|
||||
point_t F = h * C_prime - dz * C + E + last_pow_block_id_hashed * h * c_point_H;
|
||||
|
||||
DBG_VAL_PRINT(h); DBG_VAL_PRINT(last_pow_block_id_hashed); DBG_VAL_PRINT(dz);
|
||||
DBG_VAL_PRINT(C); DBG_VAL_PRINT(C_prime); DBG_VAL_PRINT(E); DBG_VAL_PRINT(F);
|
||||
|
||||
// check three proofs with a shared Fiat-Shamir challenge c
|
||||
point_t C_plus_C_prime = C + C_prime;
|
||||
point_t C_minus_C_prime = C - C_prime;
|
||||
hash_helper_t::hs_t hash_calc(7);
|
||||
hash_calc.add_32_chars(CRYPTO_HDS_ZARCANUM_PROOF_HASH);
|
||||
hash_calc.add_point(sig.y0 * c_point_X + sig.y1 * c_point_H_plus_G - sig.c * C_plus_C_prime); // y_0 * X + y1 (H + G) - c (C + C')
|
||||
hash_calc.add_point(sig.y2 * c_point_X + sig.y3 * c_point_H_minus_G - sig.c * C_minus_C_prime); // y_2 * X + y3 (H - G) - c (C - C')
|
||||
hash_calc.add_point(sig.y4 * c_point_X - sig.c * F); // y_4 * X - c * F
|
||||
hash_calc.add_point(C_plus_C_prime);
|
||||
hash_calc.add_point(C_minus_C_prime);
|
||||
hash_calc.add_point(F);
|
||||
scalar_t c_prime = hash_calc.calc_hash();
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.c == c_prime, 3);
|
||||
|
||||
// check extended range proof for E
|
||||
std::vector<point_t> E_for_range_proof = { point_t(sig.E) }; // consider changing to 8*sig.E to avoid additional conversion
|
||||
std::vector<bppe_sig_commit_ref_t> range_proofs = { bppe_sig_commit_ref_t(sig.E_range_proof, E_for_range_proof) };
|
||||
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(bppe_verify<bpp_crypto_trait_Zarcanum>(range_proofs), 10);
|
||||
|
||||
static public_key native_coin_asset_id = (c_scalar_1div8 * c_point_H).to_public_key(); // consider making it less ugly -- sowle
|
||||
|
||||
// check extended CLSAG-GGXG ring signature
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(verify_CLSAG_GGXXG(m, ring, sig.pseudo_out_amount_commitment, native_coin_asset_id, sig.C, stake_ki, sig.clsag_ggxxg), 1);
|
||||
}
|
||||
CATCH_ENTRY_CUSTOM2({if (p_err) *p_err = 100;}, false)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
|
||||
|
||||
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("generate_vector_UG_aggregation_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
bool generate_vector_UG_aggregation_proof(const hash& m, const scalar_vec_t& u_secrets, const scalar_vec_t& g_secrets0, const scalar_vec_t& g_secrets1,
|
||||
const std::vector<point_t>& amount_commitments,
|
||||
const std::vector<point_t>& amount_commitments_for_rp_aggregation,
|
||||
const std::vector<point_t>& blinded_asset_ids,
|
||||
vector_UG_aggregation_proof& result, uint8_t* p_err /* = nullptr */)
|
||||
{
|
||||
// w - public random weighting factor
|
||||
// proof of knowing e_j and y'' in zero knowledge in the following eq:
|
||||
// E_j + w * E'_j = e_j * (T'_j + w * U) + (y_j + w * y'_j) * G
|
||||
// where:
|
||||
// e_j -- output's amount
|
||||
// T'_j -- output's blinded asset tag
|
||||
// E_j == e_j * T'_j + y_j * G -- output's amount commitments
|
||||
// E'_j == e_j * U + y'_j * G -- additional commitment to the same amount for range proof aggregation
|
||||
|
||||
// amount_commitments[j] + w * amount_commitments_for_rp_aggregation[j]
|
||||
// ==
|
||||
// u_secrets[j] * (blinded_asset_ids[j] + w * U) + (g_secrets0[j] + w * g_secrets1[j]) * G
|
||||
|
||||
const size_t n = u_secrets.size();
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n != 0, 1);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == g_secrets0.size(), 2);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == g_secrets1.size(), 3);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == amount_commitments.size(), 4);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == amount_commitments_for_rp_aggregation.size(), 5);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == blinded_asset_ids.size(), 6);
|
||||
|
||||
hash_helper_t::hs_t hash_calculator(1 + 3 * n);
|
||||
hash_calculator.add_hash(m);
|
||||
hash_calculator.add_points_array(amount_commitments);
|
||||
hash_calculator.add_points_array(amount_commitments_for_rp_aggregation);
|
||||
scalar_t w = hash_calculator.calc_hash(false); // don't clean the buffer
|
||||
DBG_VAL_PRINT(w);
|
||||
|
||||
#ifndef NDEBUG
|
||||
for(size_t j = 0; j < n; ++j)
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(amount_commitments[j] + w * amount_commitments_for_rp_aggregation[j] == u_secrets[j] * (blinded_asset_ids[j] + w * c_point_U) + (g_secrets0[j] + w * g_secrets1[j]) * c_point_G, 20);
|
||||
#endif
|
||||
|
||||
result.amount_commitments_for_rp_aggregation.clear();
|
||||
result.y0s.clear();
|
||||
result.y1s.clear();
|
||||
|
||||
scalar_vec_t r0, r1;
|
||||
r0.resize_and_make_random(n);
|
||||
r1.resize_and_make_random(n);
|
||||
|
||||
std::vector<point_t> asset_tag_plus_U_vec(n);
|
||||
for(size_t j = 0; j < n; ++j)
|
||||
asset_tag_plus_U_vec[j] = blinded_asset_ids[j] + w * c_point_U;
|
||||
|
||||
std::vector<point_t> R(n);
|
||||
for(size_t j = 0; j < n; ++j)
|
||||
R[j].assign_mul_plus_G(r0[j], asset_tag_plus_U_vec[j], r1[j]); // R[j] = r0[j] * asset_tag_plus_U_vec[j] + r1[j] * G
|
||||
|
||||
hash_calculator.add_points_array(R);
|
||||
result.c = hash_calculator.calc_hash();
|
||||
|
||||
DBG_VAL_PRINT(asset_tag_plus_U_vec); DBG_VAL_PRINT(m); DBG_VAL_PRINT(amount_commitments); DBG_VAL_PRINT(amount_commitments_for_rp_aggregation); DBG_VAL_PRINT(R);
|
||||
DBG_VAL_PRINT(result.c);
|
||||
|
||||
for(size_t j = 0; j < n; ++j)
|
||||
{
|
||||
result.y0s.emplace_back(r0[j] - result.c * u_secrets[j]);
|
||||
result.y1s.emplace_back(r1[j] - result.c * (g_secrets0[j] + w * g_secrets1[j]));
|
||||
result.amount_commitments_for_rp_aggregation.emplace_back((c_scalar_1div8 * amount_commitments_for_rp_aggregation[j]).to_public_key());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
|
||||
|
||||
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("verify_vector_UG_aggregation_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
bool verify_vector_UG_aggregation_proof(const hash& m, const std::vector<const public_key*> amount_commitments_1div8, const std::vector<const public_key*> blinded_asset_ids_1div8,
|
||||
const vector_UG_aggregation_proof& sig, uint8_t* p_err /* = nullptr */) noexcept
|
||||
{
|
||||
TRY_ENTRY()
|
||||
{
|
||||
const size_t n = amount_commitments_1div8.size();
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n > 0, 1);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(blinded_asset_ids_1div8.size() == n, 2);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.amount_commitments_for_rp_aggregation.size() == n, 3);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.y0s.size() == n, 4);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.y1s.size() == n, 5);
|
||||
|
||||
hash_helper_t::hs_t hash_calculator(1 + 3 * n);
|
||||
hash_calculator.add_hash(m);
|
||||
DBG_VAL_PRINT(m);
|
||||
|
||||
std::vector<point_t> amount_commitments_pt;
|
||||
for(size_t j = 0; j < n; ++j)
|
||||
{
|
||||
point_t A = point_t(*amount_commitments_1div8[j]).modify_mul8();
|
||||
hash_calculator.add_point(A);
|
||||
amount_commitments_pt.emplace_back(A);
|
||||
DBG_VAL_PRINT(A);
|
||||
}
|
||||
|
||||
std::vector<point_t> amount_commitments_for_rp_aggregation_pt;
|
||||
for(size_t j = 0; j < n; ++j)
|
||||
{
|
||||
point_t Arpa = point_t(sig.amount_commitments_for_rp_aggregation[j]).modify_mul8();
|
||||
hash_calculator.add_point(Arpa); // TODO @#@ performance: consider adding premultiplied by 1/8 points to the hash
|
||||
amount_commitments_for_rp_aggregation_pt.emplace_back(Arpa);
|
||||
DBG_VAL_PRINT(Arpa);
|
||||
}
|
||||
|
||||
scalar_t w = hash_calculator.calc_hash(false); // don't clear the buffer
|
||||
DBG_VAL_PRINT(w);
|
||||
|
||||
std::vector<point_t> asset_tag_plus_U_vec(n);
|
||||
for(size_t j = 0; j < n; ++j)
|
||||
asset_tag_plus_U_vec[j] = point_t(*blinded_asset_ids_1div8[j]).modify_mul8() + w * c_point_U;
|
||||
DBG_VAL_PRINT(asset_tag_plus_U_vec);
|
||||
|
||||
for(size_t j = 0; j < n; ++j)
|
||||
{
|
||||
hash_calculator.add_pub_key(point_t(
|
||||
sig.y0s[j] * asset_tag_plus_U_vec[j] +
|
||||
sig.y1s[j] * c_point_G +
|
||||
sig.c * (amount_commitments_pt[j] + w * amount_commitments_for_rp_aggregation_pt[j])
|
||||
).to_public_key());
|
||||
DBG_VAL_PRINT(hash_calculator.m_elements.back().pk);
|
||||
}
|
||||
|
||||
scalar_t c = hash_calculator.calc_hash();
|
||||
DBG_VAL_PRINT(c); DBG_VAL_PRINT(sig.c);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.c == c, 0);
|
||||
}
|
||||
CATCH_ENTRY_CUSTOM2({if (p_err) *p_err = 100; }, false)
|
||||
|
||||
return true;
|
||||
}
|
||||
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
|
||||
|
||||
|
||||
|
||||
} // namespace crypto
|
||||
295
src/crypto/zarcanum.h
Normal file
295
src/crypto/zarcanum.h
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
// Copyright (c) 2022-2024 Zano Project
|
||||
// Copyright (c) 2022-2024 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
// Note: This file originates from tests/functional_tests/crypto_tests.cpp
|
||||
#pragma once
|
||||
#include "crypto-sugar.h"
|
||||
#include "range_proofs.h"
|
||||
#include "clsag.h"
|
||||
|
||||
namespace crypto
|
||||
{
|
||||
extern const mp::uint256_t c_zarcanum_z_coeff_mp;
|
||||
extern const scalar_t c_zarcanum_z_coeff_s;
|
||||
|
||||
mp::uint256_t zarcanum_precalculate_l_div_z_D(const mp::uint128_t& pos_difficulty);
|
||||
mp::uint256_t zarcanum_precalculate_z_l_div_z_D(const mp::uint128_t& pos_difficulty);
|
||||
|
||||
bool zarcanum_check_main_pos_inequality(const hash& kernel_hash, const scalar_t& blinding_mask, const scalar_t& secret_q,
|
||||
const scalar_t& last_pow_block_id_hashed, const mp::uint256_t& z_l_div_z_D_, uint64_t stake_amount, mp::uint256_t& lhs, mp::uint512_t& rhs);
|
||||
|
||||
|
||||
struct zarcanum_proof
|
||||
{
|
||||
scalar_t d = 0;
|
||||
public_key C; // premultiplied by 1/8
|
||||
public_key C_prime; // premultiplied by 1/8
|
||||
public_key E; // premultiplied by 1/8
|
||||
|
||||
scalar_t c; // shared Fiat-Shamir challenge for the following three proofs
|
||||
scalar_t y0; // 1st linear composition proof
|
||||
scalar_t y1; // ( C + C' = lin(X, H + G) )
|
||||
scalar_t y2; // 2nd linear composition proof
|
||||
scalar_t y3; // ( C - C' = lin(X, H - G) )
|
||||
scalar_t y4; // Schnorr proof (F = lin(X))
|
||||
|
||||
bppe_signature E_range_proof;
|
||||
|
||||
public_key pseudo_out_amount_commitment; // premultiplied by 1/8
|
||||
CLSAG_GGXXG_signature clsag_ggxxg;
|
||||
};
|
||||
|
||||
bool zarcanum_generate_proof(const hash& m, const hash& kernel_hash, const std::vector<CLSAG_GGXXG_input_ref_t>& ring,
|
||||
const scalar_t& last_pow_block_id_hashed, const key_image& stake_ki,
|
||||
const scalar_t& secret_x, const scalar_t& secret_q, uint64_t secret_index, uint64_t stake_amount,
|
||||
const scalar_t& stake_out_asset_id_blinding_mask, const scalar_t& stake_out_amount_blinding_mask, const scalar_t& pseudo_out_amount_blinding_mask,
|
||||
zarcanum_proof& result, uint8_t* p_err = nullptr);
|
||||
|
||||
|
||||
bool zarcanum_verify_proof(const hash& m, const hash& kernel_hash, const std::vector<CLSAG_GGXXG_input_ref_t>& ring,
|
||||
const scalar_t& last_pow_block_id_hashed, const key_image& stake_ki,
|
||||
const mp::uint128_t& pos_difficulty,
|
||||
const zarcanum_proof& sig, uint8_t* p_err = nullptr) noexcept;
|
||||
|
||||
|
||||
// TODO @#@#: make sure it is used, implement, then move it to an appropriate place
|
||||
struct linear_composition_proof
|
||||
{
|
||||
scalar_t c;
|
||||
scalar_t y0;
|
||||
scalar_t y1;
|
||||
};
|
||||
|
||||
enum generator_tag { gt_void = 0, gt_G = 1, gt_H = 2, gt_H2 = 3, gt_X = 4, gt_U = 5 };
|
||||
|
||||
template<generator_tag gen0 = gt_H, generator_tag gen1 = gt_G>
|
||||
bool generate_linear_composition_proof(const hash& m, const public_key& A, const scalar_t& secret_a, const scalar_t& secret_b, linear_composition_proof& result, uint8_t* p_err = nullptr)
|
||||
{
|
||||
// consider embedding generators' tags into random entropy to distinguish proofs made with different generators during verification
|
||||
return false;
|
||||
}
|
||||
|
||||
template<generator_tag gen0 = gt_H, generator_tag gen1 = gt_G>
|
||||
bool verify_linear_composition_proof(const hash& m, const public_key& A, const linear_composition_proof& sig, uint8_t* p_err = nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
struct generic_schnorr_sig
|
||||
{
|
||||
scalar_t c;
|
||||
scalar_t y;
|
||||
};
|
||||
|
||||
|
||||
template<typename generator_t>
|
||||
inline bool generate_schnorr_sig_custom_generator(const hash& m, const point_t& A, const scalar_t& secret_a, generic_schnorr_sig& result, const generator_t& g_point_g)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (A != secret_a * g_point_g)
|
||||
return false;
|
||||
#endif
|
||||
scalar_t r = scalar_t::random();
|
||||
point_t R = r * g_point_g;
|
||||
hash_helper_t::hs_t hsc(3);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_point(A);
|
||||
hsc.add_point(R);
|
||||
result.c = hsc.calc_hash();
|
||||
result.y.assign_mulsub(result.c, secret_a, r); // y = r - c * secret_a
|
||||
return true;
|
||||
}
|
||||
|
||||
template<generator_tag gen = gt_G>
|
||||
inline bool generate_schnorr_sig(const hash& m, const point_t& A, const scalar_t& secret_a, generic_schnorr_sig& result);
|
||||
|
||||
template<>
|
||||
inline bool generate_schnorr_sig<gt_G>(const hash& m, const point_t& A, const scalar_t& secret_a, generic_schnorr_sig& result)
|
||||
{
|
||||
return generate_schnorr_sig_custom_generator(m, A, secret_a, result, c_point_G);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool generate_schnorr_sig<gt_X>(const hash& m, const point_t& A, const scalar_t& secret_a, generic_schnorr_sig& result)
|
||||
{
|
||||
return generate_schnorr_sig_custom_generator(m, A, secret_a, result, c_point_X);
|
||||
}
|
||||
|
||||
inline bool generate_schnorr_sig(const hash& m, const public_key& A, const secret_key& secret_a, generic_schnorr_sig& result)
|
||||
{
|
||||
return generate_schnorr_sig(m, point_t(A), scalar_t(secret_a), result);
|
||||
}
|
||||
|
||||
|
||||
template<generator_tag gen = gt_G>
|
||||
inline bool verify_schnorr_sig(const hash& m, const public_key& A, const generic_schnorr_sig& sig) noexcept;
|
||||
|
||||
// TODO @#@# make optimized version inline bool verify_schnorr_sig(const hash& m, const point_t& A, const generic_schnorr_sig& sig) noexcept;
|
||||
// and change check_tx_balance() accordingly
|
||||
|
||||
template<>
|
||||
inline bool verify_schnorr_sig<gt_G>(const hash& m, const public_key& A, const generic_schnorr_sig& sig) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!sig.c.is_reduced() || !sig.y.is_reduced())
|
||||
return false;
|
||||
hash_helper_t::hs_t hsc(3);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_pub_key(A);
|
||||
hsc.add_point(point_t(A).mul_plus_G(sig.c, sig.y)); // sig.y * G + sig.c * A
|
||||
return sig.c == hsc.calc_hash();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool verify_schnorr_sig<gt_X>(const hash& m, const public_key& A, const generic_schnorr_sig& sig) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!sig.c.is_reduced() || !sig.y.is_reduced())
|
||||
return false;
|
||||
hash_helper_t::hs_t hsc(3);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_pub_key(A);
|
||||
hsc.add_point(sig.y * c_point_X + sig.c * point_t(A));
|
||||
return sig.c == hsc.calc_hash();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------
|
||||
|
||||
// multi-base Schnorr-like proof (two generators, two secrets, one Fiat-Shamir challenge)
|
||||
struct generic_double_schnorr_sig
|
||||
{
|
||||
scalar_t c;
|
||||
scalar_t y0;
|
||||
scalar_t y1;
|
||||
};
|
||||
|
||||
template<generator_tag gen0, generator_tag gen1>
|
||||
inline bool generate_double_schnorr_sig(const hash& m, const point_t& A, const scalar_t& secret_a, const point_t& B, const scalar_t& secret_b, generic_double_schnorr_sig& result);
|
||||
|
||||
template<>
|
||||
inline bool generate_double_schnorr_sig<gt_G, gt_G>(const hash& m, const point_t& A, const scalar_t& secret_a, const point_t& B, const scalar_t& secret_b, generic_double_schnorr_sig& result)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (A != secret_a * c_point_G || B != secret_b * c_point_G)
|
||||
return false;
|
||||
#endif
|
||||
scalar_t r0 = scalar_t::random();
|
||||
scalar_t r1 = scalar_t::random();
|
||||
point_t R0 = r0 * c_point_G;
|
||||
point_t R1 = r1 * c_point_G;
|
||||
hash_helper_t::hs_t hsc(5);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_point(A);
|
||||
hsc.add_point(B);
|
||||
hsc.add_point(R0);
|
||||
hsc.add_point(R1);
|
||||
result.c = hsc.calc_hash();
|
||||
result.y0.assign_mulsub(result.c, secret_a, r0); // y0 = r0 - c * secret_a
|
||||
result.y1.assign_mulsub(result.c, secret_b, r1); // y1 = r1 - c * secret_b
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool generate_double_schnorr_sig<gt_X, gt_G>(const hash& m, const point_t& A, const scalar_t& secret_a, const point_t& B, const scalar_t& secret_b, generic_double_schnorr_sig& result)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (A != secret_a * c_point_X || B != secret_b * c_point_G)
|
||||
return false;
|
||||
#endif
|
||||
scalar_t r0 = scalar_t::random();
|
||||
scalar_t r1 = scalar_t::random();
|
||||
point_t R0 = r0 * c_point_X;
|
||||
point_t R1 = r1 * c_point_G;
|
||||
hash_helper_t::hs_t hsc(5);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_point(A);
|
||||
hsc.add_point(B);
|
||||
hsc.add_point(R0);
|
||||
hsc.add_point(R1);
|
||||
result.c = hsc.calc_hash();
|
||||
result.y0.assign_mulsub(result.c, secret_a, r0); // y0 = r0 - c * secret_a
|
||||
result.y1.assign_mulsub(result.c, secret_b, r1); // y1 = r1 - c * secret_b
|
||||
return true;
|
||||
}
|
||||
|
||||
template<generator_tag gen0, generator_tag gen1>
|
||||
inline bool verify_double_schnorr_sig(const hash& m, const point_t& A, const public_key& B, const generic_double_schnorr_sig& sig) noexcept;
|
||||
|
||||
template<>
|
||||
inline bool verify_double_schnorr_sig<gt_G, gt_G>(const hash& m, const point_t& A, const public_key& B, const generic_double_schnorr_sig& sig) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!sig.c.is_reduced() || !sig.y0.is_reduced() || !sig.y1.is_reduced())
|
||||
return false;
|
||||
hash_helper_t::hs_t hsc(5);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_point(A);
|
||||
hsc.add_pub_key(B);
|
||||
hsc.add_point(A.mul_plus_G(sig.c, sig.y0)); // sig.y0 * G + sig.c * A
|
||||
hsc.add_point(point_t(B).mul_plus_G(sig.c, sig.y1)); // sig.y1 * G + sig.c * B
|
||||
return sig.c == hsc.calc_hash();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool verify_double_schnorr_sig<gt_X, gt_G>(const hash& m, const point_t& A, const public_key& B, const generic_double_schnorr_sig& sig) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!sig.c.is_reduced() || !sig.y0.is_reduced() || !sig.y1.is_reduced())
|
||||
return false;
|
||||
hash_helper_t::hs_t hsc(5);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_point(A);
|
||||
hsc.add_pub_key(B);
|
||||
hsc.add_point(sig.y0 * c_point_X + sig.c * A);
|
||||
hsc.add_point(point_t(B).mul_plus_G(sig.c, sig.y1)); // sig.y1 * G + sig.c * B
|
||||
return sig.c == hsc.calc_hash();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: improve this proof using random weightning factor
|
||||
struct vector_UG_aggregation_proof
|
||||
{
|
||||
std::vector<public_key> amount_commitments_for_rp_aggregation; // E' = e * U + y' * G, premultiplied by 1/8
|
||||
scalar_vec_t y0s;
|
||||
scalar_vec_t y1s;
|
||||
scalar_t c; // common challenge
|
||||
};
|
||||
|
||||
bool generate_vector_UG_aggregation_proof(const hash& m, const scalar_vec_t& u_secrets, const scalar_vec_t& g_secrets0, const scalar_vec_t& g_secrets1,
|
||||
const std::vector<point_t>& amount_commitments,
|
||||
const std::vector<point_t>& amount_commitments_for_rp_aggregation,
|
||||
const std::vector<point_t>& blinded_asset_ids,
|
||||
vector_UG_aggregation_proof& result, uint8_t* p_err = nullptr);
|
||||
|
||||
bool verify_vector_UG_aggregation_proof(const hash& m, const std::vector<const public_key*> amount_commitments_1div8, const std::vector<const public_key*> blinded_asset_ids_1div8,
|
||||
const vector_UG_aggregation_proof& sig, uint8_t* p_err = nullptr) noexcept;
|
||||
|
||||
|
||||
} // namespace crypto
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2018 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
@ -8,14 +8,54 @@
|
|||
|
||||
namespace bc_services
|
||||
{
|
||||
template<typename T>
|
||||
struct is_boost_variant : std::false_type {};
|
||||
|
||||
template<typename... Args>
|
||||
struct is_boost_variant<boost::variant<Args...>> : std::true_type {};
|
||||
|
||||
template<bool is_variant>
|
||||
struct type_selector;
|
||||
|
||||
template<>
|
||||
struct type_selector<true>
|
||||
{
|
||||
template<typename t_type>
|
||||
static const std::type_info& get_type(const t_type& t)
|
||||
{
|
||||
return t.type();
|
||||
}
|
||||
template<typename t_type, typename t_return_type>
|
||||
static const t_return_type& get(const t_type& t)
|
||||
{
|
||||
return boost::get<t_return_type>(t);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct type_selector<false>
|
||||
{
|
||||
template<typename t_type>
|
||||
static const std::type_info& get_type(const t_type& t)
|
||||
{
|
||||
return typeid(t);
|
||||
}
|
||||
template<typename t_type, typename t_return_type>
|
||||
static const t_return_type& get(const t_type& t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
};
|
||||
|
||||
template<class t_attachment_type_container_t>
|
||||
bool get_first_service_attachment_by_id(const t_attachment_type_container_t& tx_items, const std::string& id, const std::string& instruction, currency::tx_service_attachment& res)
|
||||
{
|
||||
for (const auto& item : tx_items)
|
||||
{
|
||||
if (item.type() == typeid(currency::tx_service_attachment))
|
||||
typedef type_selector<is_boost_variant<typename t_attachment_type_container_t::value_type>::value> TS;
|
||||
if (TS::get_type(item) == typeid(currency::tx_service_attachment))
|
||||
{
|
||||
const currency::tx_service_attachment& tsa = boost::get<currency::tx_service_attachment>(item);
|
||||
const currency::tx_service_attachment& tsa = TS::template get<decltype(item), currency::tx_service_attachment>(item);
|
||||
if (tsa.service_id == id && tsa.instruction == instruction)
|
||||
{
|
||||
res = tsa;
|
||||
|
|
@ -25,4 +65,5 @@ namespace bc_services
|
|||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
#include <boost/foreach.hpp>
|
||||
#include <boost/serialization/is_bitwise_serializable.hpp>
|
||||
#include "common/unordered_containers_boost_serialization.h"
|
||||
#include "common/crypto_boost_serialization.h"
|
||||
#include "common/crypto_serialization.h"
|
||||
#include "offers_service_basics.h"
|
||||
#include "offers_services_helpers.h"
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -39,7 +39,7 @@
|
|||
#include "dispatch_core_events.h"
|
||||
#include "bc_attachments_service_manager.h"
|
||||
#include "common/median_db_cache.h"
|
||||
|
||||
#include "common/variant_helper.h"
|
||||
|
||||
|
||||
MARK_AS_POD_C11(crypto::key_image);
|
||||
|
|
@ -68,10 +68,20 @@ namespace currency
|
|||
epee::math_helper::average<uint64_t, 5> etc_stuff_6;
|
||||
epee::math_helper::average<uint64_t, 5> insert_time_4;
|
||||
epee::math_helper::average<uint64_t, 5> raise_block_core_event;
|
||||
epee::math_helper::average<uint64_t, 5> validate_miner_transaction_time;
|
||||
epee::math_helper::average<uint64_t, 5> collect_rangeproofs_data_from_tx_time;
|
||||
epee::math_helper::average<uint64_t, 5> verify_multiple_zc_outs_range_proofs_time;
|
||||
|
||||
|
||||
//target_calculating_time_2
|
||||
epee::math_helper::average<uint64_t, 5> target_calculating_enum_blocks;
|
||||
epee::math_helper::average<uint64_t, 5> target_calculating_calc;
|
||||
|
||||
//longhash_calculating_time_3
|
||||
epee::math_helper::average<uint64_t, 1> pos_validate_ki_search;
|
||||
epee::math_helper::average<uint64_t, 1> pos_validate_get_out_keys_for_inputs;
|
||||
epee::math_helper::average<uint64_t, 1> pos_validate_zvp;
|
||||
|
||||
//tx processing zone
|
||||
epee::math_helper::average<uint64_t, 1> tx_check_inputs_time;
|
||||
epee::math_helper::average<uint64_t, 1> tx_add_one_tx_time;
|
||||
|
|
@ -139,6 +149,7 @@ namespace currency
|
|||
{
|
||||
bool htlc_is_expired;
|
||||
std::list<txout_htlc> htlc_outs;
|
||||
std::list<tx_out_zarcanum> zc_outs;
|
||||
};
|
||||
|
||||
// == Output indexes local lookup table conception ==
|
||||
|
|
@ -239,11 +250,11 @@ namespace currency
|
|||
|
||||
|
||||
template<class visitor_t>
|
||||
bool scan_outputkeys_for_indexes(const transaction &validated_tx, const txin_to_key& tx_in_to_key, visitor_t& vis)
|
||||
bool scan_outputkeys_for_indexes(const transaction &validated_tx, const txin_v& in_v, visitor_t& vis)
|
||||
{
|
||||
scan_for_keys_context cntx_stub = AUTO_VAL_INIT(cntx_stub);
|
||||
uint64_t stub = 0;
|
||||
return scan_outputkeys_for_indexes(validated_tx, tx_in_to_key, vis, stub, cntx_stub);
|
||||
return scan_outputkeys_for_indexes(validated_tx, in_v, vis, stub, cntx_stub);
|
||||
}
|
||||
template<class visitor_t>
|
||||
bool scan_outputkeys_for_indexes(const transaction &validated_tx, const txin_v& verified_input, visitor_t& vis, uint64_t& max_related_block_height, scan_for_keys_context& /*scan_context*/) const;
|
||||
|
|
@ -259,8 +270,8 @@ namespace currency
|
|||
wide_difficulty_type get_cached_next_difficulty(bool pos) const;
|
||||
|
||||
|
||||
bool create_block_template(block& b, const account_public_address& miner_address, const account_public_address& stakeholder_address, wide_difficulty_type& di, uint64_t& height, const blobdata& ex_nonce, bool pos, const pos_entry& pe, fill_block_template_func_t custom_fill_block_template_func = nullptr) const;
|
||||
bool create_block_template(block& b, const account_public_address& miner_address, wide_difficulty_type& di, uint64_t& height, const blobdata& ex_nonce) const;
|
||||
bool create_block_template(const account_public_address& miner_address, const blobdata& ex_nonce, block& b, wide_difficulty_type& di, uint64_t& height) const;
|
||||
bool create_block_template(const account_public_address& miner_address, const account_public_address& stakeholder_address, const blobdata& ex_nonce, bool pos, const pos_entry& pe, fill_block_template_func_t custom_fill_block_template_func, block& b, wide_difficulty_type& di, uint64_t& height, tx_generation_context* miner_tx_tgc_ptr = nullptr) const;
|
||||
bool create_block_template(const create_block_template_params& params, create_block_template_response& resp) const;
|
||||
|
||||
bool have_block(const crypto::hash& id) const;
|
||||
|
|
@ -275,10 +286,12 @@ namespace currency
|
|||
bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp)const;
|
||||
bool handle_get_objects(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res)const;
|
||||
bool get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res)const;
|
||||
bool get_random_outs_for_amounts2(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res)const;
|
||||
bool get_backward_blocks_sizes(size_t from_height, std::vector<size_t>& sz, size_t count)const;
|
||||
bool get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<uint64_t>& indexs)const;
|
||||
bool get_alias_info(const std::string& alias, extra_alias_entry_base& info)const;
|
||||
std::string get_alias_by_address(const account_public_address& addr)const;
|
||||
std::set<std::string> get_aliases_by_address(const account_public_address& addr)const;
|
||||
template<typename cb_t>
|
||||
bool enumerate_aliases(cb_t cb) const;
|
||||
template<typename cb_t>
|
||||
|
|
@ -286,25 +299,27 @@ namespace currency
|
|||
uint64_t get_aliases_count()const;
|
||||
uint64_t get_block_h_older_then(uint64_t timestamp) const;
|
||||
bool validate_tx_service_attachmens_in_services(const tx_service_attachment& a, size_t i, const transaction& tx)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height)const;
|
||||
bool get_asset_info(const crypto::public_key& asset_id, asset_descriptor_base& info)const;
|
||||
uint64_t get_assets_count() const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_zc_input& zc_in, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, bool& all_tx_ins_have_explicit_native_asset_ids) const;
|
||||
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height)const;
|
||||
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash) const;
|
||||
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height, crypto::hash& max_used_block_id)const;
|
||||
bool check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, const transaction& source_tx, size_t out_n) const;
|
||||
bool check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const transaction& source_tx, size_t out_n) const;
|
||||
bool validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id, uint64_t block_height) const;
|
||||
bool validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id) const;
|
||||
bool get_output_keys_for_input_with_checks(const transaction& tx, const txin_v& verified_input, std::vector<crypto::public_key>& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase, scan_for_keys_context& scan_context) const;
|
||||
bool get_output_keys_for_input_with_checks(const transaction& tx, const txin_v& verified_input, std::vector<crypto::public_key>& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const;
|
||||
bool check_input_signature(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, const std::vector<const crypto::public_key*>& output_keys_ptrs) const;
|
||||
bool check_input_signature(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<const crypto::public_key*>& output_keys_ptrs) const;
|
||||
bool check_input_signature(const transaction& tx,
|
||||
size_t in_index,
|
||||
uint64_t in_amount,
|
||||
const crypto::key_image& k_image,
|
||||
const std::vector<txin_etc_details_v>& in_etc_details,
|
||||
const crypto::hash& tx_prefix_hash,
|
||||
const std::vector<crypto::signature>& sig,
|
||||
const std::vector<const crypto::public_key*>& output_keys_ptrs) const;
|
||||
|
||||
uint64_t get_current_comulative_blocksize_limit()const;
|
||||
|
|
@ -315,6 +330,7 @@ namespace currency
|
|||
boost::multiprecision::uint128_t total_coins()const;
|
||||
bool is_pos_allowed()const;
|
||||
uint64_t get_tx_fee_median()const;
|
||||
uint64_t get_tx_fee_window_value_median() const;
|
||||
uint64_t get_tx_expiration_median() const;
|
||||
uint64_t validate_alias_reward(const transaction& tx, const std::string& ai)const;
|
||||
void set_event_handler(i_core_event_handler* event_handler) const;
|
||||
|
|
@ -328,6 +344,11 @@ namespace currency
|
|||
bool is_tx_expired(const transaction& tx) const;
|
||||
std::shared_ptr<const transaction_chain_entry> find_key_image_and_related_tx(const crypto::key_image& ki, crypto::hash& id_result) const;
|
||||
|
||||
// returns true as soon as the hardfork is active for the NEXT upcoming block (not for the top block in the blockchain storage)
|
||||
bool is_hardfork_active(size_t hardfork_id) const;
|
||||
bool fill_tx_rpc_inputs(tx_rpc_extended_info& tei, const transaction& tx) const;
|
||||
bool fill_tx_rpc_details(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce, const crypto::hash& h, uint64_t timestamp, bool is_short = false) const;
|
||||
|
||||
wide_difficulty_type block_difficulty(size_t i)const;
|
||||
bool forecast_difficulty(std::vector<std::pair<uint64_t, wide_difficulty_type>> &out_height_2_diff_vector, bool pos) const;
|
||||
bool prune_aged_alt_blocks();
|
||||
|
|
@ -335,14 +356,12 @@ namespace currency
|
|||
bool check_keyimages(const std::list<crypto::key_image>& images, std::list<uint64_t>& images_stat)const;//true - unspent, false - spent
|
||||
bool build_kernel(const block& bl, stake_kernel& kernel, uint64_t& amount, const stake_modifier_type& stake_modifier)const;
|
||||
// --- PoS ---
|
||||
bool build_kernel(uint64_t amount,
|
||||
const crypto::key_image& ki,
|
||||
bool build_kernel(const crypto::key_image& ki,
|
||||
stake_kernel& kernel,
|
||||
const stake_modifier_type& stake_modifier,
|
||||
uint64_t timestamp)const;
|
||||
bool build_stake_modifier(stake_modifier_type& sm, const alt_chain_type& alt_chain = alt_chain_type(), uint64_t split_height = 0, crypto::hash *p_last_block_hash = nullptr) const;
|
||||
uint64_t timestamp) const;
|
||||
bool build_stake_modifier(stake_modifier_type& sm, const alt_chain_type& alt_chain = alt_chain_type(), uint64_t split_height = 0, crypto::hash* p_last_block_hash = nullptr, uint64_t* p_last_pow_block_height = nullptr) const;
|
||||
|
||||
bool scan_pos(const COMMAND_RPC_SCAN_POS::request& sp, COMMAND_RPC_SCAN_POS::response& rsp)const;
|
||||
bool validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t source_max_unlock_time)const;
|
||||
bool validate_pos_block(const block& b, const crypto::hash& id, bool for_altchain)const;
|
||||
bool validate_pos_block(const block& b, wide_difficulty_type basic_diff, const crypto::hash& id, bool for_altchain)const;
|
||||
|
|
@ -350,7 +369,7 @@ namespace currency
|
|||
wide_difficulty_type basic_diff,
|
||||
uint64_t& amount,
|
||||
wide_difficulty_type& final_diff,
|
||||
crypto::hash& proof_hash,
|
||||
crypto::hash& kernel_hash,
|
||||
const crypto::hash& id,
|
||||
bool for_altchain,
|
||||
const alt_chain_type& alt_chain = alt_chain_type(),
|
||||
|
|
@ -395,7 +414,7 @@ namespace currency
|
|||
missed_bs.push_back(bl_id);
|
||||
else
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(*block_ind_ptr < m_db_blocks.size(), false, "Internal error: bl_id=" << string_tools::pod_to_hex(bl_id)
|
||||
CHECK_AND_ASSERT_MES(*block_ind_ptr < m_db_blocks.size(), false, "Internal error: bl_id=" << epst::pod_to_hex(bl_id)
|
||||
<< " have index record with offset=" << *block_ind_ptr << ", bigger then m_db_blocks.size()=" << m_db_blocks.size());
|
||||
blocks.push_back(m_db_blocks[*block_ind_ptr]->bl);
|
||||
}
|
||||
|
|
@ -450,6 +469,7 @@ namespace currency
|
|||
void serialize(archive_t & ar, const unsigned int version);
|
||||
bool get_est_height_from_date(uint64_t date, uint64_t& res_h)const;
|
||||
|
||||
bool get_pos_votes(uint64_t start_h, uint64_t end_h, vote_results& r);
|
||||
|
||||
//debug functions
|
||||
bool validate_blockchain_prev_links(size_t last_n_blocks_to_check = 10) const;
|
||||
|
|
@ -486,6 +506,9 @@ namespace currency
|
|||
typedef tools::db::cached_key_value_accessor<crypto::hash, ms_output_entry, false, false> multisig_outs_container;// ms out id => ms_output_entry
|
||||
typedef tools::db::cached_key_value_accessor<uint64_t, uint64_t, false, true> solo_options_container;
|
||||
typedef tools::db::basic_key_value_accessor<uint32_t, block_gindex_increments, true> per_block_gindex_increments_container; // height => [(amount, gindex_increment), ...]
|
||||
|
||||
typedef tools::db::cached_key_value_accessor<crypto::public_key, std::list<asset_descriptor_operation>, true, false> assets_container; // TODO @#@# consider storing tx_id as well for reference -- sowle
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
|
||||
|
|
@ -527,13 +550,14 @@ namespace currency
|
|||
address_to_aliases_container m_db_addr_to_alias;
|
||||
per_block_gindex_increments_container m_db_per_block_gindex_incs;
|
||||
|
||||
assets_container m_db_assets;
|
||||
|
||||
|
||||
|
||||
|
||||
mutable critical_section m_invalid_blocks_lock;
|
||||
mutable epee::critical_section m_invalid_blocks_lock;
|
||||
blocks_ext_by_hash m_invalid_blocks; // crypto::hash -> block_extended_info
|
||||
mutable critical_section m_alternative_chains_lock;
|
||||
mutable epee::critical_section m_alternative_chains_lock;
|
||||
alt_chain_container m_alternative_chains; // crypto::hash -> alt_block_extended_info
|
||||
std::unordered_map<crypto::hash, size_t> m_alternative_chains_txs; // tx_id -> how many alt blocks it related to (always >= 1)
|
||||
std::unordered_map<crypto::key_image, std::list<crypto::hash>> m_altblocks_keyimages; // key image -> list of alt blocks hashes where it appears in inputs
|
||||
|
|
@ -557,7 +581,7 @@ namespace currency
|
|||
mutable wide_difficulty_type m_cached_next_pow_difficulty;
|
||||
mutable wide_difficulty_type m_cached_next_pos_difficulty;
|
||||
|
||||
mutable critical_section m_targetdata_cache_lock;
|
||||
mutable epee::critical_section m_targetdata_cache_lock;
|
||||
mutable std::list <std::pair<wide_difficulty_type, uint64_t>> m_pos_targetdata_cache;
|
||||
mutable std::list <std::pair<wide_difficulty_type, uint64_t>> m_pow_targetdata_cache;
|
||||
//work like a cache to avoid recalculation on read operations
|
||||
|
|
@ -567,8 +591,8 @@ namespace currency
|
|||
mutable std::atomic<bool> m_deinit_is_done;
|
||||
mutable uint64_t m_blockchain_launch_timestamp;
|
||||
|
||||
bool init_tx_fee_median();
|
||||
bool update_tx_fee_median();
|
||||
//bool init_tx_fee_median();
|
||||
//bool update_tx_fee_median();
|
||||
void store_db_solo_options_values();
|
||||
bool set_lost_tx_unmixable();
|
||||
bool set_lost_tx_unmixable_for_height(uint64_t height);
|
||||
|
|
@ -584,11 +608,12 @@ namespace currency
|
|||
wide_difficulty_type get_next_difficulty_for_alternative_chain(const alt_chain_type& alt_chain, block_extended_info& bei, bool pos) const;
|
||||
bool handle_block_to_main_chain(const block& bl, block_verification_context& bvc);
|
||||
bool handle_block_to_main_chain(const block& bl, const crypto::hash& id, block_verification_context& bvc);
|
||||
bool collect_rangeproofs_data_from_tx(const transaction& tx, const crypto::hash& tx_id, std::vector<zc_outs_range_proofs_with_commitments>& agregated_proofs);
|
||||
std::string print_alt_chain(alt_chain_type alt_chain);
|
||||
bool handle_alternative_block(const block& b, const crypto::hash& id, block_verification_context& bvc);
|
||||
bool is_reorganize_required(const block_extended_info& main_chain_bei, const alt_chain_type& alt_chain, const crypto::hash& proof_alt);
|
||||
wide_difficulty_type get_x_difficulty_after_height(uint64_t height, bool is_pos);
|
||||
bool purge_keyimage_from_big_heap(const crypto::key_image& ki, const crypto::hash& id);
|
||||
bool purge_keyimage_from_big_heap(const crypto::key_image& ki, const crypto::hash& block_id);
|
||||
bool purge_altblock_keyimages_from_big_heap(const block& b, const crypto::hash& id);
|
||||
bool append_altblock_keyimages_to_big_heap(const crypto::hash& block_id, const std::unordered_set<crypto::key_image>& alt_block_keyimages);
|
||||
bool validate_alt_block_input(const transaction& input_tx,
|
||||
|
|
@ -597,13 +622,17 @@ namespace currency
|
|||
const crypto::hash& bl_id,
|
||||
const crypto::hash& input_tx_hash,
|
||||
size_t input_index,
|
||||
const std::vector<crypto::signature>& input_sigs,
|
||||
uint64_t split_height,
|
||||
const alt_chain_type& alt_chain,
|
||||
const std::unordered_set<crypto::hash>& alt_chain_block_ids,
|
||||
uint64_t& ki_lookuptime,
|
||||
uint64_t* p_max_related_block_height = nullptr) const;
|
||||
bool validate_alt_block_ms_input(const transaction& input_tx, const crypto::hash& input_tx_hash, size_t input_index, const std::vector<crypto::signature>& input_sigs, uint64_t split_height, const alt_chain_type& alt_chain) const;
|
||||
bool validate_alt_block_ms_input(const transaction& input_tx,
|
||||
const crypto::hash& input_tx_hash,
|
||||
size_t input_index,
|
||||
//const signature_v& input_sigs,//const std::vector<crypto::signature>& input_sigs,
|
||||
uint64_t split_height,
|
||||
const alt_chain_type& alt_chain) const;
|
||||
bool validate_alt_block_txs(const block& b, const crypto::hash& id, std::unordered_set<crypto::key_image>& collected_keyimages, alt_block_extended_info& abei, const alt_chain_type& alt_chain, uint64_t split_height, uint64_t& ki_lookup_time_total) const;
|
||||
bool update_alt_out_indexes_for_tx_in_block(const transaction& tx, alt_block_extended_info& abei)const;
|
||||
bool get_transaction_from_pool_or_db(const crypto::hash& tx_id, std::shared_ptr<transaction>& tx_ptr, uint64_t min_allowed_block_height = 0) const;
|
||||
|
|
@ -613,14 +642,15 @@ namespace currency
|
|||
bool add_transaction_from_block(const transaction& tx, const crypto::hash& tx_id, const crypto::hash& bl_id, uint64_t bl_height, uint64_t timestamp);
|
||||
bool push_transaction_to_global_outs_index(const transaction& tx, const crypto::hash& tx_id, std::vector<uint64_t>& global_indexes);
|
||||
bool pop_transaction_from_global_index(const transaction& tx, const crypto::hash& tx_id);
|
||||
bool add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, uint64_t amount, size_t i, uint64_t mix_count, bool use_only_forced_to_mix = false) const;
|
||||
bool add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, uint64_t amount, size_t i, uint64_t mix_count, bool use_only_forced_to_mix = false, uint64_t height_upper_limit = 0) const;
|
||||
bool get_target_outs_for_amount_prezarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const;
|
||||
bool get_target_outs_for_postzarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const;
|
||||
bool add_block_as_invalid(const block& bl, const crypto::hash& h);
|
||||
bool add_block_as_invalid(const block_extended_info& bei, const crypto::hash& h);
|
||||
size_t find_end_of_allowed_index(uint64_t amount)const;
|
||||
bool check_block_timestamp_main(const block& b)const;
|
||||
bool check_block_timestamp(std::vector<uint64_t> timestamps, const block& b)const;
|
||||
std::vector<uint64_t> get_last_n_blocks_timestamps(size_t n)const;
|
||||
const std::vector<txin_etc_details_v>& get_txin_etc_options(const txin_v& in)const;
|
||||
void on_block_added(const block_extended_info& bei, const crypto::hash& id, const std::list<crypto::key_image>& bsk);
|
||||
void on_block_removed(const block_extended_info& bei);
|
||||
void update_targetdata_cache_on_block_added(const block_extended_info& bei);
|
||||
|
|
@ -629,22 +659,26 @@ namespace currency
|
|||
uint64_t get_tx_fee_median_effective_index(uint64_t h) const;
|
||||
void on_abort_transaction();
|
||||
void load_targetdata_cache(bool is_pos) const;
|
||||
|
||||
|
||||
|
||||
uint64_t get_adjusted_time()const;
|
||||
bool complete_timestamps_vector(uint64_t start_height, std::vector<uint64_t>& timestamps);
|
||||
bool update_next_comulative_size_limit();
|
||||
bool process_blockchain_tx_extra(const transaction& tx);
|
||||
bool process_blockchain_tx_extra(const transaction& tx, const crypto::hash& tx_id);
|
||||
bool unprocess_blockchain_tx_extra(const transaction& tx);
|
||||
bool process_blockchain_tx_attachments(const transaction& tx, uint64_t h, const crypto::hash& bl_id, uint64_t timestamp);
|
||||
bool unprocess_blockchain_tx_attachments(const transaction& tx, uint64_t h, uint64_t timestamp);
|
||||
bool validate_ado_ownership(asset_op_verification_context& avc);
|
||||
bool pop_alias_info(const extra_alias_entry& ai);
|
||||
bool put_alias_info(const transaction& tx, extra_alias_entry& ai);
|
||||
bool pop_asset_info(const crypto::public_key& asset_id);
|
||||
bool put_asset_info(const transaction& tx, const crypto::hash& tx_id, const asset_descriptor_operation& ado);
|
||||
void fill_addr_to_alias_dict();
|
||||
//bool resync_spent_tx_flags();
|
||||
bool prune_ring_signatures_and_attachments_if_need();
|
||||
bool prune_ring_signatures_and_attachments(uint64_t height, uint64_t& transactions_pruned, uint64_t& signatures_pruned, uint64_t& attachments_pruned);
|
||||
// bool build_stake_modifier_for_alt(const alt_chain_type& alt_chain, stake_modifier_type& sm);
|
||||
|
||||
template<class visitor_t>
|
||||
bool enum_blockchain(visitor_t& v, const alt_chain_type& alt_chain = alt_chain_type(), uint64_t split_height = 0) const;
|
||||
bool update_spent_tx_flags_for_input(uint64_t amount, const txout_ref_v& o, bool spent);
|
||||
|
|
@ -661,13 +695,7 @@ namespace currency
|
|||
bool is_output_allowed_for_input(const output_key_or_htlc_v& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const;
|
||||
bool is_output_allowed_for_input(const txout_to_key& out_v, const txin_v& in_v)const;
|
||||
bool is_output_allowed_for_input(const txout_htlc& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const;
|
||||
bool is_after_hardfork_1_zone()const;
|
||||
bool is_after_hardfork_1_zone(uint64_t height)const;
|
||||
bool is_after_hardfork_2_zone()const;
|
||||
bool is_after_hardfork_2_zone(uint64_t height)const;
|
||||
bool is_after_hardfork_3_zone()const;
|
||||
bool is_after_hardfork_3_zone(uint64_t height)const;
|
||||
|
||||
bool is_output_allowed_for_input(const tx_out_zarcanum& out, const txin_v& in_v) const;
|
||||
|
||||
|
||||
|
||||
|
|
@ -714,10 +742,10 @@ namespace currency
|
|||
template<class visitor_t>
|
||||
bool blockchain_storage::scan_outputkeys_for_indexes(const transaction &validated_tx, const txin_v& verified_input, visitor_t& vis, uint64_t& max_related_block_height, scan_for_keys_context& scan_context) const
|
||||
{
|
||||
const txin_to_key& input_to_key = get_to_key_input_from_txin_v(verified_input);
|
||||
bool hf4 = this->is_hardfork_active(ZANO_HARDFORK_04_ZARCANUM);
|
||||
|
||||
uint64_t amount = input_to_key.amount;
|
||||
const std::vector<txout_ref_v>& key_offsets = input_to_key.key_offsets;
|
||||
uint64_t amount = get_amount_from_variant(verified_input);
|
||||
const std::vector<txout_ref_v>& key_offsets = get_key_offsets_from_txin_v(verified_input);
|
||||
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_get_item_size);
|
||||
|
|
@ -731,7 +759,7 @@ namespace currency
|
|||
TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_relative_to_absolute);
|
||||
TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop);
|
||||
size_t output_index = 0;
|
||||
for(const txout_ref_v& o : absolute_offsets)
|
||||
for (const txout_ref_v& o : absolute_offsets)
|
||||
{
|
||||
crypto::hash tx_id = null_hash;
|
||||
size_t n = 0;
|
||||
|
|
@ -756,7 +784,7 @@ namespace currency
|
|||
}
|
||||
TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop_find_tx);
|
||||
auto tx_ptr = m_db_transactions.find(tx_id);
|
||||
CHECK_AND_ASSERT_MES(tx_ptr, false, "Wrong transaction id in output indexes: " << string_tools::pod_to_hex(tx_id));
|
||||
CHECK_AND_ASSERT_MES(tx_ptr, false, "Wrong transaction id in output indexes: " << epst::pod_to_hex(tx_id));
|
||||
CHECK_AND_ASSERT_MES(n < tx_ptr->tx.vout.size(), false,
|
||||
"Wrong index in transaction outputs: " << n << ", expected less then " << tx_ptr->tx.vout.size());
|
||||
//check mix_attr
|
||||
|
|
@ -774,57 +802,109 @@ namespace currency
|
|||
TO_KEY | TO_KEY | YES
|
||||
*/
|
||||
|
||||
bool r = is_output_allowed_for_input(tx_ptr->tx.vout[n].target, verified_input, get_current_blockchain_size() - tx_ptr->m_keeper_block_height);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type");
|
||||
|
||||
if (tx_ptr->tx.vout[n].target.type() == typeid(txout_to_key))
|
||||
VARIANT_SWITCH_BEGIN(tx_ptr->tx.vout[n]);
|
||||
VARIANT_CASE_CONST(tx_out_bare, o)
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(tx_ptr->tx.vout[n].target, const txout_to_key, outtk, false);
|
||||
//fix for burned money
|
||||
patch_out_if_needed(const_cast<txout_to_key&>(outtk), tx_id, n);
|
||||
bool r = is_output_allowed_for_input(o.target, verified_input, get_current_blockchain_size() - tx_ptr->m_keeper_block_height);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type");
|
||||
|
||||
bool mixattr_ok = is_mixattr_applicable_for_fake_outs_counter(outtk.mix_attr, key_offsets.size() - 1);
|
||||
CHECK_AND_ASSERT_MES(mixattr_ok, false, "tx output #" << output_index << " violates mixin restrictions: mix_attr = " << static_cast<uint32_t>(outtk.mix_attr) << ", key_offsets.size = " << key_offsets.size());
|
||||
}
|
||||
else if (tx_ptr->tx.vout[n].target.type() == typeid(txout_htlc))
|
||||
{
|
||||
//check for spend flags
|
||||
CHECK_AND_ASSERT_MES(tx_ptr->m_spent_flags.size() > n, false,
|
||||
"Internal error: tx_ptr->m_spent_flags.size(){" << tx_ptr->m_spent_flags.size() << "} > n{" << n << "}");
|
||||
CHECK_AND_ASSERT_MES(tx_ptr->m_spent_flags[n] == false, false, "HTLC out already spent, double spent attempt detected");
|
||||
|
||||
const txout_htlc& htlc_out = boost::get<txout_htlc>(tx_ptr->tx.vout[n].target);
|
||||
if (htlc_out.expiration > get_current_blockchain_size() - tx_ptr->m_keeper_block_height)
|
||||
if (o.target.type() == typeid(txout_to_key))
|
||||
{
|
||||
//HTLC IS NOT expired, can be used ONLY by pkey_before_expiration and ONLY by HTLC input
|
||||
scan_context.htlc_is_expired = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//HTLC IS expired, can be used ONLY by pkey_after_expiration and ONLY by to_key input
|
||||
scan_context.htlc_is_expired = true;
|
||||
}
|
||||
}else
|
||||
{
|
||||
LOG_ERROR("[scan_outputkeys_for_indexes]: Wrong output type in : " << tx_ptr->tx.vout[n].target.type().name());
|
||||
return false;
|
||||
}
|
||||
CHECKED_GET_SPECIFIC_VARIANT(o.target, const txout_to_key, outtk, false);
|
||||
//fix for burned money
|
||||
patch_out_if_needed(const_cast<txout_to_key&>(outtk), tx_id, n);
|
||||
|
||||
bool mixattr_ok = is_mixattr_applicable_for_fake_outs_counter(tx_ptr->tx.version, outtk.mix_attr, key_offsets.size() - 1, this->get_core_runtime_config());
|
||||
CHECK_AND_ASSERT_MES(mixattr_ok, false, "tx input ref #" << output_index << " violates mixin restrictions: tx.version = " << tx_ptr->tx.version << ", mix_attr = " << static_cast<uint32_t>(outtk.mix_attr) << ", key_offsets.size = " << key_offsets.size());
|
||||
if (hf4)
|
||||
{
|
||||
bool legit_output_key = validate_output_key_legit(outtk.key);
|
||||
CHECK_AND_ASSERT_MES(legit_output_key, false, "tx input ref #" << output_index << " violates public key restrictions: tx.version = " << tx_ptr->tx.version << ", outtk.key = " << outtk.key);
|
||||
}
|
||||
}
|
||||
else if (o.target.type() == typeid(txout_htlc))
|
||||
{
|
||||
//check for spend flags
|
||||
CHECK_AND_ASSERT_MES(tx_ptr->m_spent_flags.size() > n, false,
|
||||
"Internal error: tx_ptr->m_spent_flags.size(){" << tx_ptr->m_spent_flags.size() << "} > n{" << n << "}");
|
||||
CHECK_AND_ASSERT_MES(tx_ptr->m_spent_flags[n] == false, false, "HTLC out already spent, double spent attempt detected");
|
||||
|
||||
const txout_htlc& htlc_out = boost::get<txout_htlc>(o.target);
|
||||
if (htlc_out.expiration > get_current_blockchain_size() - tx_ptr->m_keeper_block_height)
|
||||
{
|
||||
//HTLC IS NOT expired, can be used ONLY by pkey_before_expiration and ONLY by HTLC input
|
||||
scan_context.htlc_is_expired = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//HTLC IS expired, can be used ONLY by pkey_after_expiration and ONLY by to_key input
|
||||
scan_context.htlc_is_expired = true;
|
||||
}
|
||||
if (hf4)
|
||||
{
|
||||
bool legit_output_key = validate_output_key_legit(scan_context.htlc_is_expired ? htlc_out.pkey_refund : htlc_out.pkey_redeem);
|
||||
CHECK_AND_ASSERT_MES(legit_output_key, false, "tx input ref #" << output_index << " violates public key restrictions: tx.version = " << tx_ptr->tx.version << ", outtk.key = " << static_cast<const crypto::public_key&>(scan_context.htlc_is_expired ? htlc_out.pkey_refund : htlc_out.pkey_redeem));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("[scan_outputkeys_for_indexes]: Wrong output type in : " << o.target.type().name());
|
||||
return false;
|
||||
}
|
||||
|
||||
TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output);
|
||||
|
||||
if (!vis.handle_output(tx_ptr->tx, validated_tx, o, n))
|
||||
{
|
||||
size_t verified_input_index = std::find(validated_tx.vin.begin(), validated_tx.vin.end(), verified_input) - validated_tx.vin.begin();
|
||||
LOG_PRINT_RED_L0("handle_output failed for output #" << n << " in " << tx_id << " referenced by input #" << verified_input_index << " in tx " << get_transaction_hash(validated_tx));
|
||||
return false;
|
||||
}
|
||||
TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output);
|
||||
}
|
||||
VARIANT_CASE_CONST(tx_out_zarcanum, out_zc)
|
||||
bool r = is_output_allowed_for_input(out_zc, verified_input);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Input and output are incompatible");
|
||||
|
||||
r = is_mixattr_applicable_for_fake_outs_counter(tx_ptr->tx.version, out_zc.mix_attr, key_offsets.size() - 1, this->get_core_runtime_config());
|
||||
CHECK_AND_ASSERT_MES(r, false, "tx input ref #" << output_index << " violates mixin restrictions: tx.version = " << tx_ptr->tx.version << ", mix_attr = " << static_cast<uint32_t>(out_zc.mix_attr) << ", key_offsets.size = " << key_offsets.size());
|
||||
|
||||
bool legit_output_key = validate_output_key_legit(out_zc.stealth_address);
|
||||
CHECK_AND_ASSERT_MES(legit_output_key, false, "tx input ref #" << output_index << " violates public key restrictions: tx.version = " << tx_ptr->tx.version << ", outtk.key = " << out_zc.stealth_address);
|
||||
|
||||
|
||||
|
||||
TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output);
|
||||
if (!vis.handle_output(tx_ptr->tx, validated_tx, tx_ptr->tx.vout[n], n))
|
||||
if (!vis.handle_output(tx_ptr->tx, validated_tx, out_zc, n))
|
||||
{
|
||||
LOG_PRINT_L0("Failed to handle_output for output id = " << tx_id << ", no " << n);
|
||||
size_t verified_input_index = std::find(validated_tx.vin.begin(), validated_tx.vin.end(), verified_input) - validated_tx.vin.begin();
|
||||
LOG_PRINT_RED_L0("handle_output failed for output #" << n << " in " << tx_id << " referenced by input #" << verified_input_index << " in tx " << get_transaction_hash(validated_tx));
|
||||
return false;
|
||||
}
|
||||
TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output);
|
||||
VARIANT_CASE_THROW_ON_OTHER();
|
||||
VARIANT_SWITCH_END();
|
||||
|
||||
if (max_related_block_height < tx_ptr->m_keeper_block_height)
|
||||
max_related_block_height = tx_ptr->m_keeper_block_height;
|
||||
|
||||
|
||||
|
||||
if (max_related_block_height < tx_ptr->m_keeper_block_height)
|
||||
max_related_block_height = tx_ptr->m_keeper_block_height;
|
||||
|
||||
++output_index;
|
||||
}
|
||||
|
||||
if (m_core_runtime_config.is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, this->get_current_blockchain_size()))
|
||||
{
|
||||
//with hard fork 4 make it network rule to have at least 10 confirmations
|
||||
|
||||
if (this->get_current_blockchain_size() - max_related_block_height < CURRENCY_HF4_MANDATORY_MIN_COINAGE)
|
||||
{
|
||||
LOG_ERROR("Coinage rule broken(mainblock): h = " << this->get_current_blockchain_size() << ", max_related_block_height=" << max_related_block_height << ", tx: " << get_transaction_hash(validated_tx));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2018 Zano Project
|
||||
// Copyright (c) 2014-2023 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Copyright (c) 2012-2013 The Boolberry developers
|
||||
|
|
@ -19,6 +19,8 @@
|
|||
#include "currency_basic.h"
|
||||
#include "difficulty.h"
|
||||
#include "currency_protocol/blobdatatype.h"
|
||||
#include "currency_format_utils_transactions.h" // only for output_generation_context
|
||||
|
||||
namespace currency
|
||||
{
|
||||
|
||||
|
|
@ -46,9 +48,9 @@ namespace currency
|
|||
block bl;
|
||||
uint64_t height;
|
||||
uint64_t block_cumulative_size;
|
||||
wide_difficulty_type cumulative_diff_adjusted;
|
||||
wide_difficulty_type cumulative_diff_adjusted; // used only before hardfork 1
|
||||
wide_difficulty_type cumulative_diff_precise;
|
||||
wide_difficulty_type cumulative_diff_precise_adjusted;
|
||||
wide_difficulty_type cumulative_diff_precise_adjusted; //used after hardfork 1 (cumulative difficulty adjusted only by sequence factor)
|
||||
wide_difficulty_type difficulty;
|
||||
boost::multiprecision::uint128_t already_generated_coins;
|
||||
crypto::hash stake_hash; //TODO: unused field for PoW blocks, subject for refactoring
|
||||
|
|
@ -144,6 +146,10 @@ namespace currency
|
|||
block b;
|
||||
wide_difficulty_type diffic;
|
||||
uint64_t height;
|
||||
tx_generation_context miner_tx_tgc; // bad design, a lot of copying, consider redesign -- sowle
|
||||
uint64_t block_reward_without_fee;
|
||||
uint64_t block_reward; // == block_reward_without_fee + txs_fee if fees are given to the miner, OR block_reward_without_fee if fees are burnt
|
||||
uint64_t txs_fee; // sum of transactions' fee if any
|
||||
};
|
||||
|
||||
typedef std::unordered_map<crypto::hash, transaction> transactions_map;
|
||||
|
|
@ -154,6 +160,28 @@ namespace currency
|
|||
transactions_map onboard_transactions;
|
||||
};
|
||||
|
||||
struct vote_on_proposal
|
||||
{
|
||||
std::string proposal_id;
|
||||
uint64_t yes;
|
||||
uint64_t no;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(proposal_id)
|
||||
KV_SERIALIZE(yes)
|
||||
KV_SERIALIZE(no)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
}
|
||||
struct vote_results
|
||||
{
|
||||
uint64_t total_pos_blocks; //total pos blocks in a given range
|
||||
std::list<vote_on_proposal> votes;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(total_pos_blocks)
|
||||
KV_SERIALIZE(votes)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
} // namespace currency
|
||||
|
|
|
|||
|
|
@ -5,13 +5,97 @@
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
#include "boost/serialization/array.hpp"
|
||||
#include "misc_language.h"
|
||||
#include "string_tools.h"
|
||||
|
||||
namespace currency
|
||||
{
|
||||
struct hard_forks_descriptor
|
||||
{
|
||||
constexpr static size_t m_total_count = ZANO_HARDFORKS_TOTAL;
|
||||
std::array<uint64_t, m_total_count> m_height_the_hardfork_n_active_after;
|
||||
|
||||
hard_forks_descriptor()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_height_the_hardfork_n_active_after.fill(CURRENCY_MAX_BLOCK_NUMBER);
|
||||
}
|
||||
|
||||
void set_hardfork_height(size_t hardfork_id, uint64_t height_the_hardfork_is_active_after)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(hardfork_id < m_total_count, "invalid hardfork id: " << hardfork_id);
|
||||
m_height_the_hardfork_n_active_after[hardfork_id] = height_the_hardfork_is_active_after;
|
||||
|
||||
// set all unset previous hardforks to this height
|
||||
for(size_t hid = hardfork_id - 1; hid + 1 != 0; --hid)
|
||||
{
|
||||
if (m_height_the_hardfork_n_active_after[hid] == CURRENCY_MAX_BLOCK_NUMBER)
|
||||
m_height_the_hardfork_n_active_after[hid] = height_the_hardfork_is_active_after;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_hardfork_active_for_height(size_t hardfork_id, uint64_t height) const
|
||||
{
|
||||
if (hardfork_id == 0)
|
||||
return true; // hardfork #0 is a special case that is considered always active
|
||||
CHECK_AND_ASSERT_THROW_MES(hardfork_id < m_total_count, "invalid hardfork id: " << hardfork_id);
|
||||
return height > m_height_the_hardfork_n_active_after[hardfork_id];
|
||||
}
|
||||
|
||||
std::string get_str_height_the_hardfork_active_after(size_t hardfork_id) const
|
||||
{
|
||||
if (hardfork_id == 0)
|
||||
return "0"; // hardfork #0 is a special case that is considered always active
|
||||
CHECK_AND_ASSERT_THROW_MES(hardfork_id < m_total_count, "invalid hardfork id: " << hardfork_id);
|
||||
return epee::string_tools::num_to_string_fast(m_height_the_hardfork_n_active_after[hardfork_id]);
|
||||
}
|
||||
|
||||
size_t get_the_most_recent_hardfork_id_for_height(uint64_t height) const
|
||||
{
|
||||
for(size_t hid = m_total_count - 1; hid != 0; --hid) // 0 is not including
|
||||
{
|
||||
if(is_hardfork_active_for_height(hid, height))
|
||||
return hid;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t get_block_major_version_by_height(uint64_t height) const
|
||||
{
|
||||
if (!this->is_hardfork_active_for_height(1, height))
|
||||
return BLOCK_MAJOR_VERSION_INITIAL;
|
||||
else if (!this->is_hardfork_active_for_height(3, height))
|
||||
return HF1_BLOCK_MAJOR_VERSION;
|
||||
else if (!this->is_hardfork_active_for_height(4, height))
|
||||
return HF3_BLOCK_MAJOR_VERSION;
|
||||
else
|
||||
return CURRENT_BLOCK_MAJOR_VERSION;
|
||||
}
|
||||
|
||||
uint8_t get_block_minor_version_by_height(uint64_t height) const
|
||||
{
|
||||
return HF3_BLOCK_MINOR_VERSION;
|
||||
}
|
||||
|
||||
bool operator==(const hard_forks_descriptor& rhs) const
|
||||
{
|
||||
return m_height_the_hardfork_n_active_after == rhs.m_height_the_hardfork_n_active_after;
|
||||
}
|
||||
|
||||
bool operator!=(const hard_forks_descriptor& rhs) const
|
||||
{
|
||||
return ! operator==(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef uint64_t (*core_time_func_t)();
|
||||
|
||||
|
||||
struct core_runtime_config
|
||||
{
|
||||
uint64_t min_coinstake_age;
|
||||
|
|
@ -21,21 +105,13 @@ namespace currency
|
|||
uint64_t max_alt_blocks;
|
||||
crypto::public_key alias_validation_pubkey;
|
||||
core_time_func_t get_core_time;
|
||||
uint64_t hf4_minimum_mixins;
|
||||
|
||||
uint64_t hard_fork_01_starts_after_height;
|
||||
uint64_t hard_fork_02_starts_after_height;
|
||||
uint64_t hard_fork_03_starts_after_height;
|
||||
hard_forks_descriptor hard_forks;
|
||||
|
||||
bool is_hardfork_active_for_height(size_t hardfork_id, uint64_t height) const
|
||||
{
|
||||
switch (hardfork_id)
|
||||
{
|
||||
case 0: return true;
|
||||
case 1: return height > hard_fork_01_starts_after_height;
|
||||
case 2: return height > hard_fork_02_starts_after_height;
|
||||
case 3: return height > hard_fork_03_starts_after_height;
|
||||
default: return false;
|
||||
}
|
||||
return hard_forks.is_hardfork_active_for_height(hardfork_id, height);
|
||||
}
|
||||
|
||||
static uint64_t _default_core_time_function()
|
||||
|
|
@ -52,10 +128,13 @@ namespace currency
|
|||
pc.tx_pool_min_fee = TX_MINIMUM_FEE;
|
||||
pc.tx_default_fee = TX_DEFAULT_FEE;
|
||||
pc.max_alt_blocks = CURRENCY_ALT_BLOCK_MAX_COUNT;
|
||||
pc.hf4_minimum_mixins = CURRENCY_HF4_MANDATORY_DECOY_SET_SIZE;
|
||||
|
||||
pc.hard_fork_01_starts_after_height = ZANO_HARDFORK_01_AFTER_HEIGHT;
|
||||
pc.hard_fork_02_starts_after_height = ZANO_HARDFORK_02_AFTER_HEIGHT;
|
||||
pc.hard_fork_03_starts_after_height = ZANO_HARDFORK_03_AFTER_HEIGHT;
|
||||
// TODO: refactor the following
|
||||
pc.hard_forks.set_hardfork_height(1, ZANO_HARDFORK_01_AFTER_HEIGHT);
|
||||
pc.hard_forks.set_hardfork_height(2, ZANO_HARDFORK_02_AFTER_HEIGHT);
|
||||
pc.hard_forks.set_hardfork_height(3, ZANO_HARDFORK_03_AFTER_HEIGHT);
|
||||
pc.hard_forks.set_hardfork_height(4, ZANO_HARDFORK_04_AFTER_HEIGHT);
|
||||
|
||||
pc.get_core_time = &core_runtime_config::_default_core_time_function;
|
||||
bool r = epee::string_tools::hex_to_pod(ALIAS_SHORT_NAMES_VALIDATION_PUB_KEY, pc.alias_validation_pubkey);
|
||||
|
|
|
|||
43
src/currency_core/crypto_config.h
Normal file
43
src/currency_core/crypto_config.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) 2022-2023 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
// hash domain separation strings, 32 bytes long (31 chars + \0)
|
||||
//
|
||||
|
||||
#define CRYPTO_HDS_OUT_AMOUNT_MASK "ZANO_HDS_OUT_AMOUNT_MASK_______"
|
||||
#define CRYPTO_HDS_OUT_AMOUNT_BLINDING_MASK "ZANO_HDS_OUT_AMOUNT_BLIND_MASK_"
|
||||
#define CRYPTO_HDS_OUT_ASSET_BLINDING_MASK "ZANO_HDS_OUT_ASSET_BLIND_MASK__"
|
||||
#define CRYPTO_HDS_OUT_CONCEALING_POINT "ZANO_HDS_OUT_CONCEALING_POINT__"
|
||||
|
||||
#define CRYPTO_HDS_CLSAG_GG_LAYER_0 "ZANO_HDS_CLSAG_GG_LAYER_ZERO___"
|
||||
#define CRYPTO_HDS_CLSAG_GG_LAYER_1 "ZANO_HDS_CLSAG_GG_LAYER_ONE____"
|
||||
#define CRYPTO_HDS_CLSAG_GG_CHALLENGE "ZANO_HDS_CLSAG_GG_CHALLENGE____"
|
||||
|
||||
#define CRYPTO_HDS_CLSAG_GGX_LAYER_0 "ZANO_HDS_CLSAG_GGX_LAYER_ZERO__"
|
||||
#define CRYPTO_HDS_CLSAG_GGX_LAYER_1 "ZANO_HDS_CLSAG_GGX_LAYER_ONE___"
|
||||
#define CRYPTO_HDS_CLSAG_GGX_LAYER_2 "ZANO_HDS_CLSAG_GGX_LAYER_TWO___"
|
||||
#define CRYPTO_HDS_CLSAG_GGX_CHALLENGE "ZANO_HDS_CLSAG_GGX_CHALLENGE___"
|
||||
|
||||
#define CRYPTO_HDS_CLSAG_GGXG_LAYER_0 "ZANO_HDS_CLSAG_GGXG_LAYER_ZERO_"
|
||||
#define CRYPTO_HDS_CLSAG_GGXG_LAYER_1 "ZANO_HDS_CLSAG_GGXG_LAYER_ONE__"
|
||||
#define CRYPTO_HDS_CLSAG_GGXG_LAYER_2 "ZANO_HDS_CLSAG_GGXG_LAYER_TWO__"
|
||||
#define CRYPTO_HDS_CLSAG_GGXG_LAYER_3 "ZANO_HDS_CLSAG_GGXG_LAYER_THREE"
|
||||
#define CRYPTO_HDS_CLSAG_GGXG_CHALLENGE "ZANO_HDS_CLSAG_GGXG_CHALLENGE__"
|
||||
|
||||
#define CRYPTO_HDS_CLSAG_GGXXG_LAYER_0 "ZANO_HDS_CLSAG_GGXXG_LAYER_ZERO"
|
||||
#define CRYPTO_HDS_CLSAG_GGXXG_LAYER_1 "ZANO_HDS_CLSAG_GGXXG_LAYER_ONE_"
|
||||
#define CRYPTO_HDS_CLSAG_GGXXG_LAYER_2 "ZANO_HDS_CLSAG_GGXXG_LAYER_TWO_"
|
||||
#define CRYPTO_HDS_CLSAG_GGXXG_LAYER_3 "ZANO_HDS_CLSAG_GGXXG_LAYER_3___"
|
||||
#define CRYPTO_HDS_CLSAG_GGXXG_LAYER_4 "ZANO_HDS_CLSAG_GGXXG_LAYER_FOUR"
|
||||
#define CRYPTO_HDS_CLSAG_GGXXG_CHALLENGE "ZANO_HDS_CLSAG_GGXXG_CHALLENGE_"
|
||||
|
||||
#define CRYPTO_HDS_ZARCANUM_LAST_POW_HASH "ZANO_HDS_ZARCANUM_LAST_POW_HASH"
|
||||
#define CRYPTO_HDS_ZARCANUM_PROOF_HASH "ZANO_HDS_ZARCANUM_PROOF_HASH___"
|
||||
|
||||
#define CRYPTO_HDS_ASSET_CONTROL_KEY "ZANO_HDS_ASSET_CONTROL_KEY_____"
|
||||
#define CRYPTO_HDS_ASSET_CONTROL_ABM "ZANO_HDS_ASSET_CONTROL_ABM_____"
|
||||
#define CRYPTO_HDS_ASSET_ID "ZANO_HDS_ASSET_ID______________"
|
||||
#define CRYPTO_HDS_DETERMINISTIC_TX_KEY "ZANO_HDS_DETERMINISTIC_TX_KEY__"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2019 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Copyright (c) 2014-2015 The Boolberry developers
|
||||
|
|
@ -26,10 +26,11 @@
|
|||
#include "include_base_utils.h"
|
||||
|
||||
#include "serialization/binary_archive.h"
|
||||
#include "serialization/crypto.h"
|
||||
#include "common/crypto_serialization.h"
|
||||
#include "serialization/stl_containers.h"
|
||||
#include "serialization/serialization.h"
|
||||
#include "serialization/variant.h"
|
||||
#include "serialization/boost_types.h"
|
||||
#include "serialization/json_archive.h"
|
||||
#include "serialization/debug_archive.h"
|
||||
#include "serialization/keyvalue_serialization.h" // epee key-value serialization
|
||||
|
|
@ -37,9 +38,12 @@
|
|||
#include "currency_config.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "crypto/range_proofs.h"
|
||||
#include "crypto/zarcanum.h"
|
||||
#include "misc_language.h"
|
||||
#include "block_flags.h"
|
||||
#include "etc_custom_serialization.h"
|
||||
#include "difficulty.h"
|
||||
|
||||
namespace currency
|
||||
{
|
||||
|
|
@ -53,6 +57,16 @@ namespace currency
|
|||
|
||||
const static crypto::hash gdefault_genesis = epee::string_tools::hex_to_pod<crypto::hash>("CC608F59F8080E2FBFE3C8C80EB6E6A953D47CF2D6AEBD345BADA3A1CAB99852");
|
||||
|
||||
// Using C++17 extended aggregate initialization (P0017R1). C++17, finally! -- sowle
|
||||
const static crypto::public_key native_coin_asset_id = {{'\xd6', '\x32', '\x9b', '\x5b', '\x1f', '\x7c', '\x08', '\x05', '\xb5', '\xc3', '\x45', '\xf4', '\x95', '\x75', '\x54', '\x00', '\x2a', '\x2f', '\x55', '\x78', '\x45', '\xf6', '\x4d', '\x76', '\x45', '\xda', '\xe0', '\xe0', '\x51', '\xa6', '\x49', '\x8a'}}; // == crypto::c_point_H, checked in crypto_constants
|
||||
const static crypto::public_key native_coin_asset_id_1div8 = {{'\x74', '\xc3', '\x2d', '\x3e', '\xaa', '\xfa', '\xfc', '\x62', '\x3b', '\xf4', '\x83', '\xe8', '\x58', '\xd4', '\x2e', '\x8b', '\xf4', '\xec', '\x7d', '\xf0', '\x64', '\xad', '\xa2', '\xe3', '\x49', '\x34', '\x46', '\x9c', '\xff', '\x6b', '\x62', '\x68'}}; // == 1/8 * crypto::c_point_H, checked in crypto_constants
|
||||
const static crypto::point_t native_coin_asset_id_pt {{ 20574939, 16670001, -29137604, 14614582, 24883426, 3503293, 2667523, 420631, 2267646, -4769165, -11764015, -12206428, -14187565, -2328122, -16242653, -788308, -12595746, -8251557, -10110987, 853396, -4982135, 6035602, -21214320, 16156349, 977218, 2807645, 31002271, 5694305, -16054128, 5644146, -15047429, -568775, -22568195, -8089957, -27721961, -10101877, -29459620, -13359100, -31515170, -6994674 }}; // c_point_H
|
||||
|
||||
const static wide_difficulty_type global_difficulty_pow_starter = DIFFICULTY_POW_STARTER;
|
||||
const static wide_difficulty_type global_difficulty_pos_starter = DIFFICULTY_POS_STARTER;
|
||||
const static uint64_t global_difficulty_pos_target = DIFFICULTY_POS_TARGET;
|
||||
const static uint64_t global_difficulty_pow_target = DIFFICULTY_POW_TARGET;
|
||||
|
||||
typedef std::string payment_id_t;
|
||||
|
||||
|
||||
|
|
@ -208,16 +222,21 @@ namespace currency
|
|||
|
||||
typedef boost::variant<signed_parts, extra_attachment_info> txin_etc_details_v;
|
||||
|
||||
struct txin_to_key
|
||||
|
||||
struct referring_input
|
||||
{
|
||||
std::vector<txout_ref_v> key_offsets;
|
||||
};
|
||||
|
||||
struct txin_to_key : public referring_input
|
||||
{
|
||||
uint64_t amount;
|
||||
std::vector<txout_ref_v> key_offsets;
|
||||
crypto::key_image k_image; // double spending protection
|
||||
std::vector<txin_etc_details_v> etc_details; //this flag used when TX_FLAG_SIGNATURE_MODE_SEPARATE flag is set, point to which amount of outputs(starting from zero) used in signature
|
||||
std::vector<txin_etc_details_v> etc_details; // see also TX_FLAG_SIGNATURE_MODE_SEPARATE
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
VARINT_FIELD(amount)
|
||||
FIELD(key_offsets)
|
||||
FIELD(key_offsets) // from referring_input
|
||||
FIELD(k_image)
|
||||
FIELD(etc_details)
|
||||
END_SERIALIZE()
|
||||
|
|
@ -247,6 +266,7 @@ namespace currency
|
|||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
|
||||
struct txout_multisig
|
||||
{
|
||||
uint32_t minimum_sigs;
|
||||
|
|
@ -277,12 +297,10 @@ namespace currency
|
|||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
typedef boost::variant<txin_gen, txin_to_key, txin_multisig, txin_htlc> txin_v;
|
||||
|
||||
typedef boost::variant<txout_to_key, txout_multisig, txout_htlc> txout_target_v;
|
||||
|
||||
//typedef std::pair<uint64_t, txout> out_t;
|
||||
struct tx_out
|
||||
struct tx_out_bare
|
||||
{
|
||||
uint64_t amount;
|
||||
txout_target_v target;
|
||||
|
|
@ -294,6 +312,192 @@ namespace currency
|
|||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Zarcanum structures
|
||||
//
|
||||
|
||||
struct txin_zc_input : public referring_input
|
||||
{
|
||||
txin_zc_input() {}
|
||||
// Boost's Assignable concept
|
||||
txin_zc_input(const txin_zc_input&) = default;
|
||||
txin_zc_input& operator=(const txin_zc_input&)= default;
|
||||
|
||||
crypto::key_image k_image;
|
||||
std::vector<txin_etc_details_v> etc_details;
|
||||
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(key_offsets) // referring_input
|
||||
FIELD(k_image)
|
||||
FIELD(etc_details)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(key_offsets) // referring_input
|
||||
BOOST_SERIALIZE(k_image)
|
||||
BOOST_SERIALIZE(etc_details)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct tx_out_zarcanum
|
||||
{
|
||||
tx_out_zarcanum() {}
|
||||
|
||||
// Boost's Assignable concept
|
||||
tx_out_zarcanum(const tx_out_zarcanum&) = default;
|
||||
tx_out_zarcanum& operator=(const tx_out_zarcanum&) = default;
|
||||
|
||||
crypto::public_key stealth_address;
|
||||
crypto::public_key concealing_point; // group element Q, see also Zarcanum paper, premultiplied by 1/8
|
||||
crypto::public_key amount_commitment; // premultiplied by 1/8
|
||||
crypto::public_key blinded_asset_id; // group element T, premultiplied by 1/8
|
||||
uint64_t encrypted_amount = 0;
|
||||
uint8_t mix_attr = 0;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(stealth_address)
|
||||
FIELD(concealing_point)
|
||||
FIELD(amount_commitment)
|
||||
FIELD(blinded_asset_id)
|
||||
FIELD(encrypted_amount)
|
||||
FIELD(mix_attr)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(stealth_address)
|
||||
BOOST_SERIALIZE(concealing_point)
|
||||
BOOST_SERIALIZE(amount_commitment)
|
||||
BOOST_SERIALIZE(blinded_asset_id)
|
||||
BOOST_SERIALIZE(encrypted_amount)
|
||||
BOOST_SERIALIZE(mix_attr)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct zarcanum_tx_data_v1
|
||||
{
|
||||
uint64_t fee;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(fee)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(fee)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct zc_asset_surjection_proof
|
||||
{
|
||||
std::vector<crypto::BGE_proof_s> bge_proofs; // one per output, non-aggregated version of Groth-Bootle-Esgin yet, need to be upgraded later -- sowle
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(bge_proofs)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(bge_proofs)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
// non-consoditated txs must have one of this objects in the attachments (elements count == vout.size())
|
||||
// consolidated -- one pre consolidated part (sum(elements count) == vout.size())
|
||||
struct zc_outs_range_proof
|
||||
{
|
||||
crypto::bpp_signature_serialized bpp; // for commitments in form: amount * U + mask * G
|
||||
crypto::vector_UG_aggregation_proof_serialized aggregation_proof; // E'_j = e_j * U + y'_j * G + vector Shnorr
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(bpp)
|
||||
FIELD(aggregation_proof)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(bpp)
|
||||
BOOST_SERIALIZE(aggregation_proof)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
// Zarcanum-aware CLSAG signature (one per ZC input)
|
||||
struct ZC_sig
|
||||
{
|
||||
crypto::public_key pseudo_out_amount_commitment = null_pkey; // premultiplied by 1/8
|
||||
crypto::public_key pseudo_out_blinded_asset_id = null_pkey; // premultiplied by 1/8
|
||||
crypto::CLSAG_GGX_signature_serialized clsags_ggx;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(pseudo_out_amount_commitment)
|
||||
FIELD(pseudo_out_blinded_asset_id)
|
||||
FIELD(clsags_ggx)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(pseudo_out_amount_commitment)
|
||||
BOOST_SERIALIZE(pseudo_out_blinded_asset_id)
|
||||
BOOST_SERIALIZE(clsags_ggx)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
// First part of a double Schnorr proof:
|
||||
// 1) for txs without ZC inputs: proves that balance point = lin(G) (cancels out G component of outputs' amount commitments, asset tags assumed to be H (native coin) and non-blinded)
|
||||
// 2) for txs with ZC inputs: proves that balance point = lin(X) (cancels out X component of blinded asset tags within amount commitments for both outputs and inputs (pseudo outs))
|
||||
// Second part:
|
||||
// proof of knowing transaction secret key (with respect to G)
|
||||
struct zc_balance_proof
|
||||
{
|
||||
crypto::generic_double_schnorr_sig_s dss;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(dss)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(dss)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
|
||||
struct zarcanum_sig : public crypto::zarcanum_proof
|
||||
{
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(d)
|
||||
FIELD(C)
|
||||
FIELD(C_prime);
|
||||
FIELD(E);
|
||||
FIELD(c);
|
||||
FIELD(y0);
|
||||
FIELD(y1);
|
||||
FIELD(y2);
|
||||
FIELD(y3);
|
||||
FIELD(y4);
|
||||
FIELD_N("E_range_proof", (crypto::bppe_signature_serialized&)E_range_proof);
|
||||
FIELD(pseudo_out_amount_commitment);
|
||||
FIELD_N("clsag_ggxxg", (crypto::CLSAG_GGXXG_signature_serialized&)clsag_ggxxg);
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(d)
|
||||
BOOST_SERIALIZE(C)
|
||||
BOOST_SERIALIZE(C_prime);
|
||||
BOOST_SERIALIZE(E);
|
||||
BOOST_SERIALIZE(c);
|
||||
BOOST_SERIALIZE(y0);
|
||||
BOOST_SERIALIZE(y1);
|
||||
BOOST_SERIALIZE(y2);
|
||||
BOOST_SERIALIZE(y3);
|
||||
BOOST_SERIALIZE(y4);
|
||||
BOOST_SERIALIZE((crypto::bppe_signature_serialized&)E_range_proof);
|
||||
BOOST_SERIALIZE(pseudo_out_amount_commitment);
|
||||
BOOST_SERIALIZE((crypto::CLSAG_GGXXG_signature_serialized&)clsag_ggxxg);
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
//#pragma pack(pop)
|
||||
|
||||
typedef boost::variant<txin_gen, txin_to_key, txin_multisig, txin_htlc, txin_zc_input> txin_v;
|
||||
|
||||
typedef boost::variant<tx_out_bare, tx_out_zarcanum> tx_out_v;
|
||||
|
||||
|
||||
struct tx_comment
|
||||
{
|
||||
|
|
@ -470,8 +674,7 @@ namespace currency
|
|||
extra_alias_entry(const extra_alias_entry_old& old)
|
||||
: extra_alias_entry_base(old)
|
||||
, m_alias(old.m_alias)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
std::string m_alias;
|
||||
|
||||
|
|
@ -493,6 +696,142 @@ namespace currency
|
|||
};
|
||||
|
||||
|
||||
struct asset_descriptor_base
|
||||
{
|
||||
uint64_t total_max_supply = 0;
|
||||
uint64_t current_supply = 0;
|
||||
uint8_t decimal_point = 12;
|
||||
std::string ticker;
|
||||
std::string full_name;
|
||||
std::string meta_info;
|
||||
crypto::public_key owner = currency::null_pkey; // consider premultipling by 1/8
|
||||
bool hidden_supply = false;
|
||||
uint8_t version = 0;
|
||||
|
||||
BEGIN_VERSIONED_SERIALIZE(0, version)
|
||||
FIELD(total_max_supply)
|
||||
FIELD(current_supply)
|
||||
FIELD(decimal_point)
|
||||
FIELD(ticker)
|
||||
FIELD(full_name)
|
||||
FIELD(meta_info)
|
||||
FIELD(owner)
|
||||
FIELD(hidden_supply)
|
||||
END_SERIALIZE()
|
||||
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(total_max_supply)
|
||||
BOOST_SERIALIZE(current_supply)
|
||||
BOOST_SERIALIZE(decimal_point)
|
||||
BOOST_SERIALIZE(ticker)
|
||||
BOOST_SERIALIZE(full_name)
|
||||
BOOST_SERIALIZE(meta_info)
|
||||
BOOST_SERIALIZE(owner)
|
||||
BOOST_SERIALIZE(hidden_supply)
|
||||
END_BOOST_SERIALIZATION()
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(total_max_supply)
|
||||
KV_SERIALIZE(current_supply)
|
||||
KV_SERIALIZE(decimal_point)
|
||||
KV_SERIALIZE(ticker)
|
||||
KV_SERIALIZE(full_name)
|
||||
KV_SERIALIZE(meta_info)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(owner)
|
||||
KV_SERIALIZE(hidden_supply)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct asset_descriptor_with_id: public asset_descriptor_base
|
||||
{
|
||||
crypto::public_key asset_id = currency::null_pkey;
|
||||
|
||||
/*
|
||||
BEGIN_VERSIONED_SERIALIZE()
|
||||
FIELD(*static_cast<asset_descriptor_base>(this))
|
||||
FIELD(asset_id)
|
||||
END_SERIALIZE()
|
||||
*/
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_CHAIN_BASE(asset_descriptor_base)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(asset_id)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
#define ASSET_DESCRIPTOR_OPERATION_UNDEFINED 0
|
||||
#define ASSET_DESCRIPTOR_OPERATION_REGISTER 1
|
||||
#define ASSET_DESCRIPTOR_OPERATION_EMIT 2
|
||||
#define ASSET_DESCRIPTOR_OPERATION_UPDATE 3
|
||||
#define ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN 4
|
||||
|
||||
#define ASSET_DESCRIPTOR_OPERATION_STRUCTURE_VER 1
|
||||
|
||||
struct asset_descriptor_operation
|
||||
{
|
||||
uint8_t operation_type = ASSET_DESCRIPTOR_OPERATION_UNDEFINED;
|
||||
asset_descriptor_base descriptor;
|
||||
crypto::public_key amount_commitment; // premultiplied by 1/8
|
||||
boost::optional<crypto::public_key> opt_asset_id; // target asset_id - for update/emit
|
||||
uint8_t verion = ASSET_DESCRIPTOR_OPERATION_STRUCTURE_VER;
|
||||
|
||||
BEGIN_VERSIONED_SERIALIZE(ASSET_DESCRIPTOR_OPERATION_STRUCTURE_VER, verion)
|
||||
FIELD(operation_type)
|
||||
FIELD(descriptor)
|
||||
FIELD(amount_commitment)
|
||||
END_VERSION_UNDER(1)
|
||||
FIELD(opt_asset_id)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(operation_type)
|
||||
BOOST_SERIALIZE(descriptor)
|
||||
BOOST_SERIALIZE(amount_commitment)
|
||||
BOOST_END_VERSION_UNDER(1)
|
||||
BOOST_SERIALIZE(opt_asset_id)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct asset_operation_proof
|
||||
{
|
||||
// linear composition proof for the fact amount_commitment = lin(asset_id, G)
|
||||
boost::optional<crypto::linear_composition_proof_s> opt_amount_commitment_composition_proof; // for hidden supply
|
||||
boost::optional<crypto::signature> opt_amount_commitment_g_proof; // for non-hidden supply, proofs that amount_commitment - supply * asset_id = lin(G)
|
||||
uint8_t version = 0;
|
||||
|
||||
BEGIN_VERSIONED_SERIALIZE(0, version)
|
||||
FIELD(opt_amount_commitment_composition_proof)
|
||||
FIELD(opt_amount_commitment_g_proof)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(opt_amount_commitment_composition_proof)
|
||||
BOOST_SERIALIZE(opt_amount_commitment_g_proof)
|
||||
BOOST_END_VERSION_UNDER(1)
|
||||
BOOST_SERIALIZE(version)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
|
||||
struct asset_operation_ownership_proof
|
||||
{
|
||||
crypto::generic_schnorr_sig_s gss;
|
||||
uint8_t version = 0;
|
||||
|
||||
BEGIN_VERSIONED_SERIALIZE(0, version)
|
||||
FIELD(gss)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(gss)
|
||||
BOOST_END_VERSION_UNDER(1)
|
||||
BOOST_SERIALIZE(version)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
|
||||
struct extra_padding
|
||||
{
|
||||
|
|
@ -558,10 +897,10 @@ namespace currency
|
|||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
typedef boost::mpl::vector21<
|
||||
typedef boost::mpl::vector23<
|
||||
tx_service_attachment, tx_comment, tx_payer_old, tx_receiver_old, tx_derivation_hint, std::string, tx_crypto_checksum, etc_tx_time, etc_tx_details_unlock_time, etc_tx_details_expiration_time,
|
||||
etc_tx_details_flags, crypto::public_key, extra_attachment_info, extra_alias_entry_old, extra_user_data, extra_padding, etc_tx_flags16_t, etc_tx_details_unlock_time2,
|
||||
tx_payer, tx_receiver, extra_alias_entry
|
||||
tx_payer, tx_receiver, extra_alias_entry, zarcanum_tx_data_v1, asset_descriptor_operation
|
||||
> all_payload_types;
|
||||
|
||||
typedef boost::make_variant_over<all_payload_types>::type payload_items_v;
|
||||
|
|
@ -569,26 +908,57 @@ namespace currency
|
|||
typedef payload_items_v attachment_v;
|
||||
|
||||
|
||||
|
||||
|
||||
//classic CryptoNote signature by Nicolas Van Saberhagen
|
||||
struct NLSAG_sig
|
||||
{
|
||||
std::vector<crypto::signature> s;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(s)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(s)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct void_sig
|
||||
{
|
||||
//TODO:
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
typedef boost::variant<NLSAG_sig, void_sig, ZC_sig, zarcanum_sig> signature_v;
|
||||
|
||||
typedef boost::variant<zc_asset_surjection_proof, zc_outs_range_proof, zc_balance_proof, asset_operation_proof, asset_operation_ownership_proof> proof_v;
|
||||
|
||||
|
||||
//include backward compatibility defintions
|
||||
#include "currency_basic_backward_comp.inl"
|
||||
|
||||
class transaction_prefix
|
||||
{
|
||||
public:
|
||||
// tx version information
|
||||
uint64_t version{};
|
||||
//extra
|
||||
std::vector<extra_v> extra;
|
||||
uint64_t version = 0;
|
||||
std::vector<txin_v> vin;
|
||||
std::vector<tx_out> vout;
|
||||
std::vector<extra_v> extra;
|
||||
std::vector<tx_out_v> vout;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
VARINT_FIELD(version)
|
||||
CHAIN_TRANSITION_VER(TRANSACTION_VERSION_INITAL, transaction_prefix_v1)
|
||||
CHAIN_TRANSITION_VER(TRANSACTION_VERSION_PRE_HF4, transaction_prefix_v1)
|
||||
if(CURRENT_TRANSACTION_VERSION < version) return false;
|
||||
FIELD(vin)
|
||||
FIELD(vout)
|
||||
FIELD(extra)
|
||||
FIELD(vout)
|
||||
END_SERIALIZE()
|
||||
|
||||
protected:
|
||||
transaction_prefix(){}
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -604,55 +974,23 @@ namespace currency
|
|||
class transaction: public transaction_prefix
|
||||
{
|
||||
public:
|
||||
std::vector<std::vector<crypto::signature> > signatures; //count signatures always the same as inputs count
|
||||
std::vector<attachment_v> attachment;
|
||||
|
||||
transaction();
|
||||
std::vector<signature_v> signatures;
|
||||
std::vector<proof_v> proofs;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELDS(*static_cast<transaction_prefix *>(this))
|
||||
FIELD(signatures)
|
||||
CHAIN_TRANSITION_VER(TRANSACTION_VERSION_INITAL, transaction_v1)
|
||||
CHAIN_TRANSITION_VER(TRANSACTION_VERSION_PRE_HF4, transaction_v1)
|
||||
FIELD(attachment)
|
||||
FIELD(signatures)
|
||||
FIELD(proofs)
|
||||
END_SERIALIZE()
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
inline
|
||||
transaction::transaction()
|
||||
{
|
||||
version = 0;
|
||||
vin.clear();
|
||||
vout.clear();
|
||||
extra.clear();
|
||||
signatures.clear();
|
||||
attachment.clear();
|
||||
|
||||
}
|
||||
/*
|
||||
inline
|
||||
transaction::~transaction()
|
||||
{
|
||||
//set_null();
|
||||
}
|
||||
|
||||
inline
|
||||
void transaction::set_null()
|
||||
{
|
||||
version = 0;
|
||||
unlock_time = 0;
|
||||
vin.clear();
|
||||
vout.clear();
|
||||
extra.clear();
|
||||
signatures.clear();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
|
|
@ -714,8 +1052,6 @@ namespace currency
|
|||
*/
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct stake_modifier_type
|
||||
{
|
||||
|
|
@ -725,7 +1061,6 @@ namespace currency
|
|||
|
||||
struct stake_kernel
|
||||
{
|
||||
|
||||
stake_modifier_type stake_modifier;
|
||||
uint64_t block_timestamp; //this block timestamp
|
||||
crypto::key_image kimage;
|
||||
|
|
@ -735,22 +1070,45 @@ namespace currency
|
|||
struct pos_entry
|
||||
{
|
||||
uint64_t amount;
|
||||
uint64_t index;
|
||||
uint64_t g_index; // global output index. (could be WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED)
|
||||
crypto::key_image keyimage;
|
||||
uint64_t block_timestamp;
|
||||
uint64_t stake_unlock_time;
|
||||
|
||||
crypto::hash tx_id; // stake output source tx id
|
||||
uint64_t tx_out_index; // stake output local index in its tx
|
||||
|
||||
//not for serialization
|
||||
uint64_t wallet_index;
|
||||
|
||||
uint64_t wallet_index; // transfer id index
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(amount)
|
||||
KV_SERIALIZE(index)
|
||||
KV_SERIALIZE(g_index)
|
||||
KV_SERIALIZE(stake_unlock_time)
|
||||
KV_SERIALIZE(block_timestamp)
|
||||
KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(keyimage)
|
||||
KV_SERIALIZE(tx_id)
|
||||
KV_SERIALIZE(tx_out_index)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
bool operator ==(const currency::transaction& a, const currency::transaction& b);
|
||||
bool operator ==(const currency::block& a, const currency::block& b);
|
||||
bool operator ==(const currency::extra_attachment_info& a, const currency::extra_attachment_info& b);
|
||||
bool operator ==(const currency::NLSAG_sig& a, const currency::NLSAG_sig& b);
|
||||
bool operator ==(const currency::void_sig& a, const currency::void_sig& b);
|
||||
bool operator ==(const currency::ZC_sig& a, const currency::ZC_sig& b);
|
||||
bool operator ==(const currency::zarcanum_sig& a, const currency::zarcanum_sig& b);
|
||||
bool operator ==(const currency::ref_by_id& a, const currency::ref_by_id& b);
|
||||
|
||||
// TODO: REPLACE all of the following operators to "bool operator==(..) const = default" once we moved to C++20 -- sowle
|
||||
bool operator ==(const currency::signed_parts& a, const currency::signed_parts& b);
|
||||
bool operator ==(const currency::txin_gen& a, const currency::txin_gen& b);
|
||||
bool operator ==(const currency::txin_to_key& a, const currency::txin_to_key& b);
|
||||
bool operator ==(const currency::txin_multisig& a, const currency::txin_multisig& b);
|
||||
bool operator ==(const currency::txin_htlc& a, const currency::txin_htlc& b);
|
||||
bool operator ==(const currency::txin_zc_input& a, const currency::txin_zc_input& b);
|
||||
} // namespace currency
|
||||
|
||||
POD_MAKE_HASHABLE(currency, account_public_address);
|
||||
|
|
@ -763,6 +1121,10 @@ BLOB_SERIALIZER(currency::txout_to_key);
|
|||
VARIANT_TAG(json_archive, type_name, json_tag)
|
||||
|
||||
|
||||
BOOST_CLASS_VERSION(currency::asset_descriptor_operation, 1);
|
||||
BOOST_CLASS_VERSION(currency::asset_operation_proof, 1);
|
||||
BOOST_CLASS_VERSION(currency::asset_operation_ownership_proof, 1);
|
||||
|
||||
|
||||
// txin_v variant currency
|
||||
SET_VARIANT_TAGS(currency::txin_gen, 0, "gen");
|
||||
|
|
@ -814,6 +1176,27 @@ SET_VARIANT_TAGS(currency::extra_alias_entry, 33, "alias_entry2");
|
|||
SET_VARIANT_TAGS(currency::txin_htlc, 34, "txin_htlc");
|
||||
SET_VARIANT_TAGS(currency::txout_htlc, 35, "txout_htlc");
|
||||
|
||||
SET_VARIANT_TAGS(currency::tx_out_bare, 36, "tx_out_bare");
|
||||
|
||||
// Zarcanum
|
||||
SET_VARIANT_TAGS(currency::txin_zc_input, 37, "txin_zc_input");
|
||||
SET_VARIANT_TAGS(currency::tx_out_zarcanum, 38, "tx_out_zarcanum");
|
||||
SET_VARIANT_TAGS(currency::zarcanum_tx_data_v1, 39, "zarcanum_tx_data_v1");
|
||||
SET_VARIANT_TAGS(crypto::bpp_signature_serialized, 40, "bpp_signature_serialized");
|
||||
SET_VARIANT_TAGS(crypto::bppe_signature_serialized, 41, "bppe_signature_serialized");
|
||||
SET_VARIANT_TAGS(currency::NLSAG_sig, 42, "NLSAG_sig");
|
||||
SET_VARIANT_TAGS(currency::ZC_sig, 43, "ZC_sig");
|
||||
SET_VARIANT_TAGS(currency::void_sig, 44, "void_sig");
|
||||
SET_VARIANT_TAGS(currency::zarcanum_sig, 45, "zarcanum_sig");
|
||||
SET_VARIANT_TAGS(currency::zc_asset_surjection_proof, 46, "zc_asset_surjection_proof");
|
||||
SET_VARIANT_TAGS(currency::zc_outs_range_proof, 47, "zc_outs_range_proof");
|
||||
SET_VARIANT_TAGS(currency::zc_balance_proof, 48, "zc_balance_proof");
|
||||
|
||||
SET_VARIANT_TAGS(currency::asset_descriptor_operation, 49, "asset_descriptor_base");
|
||||
SET_VARIANT_TAGS(currency::asset_operation_proof, 50, "asset_operation_proof");
|
||||
SET_VARIANT_TAGS(currency::asset_operation_ownership_proof, 51, "asset_operation_ownership_proof");
|
||||
|
||||
|
||||
|
||||
|
||||
#undef SET_VARIANT_TAGS
|
||||
|
|
|
|||
118
src/currency_core/currency_basic_backward_comp.inl
Normal file
118
src/currency_core/currency_basic_backward_comp.inl
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
// Copyright (c) 2014-2022 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
||||
|
||||
class transaction_prefix_v1
|
||||
{
|
||||
public:
|
||||
// tx version information
|
||||
uint64_t version{};
|
||||
//extra
|
||||
std::vector<extra_v> extra;
|
||||
std::vector<txin_v> vin;
|
||||
std::vector<tx_out_bare> vout;//std::vector<tx_out> vout;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
//VARINT_FIELD(version) <-- this already unserialized
|
||||
if (TRANSACTION_VERSION_PRE_HF4 < version) return false;
|
||||
FIELD(vin)
|
||||
FIELD(vout)
|
||||
FIELD(extra)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
/*
|
||||
class transaction_prefix_v1_full
|
||||
{
|
||||
public:
|
||||
// tx version information
|
||||
uint64_t version{};
|
||||
//extra
|
||||
std::vector<extra_v> extra;
|
||||
std::vector<txin_v> vin;
|
||||
std::vector<tx_out_old> vout;//std::vector<tx_out> vout;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
VARINT_FIELD(version)
|
||||
if (TRANSACTION_VERSION_PRE_HF4 < version) return false;
|
||||
FIELD(vin)
|
||||
FIELD(vout)
|
||||
FIELD(extra)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
*/
|
||||
|
||||
template<typename transaction_prefix_current_t>
|
||||
bool transition_convert(const transaction_prefix_current_t& from, transaction_prefix_v1& to)
|
||||
{
|
||||
to.extra = from.extra;
|
||||
to.vin = from.vin;
|
||||
for (const auto& v : from.vout)
|
||||
{
|
||||
if (v.type() == typeid(tx_out_bare))
|
||||
{
|
||||
to.vout.push_back(boost::get<tx_out_bare>(v));
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error("Unexpected type in tx_out_v");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
template<typename transaction_prefix_current_t>
|
||||
bool transition_convert(const transaction_prefix_v1& from, transaction_prefix_current_t& to)
|
||||
{
|
||||
to.extra = from.extra;
|
||||
to.vin = from.vin;
|
||||
for (const auto& v : from.vout)
|
||||
{
|
||||
to.vout.push_back(v);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class transaction_v1
|
||||
{
|
||||
public:
|
||||
std::vector<std::vector<crypto::signature> > signatures; //count signatures always the same as inputs count
|
||||
std::vector<attachment_v> attachment;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(signatures)
|
||||
FIELD(attachment)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
template<typename transaction_current_t>
|
||||
bool transition_convert(const transaction_current_t& from, transaction_v1& to)
|
||||
{
|
||||
to.attachment = from.attachment;
|
||||
for (const auto& s : from.signatures)
|
||||
{
|
||||
if (s.type() == typeid(NLSAG_sig))
|
||||
{
|
||||
to.signatures.push_back(boost::get<NLSAG_sig>(s).s);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(std::string("Unexpected type in tx.signatures during transition_convert: ") + s.type().name());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename transaction_current_t>
|
||||
bool transition_convert(const transaction_v1& from, transaction_current_t& to)
|
||||
{
|
||||
// TODO: consider using move semantic for 'from'
|
||||
to.attachment = from.attachment;
|
||||
to.signatures.resize(from.signatures.size());
|
||||
for (size_t i = 0; i != from.signatures.size(); i++)
|
||||
{
|
||||
boost::get<NLSAG_sig>(to.signatures[i]).s = from.signatures[i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
#include <boost/serialization/is_bitwise_serializable.hpp>
|
||||
#include "currency_basic.h"
|
||||
#include "common/unordered_containers_boost_serialization.h"
|
||||
#include "common/crypto_boost_serialization.h"
|
||||
#include "common/crypto_serialization.h"
|
||||
#include "offers_services_helpers.h"
|
||||
|
||||
#define CURRENT_BLOCK_ARCHIVE_VER 2
|
||||
|
|
@ -104,13 +104,22 @@ namespace boost
|
|||
}
|
||||
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, currency::tx_out &x, const boost::serialization::version_type ver)
|
||||
inline void serialize(Archive &a, currency::tx_out_bare &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & x.amount;
|
||||
a & x.target;
|
||||
}
|
||||
|
||||
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, currency::tx_out_zarcanum &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & x.stealth_address;
|
||||
a & x.concealing_point;
|
||||
a & x.amount_commitment;
|
||||
a & x.blinded_asset_id;
|
||||
a & x.encrypted_amount;
|
||||
a & x.mix_attr;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, currency::tx_comment &x, const boost::serialization::version_type ver)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2019 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
#ifndef TESTNET
|
||||
#define CURRENCY_FORMATION_VERSION 84
|
||||
#else
|
||||
#define CURRENCY_FORMATION_VERSION 88
|
||||
#define CURRENCY_FORMATION_VERSION 97
|
||||
#endif
|
||||
|
||||
#define CURRENCY_GENESIS_NONCE (CURRENCY_FORMATION_VERSION + 101011010121) //bender's nightmare
|
||||
|
|
@ -20,15 +20,25 @@
|
|||
#define CURRENCY_MAX_BLOCK_NUMBER 500000000
|
||||
#define CURRENCY_MAX_BLOCK_SIZE 500000000 // block header blob limit, never used!
|
||||
#define CURRENCY_TX_MAX_ALLOWED_OUTS 2000
|
||||
#define CURRENCY_TX_MIN_ALLOWED_OUTS 2 // effective starting HF4 Zarcanum
|
||||
#define CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX 0xc5 // addresses start with 'Zx'
|
||||
#define CURRENCY_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX 0x3678 // integrated addresses start with 'iZ'
|
||||
#define CURRENCY_PUBLIC_INTEG_ADDRESS_V2_BASE58_PREFIX 0x36f8 // integrated addresses start with 'iZ' (new format)
|
||||
#define CURRENCY_PUBLIC_AUDITABLE_ADDRESS_BASE58_PREFIX 0x98c8 // auditable addresses start with 'aZx'
|
||||
#define CURRENCY_PUBLIC_AUDITABLE_INTEG_ADDRESS_BASE58_PREFIX 0x8a49 // auditable integrated addresses start with 'aiZX'
|
||||
#define CURRENCY_MINED_MONEY_UNLOCK_WINDOW 10
|
||||
#define CURRENT_TRANSACTION_VERSION 1
|
||||
#define CURRENT_TRANSACTION_VERSION 2
|
||||
#define TRANSACTION_VERSION_INITAL 0
|
||||
#define TRANSACTION_VERSION_PRE_HF4 1
|
||||
#define TRANSACTION_VERSION_POST_HF4 2
|
||||
#define HF1_BLOCK_MAJOR_VERSION 1
|
||||
#define CURRENT_BLOCK_MAJOR_VERSION 2
|
||||
#define HF3_BLOCK_MAJOR_VERSION 2
|
||||
#define HF3_BLOCK_MINOR_VERSION 0
|
||||
#define CURRENT_BLOCK_MAJOR_VERSION 3
|
||||
|
||||
#define CURRENCY_DEFAULT_DECOY_SET_SIZE 10
|
||||
#define CURRENCY_HF4_MANDATORY_DECOY_SET_SIZE 15
|
||||
#define CURRENCY_HF4_MANDATORY_MIN_COINAGE 10
|
||||
|
||||
#define CURRENT_BLOCK_MINOR_VERSION 0
|
||||
#define CURRENCY_BLOCK_FUTURE_TIME_LIMIT 60*60*2
|
||||
|
|
@ -58,8 +68,9 @@
|
|||
|
||||
#define WALLET_MAX_ALLOWED_OUTPUT_AMOUNT ((uint64_t)0xffffffffffffffffLL)
|
||||
#define CURRENCY_MINER_TX_MAX_OUTS CURRENCY_TX_MAX_ALLOWED_OUTS
|
||||
#define CURRENCY_TX_OUTS_RND_SPLIT_DIGITS_TO_KEEP 3
|
||||
|
||||
#define DIFFICULTY_STARTER 1
|
||||
#define DIFFICULTY_POW_STARTER 1
|
||||
#define DIFFICULTY_POS_TARGET 120 // seconds
|
||||
#define DIFFICULTY_POW_TARGET 120 // seconds
|
||||
#define DIFFICULTY_TOTAL_TARGET ((DIFFICULTY_POS_TARGET + DIFFICULTY_POW_TARGET) / 4)
|
||||
|
|
@ -104,6 +115,7 @@
|
|||
#define STRATUM_DEFAULT_PORT 11777
|
||||
#define P2P_NETWORK_ID_TESTNET_FLAG 0
|
||||
#define P2P_MAINTAINERS_PUB_KEY "8f138bb73f6d663a3746a542770781a09579a7b84cb4125249e95530824ee607"
|
||||
#define DIFFICULTY_POS_STARTER 1
|
||||
#else
|
||||
#define P2P_DEFAULT_PORT (11112 + CURRENCY_FORMATION_VERSION)
|
||||
#define RPC_DEFAULT_PORT 12111
|
||||
|
|
@ -111,6 +123,7 @@
|
|||
#define STRARUM_DEFAULT_PORT 51113
|
||||
#define P2P_NETWORK_ID_TESTNET_FLAG 1
|
||||
#define P2P_MAINTAINERS_PUB_KEY "aaa2d7aabc8d383fd53a3ae898697b28f236ceade6bafc1eecff413a6a02272a"
|
||||
#define DIFFICULTY_POS_STARTER 1
|
||||
#endif
|
||||
|
||||
#define P2P_NETWORK_ID_VER (CURRENCY_FORMATION_VERSION+0)
|
||||
|
|
@ -145,6 +158,15 @@
|
|||
#define POS_WALLET_MINING_SCAN_INTERVAL POS_SCAN_STEP //seconds
|
||||
#define POS_MINIMUM_COINSTAKE_AGE 10 // blocks count
|
||||
|
||||
#ifndef TESTNET
|
||||
# define BLOCKCHAIN_HEIGHT_FOR_POS_STRICT_SEQUENCE_LIMITATION 57000
|
||||
#else
|
||||
# define BLOCKCHAIN_HEIGHT_FOR_POS_STRICT_SEQUENCE_LIMITATION 18000
|
||||
#endif
|
||||
#define BLOCK_POS_STRICT_SEQUENCE_LIMIT 20 // the highest allowed sequence factor for a PoS block (i.e., the max total number of sequential PoS blocks is BLOCK_POS_STRICT_SEQUENCE_LIMIT + 1)
|
||||
|
||||
|
||||
#define CORE_FEE_BLOCKS_LOOKUP_WINDOW 60 //number of blocks used to check if transaction flow is big enought to rise default fee
|
||||
|
||||
#define WALLET_FILE_SIGNATURE_OLD 0x1111012101101011LL // Bender's nightmare
|
||||
#define WALLET_FILE_SIGNATURE_V2 0x1111011201101011LL // another Bender's nightmare
|
||||
|
|
@ -205,7 +227,7 @@
|
|||
#define CURRENCY_POOLDATA_FOLDERNAME_PREFIX "poolstate_"
|
||||
#define CURRENCY_POOLDATA_FOLDERNAME_SUFFIX "_v1"
|
||||
#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME_PREFIX "blockchain_"
|
||||
#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME_SUFFIX "_v1"
|
||||
#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME_SUFFIX "_v2"
|
||||
|
||||
#define P2P_NET_DATA_FILENAME "p2pstate.bin"
|
||||
#define MINER_CONFIG_FILENAME "miner_conf.json"
|
||||
|
|
@ -214,6 +236,7 @@
|
|||
#define GUI_INTERNAL_CONFIG2 "gui_internal_config.json"
|
||||
#define GUI_IPC_MESSAGE_CHANNEL_NAME CURRENCY_NAME_BASE "_message_que"
|
||||
|
||||
#define CURRENCY_VOTING_CONFIG_DEFAULT_FILENAME "voting_config.json"
|
||||
|
||||
|
||||
#define CURRENT_TRANSACTION_CHAIN_ENTRY_ARCHIVE_VER 3
|
||||
|
|
@ -227,9 +250,11 @@
|
|||
#define BC_OFFERS_CURRENCY_MARKET_FILENAME "market.bin"
|
||||
|
||||
#ifndef TESTNET
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION 153
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION 162
|
||||
#define WALLET_FILE_LAST_SUPPORTED_VERSION 162
|
||||
#else
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION (CURRENCY_FORMATION_VERSION+69)
|
||||
#define WALLET_FILE_LAST_SUPPORTED_VERSION (CURRENCY_FORMATION_VERSION+76)
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION (CURRENCY_FORMATION_VERSION+76)
|
||||
#endif
|
||||
|
||||
#define CURRENT_MEMPOOL_ARCHIVE_VER (CURRENCY_FORMATION_VERSION+31)
|
||||
|
|
@ -239,19 +264,39 @@
|
|||
#define BLOCK_MINOR_VERSION_GENESIS 0
|
||||
#define BLOCK_MAJOR_VERSION_INITIAL 0
|
||||
#ifndef TESTNET
|
||||
#define ZANO_HARDFORK_01_AFTER_HEIGHT 194624
|
||||
#define ZANO_HARDFORK_02_AFTER_HEIGHT 999999
|
||||
#define ZANO_HARDFORK_03_AFTER_HEIGHT 1082577
|
||||
#define ZANO_HARDFORK_01_AFTER_HEIGHT 194624 // 2019-09-21 20:25:16
|
||||
#define ZANO_HARDFORK_02_AFTER_HEIGHT 999999 // 2021-04-05 09:11:45
|
||||
#define ZANO_HARDFORK_03_AFTER_HEIGHT 1082577 // 2021-06-01 23:28:10
|
||||
#define ZANO_HARDFORK_04_AFTER_HEIGHT 2555000 // 2024-03-21 10:16:46 (expected)
|
||||
#else
|
||||
#define ZANO_HARDFORK_01_AFTER_HEIGHT 1440
|
||||
#define ZANO_HARDFORK_02_AFTER_HEIGHT 1800
|
||||
#define ZANO_HARDFORK_03_AFTER_HEIGHT 1801
|
||||
/////// Zarcanum Testnet //////////////////////////////
|
||||
#define ZANO_HARDFORK_01_AFTER_HEIGHT 0
|
||||
#define ZANO_HARDFORK_02_AFTER_HEIGHT 0
|
||||
#define ZANO_HARDFORK_03_AFTER_HEIGHT 0
|
||||
#define ZANO_HARDFORK_04_AFTER_HEIGHT 2440
|
||||
#endif
|
||||
|
||||
|
||||
#define ZANO_HARDFORK_00_INITAL 0
|
||||
#define ZANO_HARDFORK_01 1
|
||||
#define ZANO_HARDFORK_02 2
|
||||
#define ZANO_HARDFORK_03 3
|
||||
#define ZANO_HARDFORK_04_ZARCANUM 4
|
||||
#define ZANO_HARDFORKS_TOTAL 5
|
||||
|
||||
|
||||
|
||||
|
||||
static_assert(CURRENCY_MINER_TX_MAX_OUTS <= CURRENCY_TX_MAX_ALLOWED_OUTS, "Miner tx must obey normal tx max outs limit");
|
||||
static_assert(PREMINE_AMOUNT / WALLET_MAX_ALLOWED_OUTPUT_AMOUNT < CURRENCY_MINER_TX_MAX_OUTS, "Premine can't be divided into reasonable number of outs");
|
||||
|
||||
#define CURRENCY_RELAY_TXS_MAX_COUNT 5
|
||||
#define CURRENCY_RELAY_TXS_MAX_COUNT 5
|
||||
|
||||
#ifndef TESTNET
|
||||
#define WALLET_ASSETS_WHITELIST_URL "https://api.zano.org/assets_whitelist.json"
|
||||
#else
|
||||
#define WALLET_ASSETS_WHITELIST_URL "https://api.zano.org/assets_whitelist_testnet.json"
|
||||
#endif
|
||||
|
||||
|
||||
#define WALLET_ASSETS_WHITELIST_VALIDATION_PUBLIC_KEY "" //TODO@#@
|
||||
|
|
@ -76,7 +76,10 @@ namespace currency
|
|||
bool core::handle_command_line(const boost::program_options::variables_map& vm)
|
||||
{
|
||||
m_config_folder = command_line::get_arg(vm, command_line::arg_data_dir);
|
||||
m_stop_after_height = static_cast<uint64_t>(command_line::get_arg(vm, command_line::arg_stop_after_height));
|
||||
m_stop_after_height = 0;
|
||||
if(command_line::has_arg(vm, command_line::arg_stop_after_height))
|
||||
m_stop_after_height = static_cast<uint64_t>(command_line::get_arg(vm, command_line::arg_stop_after_height));
|
||||
|
||||
if (m_stop_after_height != 0)
|
||||
{
|
||||
LOG_PRINT_YELLOW("Daemon will STOP after block " << m_stop_after_height, LOG_LEVEL_0);
|
||||
|
|
@ -89,6 +92,11 @@ namespace currency
|
|||
return m_blockchain_storage.get_current_blockchain_size();
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
uint64_t core::get_current_tx_version() const
|
||||
{
|
||||
return get_tx_version(m_blockchain_storage.get_current_blockchain_size(), m_blockchain_storage.get_core_runtime_config().hard_forks);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
uint64_t core::get_top_block_height() const
|
||||
{
|
||||
return m_blockchain_storage.get_top_block_height();
|
||||
|
|
@ -350,7 +358,7 @@ namespace currency
|
|||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::get_block_template(block& b, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos, const pos_entry& pe)
|
||||
{
|
||||
return m_blockchain_storage.create_block_template(b, adr, stakeholder_address, diffic, height, ex_nonce, pos, pe);
|
||||
return m_blockchain_storage.create_block_template(adr, stakeholder_address, ex_nonce, pos, pe, nullptr, b, diffic, height);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::get_block_template(const create_block_template_params& params, create_block_template_response& resp)
|
||||
|
|
@ -511,12 +519,25 @@ namespace currency
|
|||
bool r = m_blockchain_storage.add_new_block(b, bvc);
|
||||
if (r && bvc.m_added_to_main_chain)
|
||||
{
|
||||
h = get_block_height(b);
|
||||
auto& crc = m_blockchain_storage.get_core_runtime_config();
|
||||
if (h == crc.hard_fork_01_starts_after_height + 1)
|
||||
{ LOG_PRINT_GREEN("Hardfork 1 activated at height " << h, LOG_LEVEL_0); }
|
||||
else if (h == crc.hard_fork_02_starts_after_height + 1)
|
||||
{ LOG_PRINT_GREEN("Hardfork 2 activated at height " << h, LOG_LEVEL_0); }
|
||||
uint64_t h = get_block_height(b);
|
||||
if (h > 0)
|
||||
{
|
||||
auto& crc = m_blockchain_storage.get_core_runtime_config();
|
||||
size_t hardfork_id_for_prev_block = crc.hard_forks.get_the_most_recent_hardfork_id_for_height(h);
|
||||
size_t hardfork_id_for_curr_block = crc.hard_forks.get_the_most_recent_hardfork_id_for_height(h + 1);
|
||||
if (hardfork_id_for_prev_block != hardfork_id_for_curr_block)
|
||||
{
|
||||
LOG_PRINT_GREEN("Hardfork " << hardfork_id_for_curr_block << " has been activated after the block at height " << h, LOG_LEVEL_0);
|
||||
}
|
||||
}
|
||||
|
||||
if (h == m_stop_after_height)
|
||||
{
|
||||
LOG_PRINT_YELLOW("Reached block " << h << ", the daemon will now stop as requested", LOG_LEVEL_0);
|
||||
if (m_critical_error_handler)
|
||||
return m_critical_error_handler->on_immediate_stop_requested();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ namespace currency
|
|||
bool set_genesis_block(const block& b);
|
||||
bool deinit();
|
||||
uint64_t get_current_blockchain_size() const;
|
||||
uint64_t get_current_tx_version() const;
|
||||
uint64_t get_top_block_height() const;
|
||||
std::string get_config_folder();
|
||||
bool get_blockchain_top(uint64_t& heeight, crypto::hash& top_id) const;
|
||||
|
|
@ -139,18 +140,18 @@ namespace currency
|
|||
tx_memory_pool m_mempool;
|
||||
i_currency_protocol* m_pprotocol;
|
||||
i_critical_error_handler* m_critical_error_handler;
|
||||
critical_section m_incoming_tx_lock;
|
||||
epee::critical_section m_incoming_tx_lock;
|
||||
miner m_miner;
|
||||
account_public_address m_miner_address;
|
||||
std::string m_config_folder;
|
||||
uint64_t m_stop_after_height;
|
||||
currency_protocol_stub m_protocol_stub;
|
||||
math_helper::once_a_time_seconds<60*60*12, false> m_prune_alt_blocks_interval;
|
||||
math_helper::once_a_time_seconds<60, true> m_check_free_space_interval;
|
||||
epee::math_helper::once_a_time_seconds<60*60*12, false> m_prune_alt_blocks_interval;
|
||||
epee::math_helper::once_a_time_seconds<60, true> m_check_free_space_interval;
|
||||
friend class tx_validate_inputs;
|
||||
std::atomic<bool> m_starter_message_showed;
|
||||
|
||||
critical_section m_blockchain_update_listeners_lock;
|
||||
epee::critical_section m_blockchain_update_listeners_lock;
|
||||
std::vector<i_blockchain_update_listener*> m_blockchain_update_listeners;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2018 Zano Project
|
||||
// Copyright (c) 2014-2023 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Copyright (c) 2012-2013 The Boolberry developers
|
||||
|
|
@ -29,6 +29,9 @@
|
|||
#include "currency_format_utils_transactions.h"
|
||||
#include "core_runtime_config.h"
|
||||
#include "wallet/wallet_public_structs_defs.h"
|
||||
#include "bc_attachments_helpers.h"
|
||||
#include "bc_payments_id_service.h"
|
||||
#include "bc_offers_service_basic.h"
|
||||
|
||||
|
||||
// ------ get_tx_type_definition -------------
|
||||
|
|
@ -53,11 +56,6 @@
|
|||
|
||||
namespace currency
|
||||
{
|
||||
bool operator ==(const currency::transaction& a, const currency::transaction& b);
|
||||
bool operator ==(const currency::block& a, const currency::block& b);
|
||||
bool operator ==(const currency::extra_attachment_info& a, const currency::extra_attachment_info& b);
|
||||
|
||||
|
||||
typedef boost::multiprecision::uint128_t uint128_tl;
|
||||
|
||||
|
||||
|
|
@ -68,6 +66,7 @@ namespace currency
|
|||
extra_alias_entry m_alias;
|
||||
std::string m_user_data_blob;
|
||||
extra_attachment_info m_attachment_info;
|
||||
asset_descriptor_operation m_asset_operation;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
|
|
@ -135,11 +134,15 @@ namespace currency
|
|||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct htlc_info
|
||||
{
|
||||
bool hltc_our_out_is_before_expiration;
|
||||
};
|
||||
struct htlc_info
|
||||
{
|
||||
bool hltc_our_out_is_before_expiration;
|
||||
};
|
||||
|
||||
struct thirdparty_sign_handler
|
||||
{
|
||||
virtual bool sign(const crypto::hash& h, const crypto::public_key& owner_public_key, crypto::generic_schnorr_sig& sig);
|
||||
};
|
||||
|
||||
struct finalize_tx_param
|
||||
{
|
||||
|
|
@ -156,6 +159,17 @@ namespace currency
|
|||
std::vector<currency::tx_destination_entry> prepared_destinations;
|
||||
uint64_t expiration_time;
|
||||
crypto::public_key spend_pub_key; // only for validations
|
||||
uint64_t tx_version;
|
||||
uint64_t mode_separate_fee = 0;
|
||||
|
||||
epee::misc_utils::events_dispatcher* pevents_dispatcher;
|
||||
tx_generation_context gen_context{}; // solely for consolidated txs
|
||||
|
||||
//crypto::secret_key asset_control_key = currency::null_skey;
|
||||
crypto::public_key ado_current_asset_owner = null_pkey;
|
||||
thirdparty_sign_handler* pthirdparty_sign_handler = nullptr;
|
||||
mutable bool need_to_generate_ado_proof = false;
|
||||
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(unlock_time)
|
||||
|
|
@ -171,6 +185,14 @@ namespace currency
|
|||
FIELD(prepared_destinations)
|
||||
FIELD(expiration_time)
|
||||
FIELD(spend_pub_key)
|
||||
FIELD(tx_version)
|
||||
FIELD(mode_separate_fee)
|
||||
if (flags & TX_FLAG_SIGNATURE_MODE_SEPARATE)
|
||||
{
|
||||
FIELD(gen_context);
|
||||
}
|
||||
FIELD(ado_current_asset_owner)
|
||||
FIELD(need_to_generate_ado_proof)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
|
|
@ -181,6 +203,8 @@ namespace currency
|
|||
finalize_tx_param ftp;
|
||||
std::string htlc_origin;
|
||||
std::vector<serializable_pair<uint64_t, crypto::key_image>> outs_key_images; // pairs (out_index, key_image) for each change output
|
||||
crypto::key_derivation derivation;
|
||||
bool was_not_prepared = false; // true if tx was not prepared/created for some good reason (e.g. not enough outs for UTXO defragmentation tx). Because we decided not to throw exceptions for non-error cases. -- sowle
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(tx)
|
||||
|
|
@ -188,37 +212,94 @@ namespace currency
|
|||
FIELD(ftp)
|
||||
FIELD(htlc_origin)
|
||||
FIELD(outs_key_images)
|
||||
FIELD(derivation)
|
||||
FIELD(was_not_prepared)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct wallet_out_info
|
||||
{
|
||||
wallet_out_info() = default;
|
||||
wallet_out_info(size_t index, uint64_t amount)
|
||||
: index(index)
|
||||
, amount(amount)
|
||||
{}
|
||||
wallet_out_info(size_t index, uint64_t amount, const crypto::scalar_t& amount_blinding_mask, const crypto::scalar_t& asset_id_blinding_mask, const crypto::public_key& asset_id)
|
||||
: index(index)
|
||||
, amount(amount)
|
||||
, amount_blinding_mask(amount_blinding_mask)
|
||||
, asset_id_blinding_mask(asset_id_blinding_mask)
|
||||
, asset_id(asset_id)
|
||||
{}
|
||||
|
||||
size_t index = SIZE_MAX;
|
||||
uint64_t amount = 0;
|
||||
crypto::scalar_t amount_blinding_mask = 0;
|
||||
crypto::scalar_t asset_id_blinding_mask = 0;
|
||||
crypto::public_key asset_id = currency::native_coin_asset_id; // use point_t instead as this is for internal use only?
|
||||
|
||||
bool is_native_coin() const { return asset_id == currency::native_coin_asset_id; }
|
||||
};
|
||||
|
||||
|
||||
// TODO @#@# consider refactoring to eliminate redundant coping and to imporve performance
|
||||
struct zc_outs_range_proofs_with_commitments
|
||||
{
|
||||
zc_outs_range_proofs_with_commitments(const zc_outs_range_proof& range_proof, const std::vector<crypto::point_t>& amount_commitments)
|
||||
: range_proof(range_proof)
|
||||
, amount_commitments(amount_commitments)
|
||||
{}
|
||||
zc_outs_range_proofs_with_commitments(const zc_outs_range_proof& range_proof)
|
||||
: range_proof(range_proof)
|
||||
{}
|
||||
zc_outs_range_proof range_proof;
|
||||
std::vector<crypto::point_t> amount_commitments;
|
||||
};
|
||||
|
||||
struct asset_op_verification_context
|
||||
{
|
||||
const transaction& tx;
|
||||
const crypto::hash& tx_id;
|
||||
const asset_descriptor_operation& ado;
|
||||
crypto::public_key asset_id = currency::null_pkey;
|
||||
crypto::point_t asset_id_pt = crypto::c_point_0;
|
||||
uint64_t amount_to_validate = 0;
|
||||
std::shared_ptr< const std::list<asset_descriptor_operation> > asset_op_history;
|
||||
};
|
||||
|
||||
bool verify_multiple_zc_outs_range_proofs(const std::vector<zc_outs_range_proofs_with_commitments>& range_proofs);
|
||||
bool generate_asset_surjection_proof(const crypto::hash& context_hash, bool has_non_zc_inputs, tx_generation_context& ogc, zc_asset_surjection_proof& result);
|
||||
bool verify_asset_surjection_proof(const transaction& tx, const crypto::hash& tx_id);
|
||||
bool generate_tx_balance_proof(const transaction &tx, const crypto::hash& tx_id, const tx_generation_context& ogc, uint64_t block_reward_for_miner_tx, zc_balance_proof& proof);
|
||||
bool generate_zc_outs_range_proof(const crypto::hash& context_hash, size_t out_index_start, const tx_generation_context& outs_gen_context,
|
||||
const std::vector<tx_out_v>& vouts, zc_outs_range_proof& result);
|
||||
bool check_tx_bare_balance(const transaction& tx, uint64_t additional_inputs_amount_and_fees_for_mining_tx = 0);
|
||||
bool check_tx_balance(const transaction& tx, const crypto::hash& tx_id, uint64_t additional_inputs_amount_and_fees_for_mining_tx = 0);
|
||||
bool validate_asset_operation_amount_commitment(asset_op_verification_context& context);
|
||||
const char* get_asset_operation_type_string(size_t asset_operation_type, bool short_name = false);
|
||||
//---------------------------------------------------------------
|
||||
bool construct_miner_tx(size_t height, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins,
|
||||
size_t current_block_size,
|
||||
uint64_t fee,
|
||||
const account_public_address &miner_address,
|
||||
const account_public_address &stakeholder_address,
|
||||
transaction& tx,
|
||||
const blobdata& extra_nonce = blobdata(),
|
||||
size_t max_outs = CURRENCY_MINER_TX_MAX_OUTS,
|
||||
bool pos = false,
|
||||
const pos_entry& pe = pos_entry());
|
||||
|
||||
bool construct_miner_tx(size_t height, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins,
|
||||
size_t current_block_size,
|
||||
uint64_t fee,
|
||||
const std::vector<tx_destination_entry>& destinations,
|
||||
transaction& tx,
|
||||
const blobdata& extra_nonce = blobdata(),
|
||||
size_t max_outs = CURRENCY_MINER_TX_MAX_OUTS,
|
||||
bool pos = false,
|
||||
const pos_entry& pe = pos_entry());
|
||||
|
||||
|
||||
transaction& tx,
|
||||
uint64_t& block_reward_without_fee,
|
||||
uint64_t& block_reward,
|
||||
uint64_t tx_version,
|
||||
const blobdata& extra_nonce = blobdata(),
|
||||
size_t max_outs = CURRENCY_MINER_TX_MAX_OUTS,
|
||||
bool pos = false,
|
||||
const pos_entry& pe = pos_entry(),
|
||||
tx_generation_context* ogc_ptr = nullptr,
|
||||
const keypair* tx_one_time_key_to_use = nullptr,
|
||||
const std::vector<tx_destination_entry>& destinations = std::vector<tx_destination_entry>()
|
||||
);
|
||||
//---------------------------------------------------------------
|
||||
uint64_t get_string_uint64_hash(const std::string& str);
|
||||
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, const account_keys& self, finalized_tx& result, uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED);
|
||||
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, const account_keys& self, crypto::scalar_t& asset_blinding_mask, crypto::scalar_t& amount_blinding_mask, crypto::point_t& blinded_asset_id, crypto::point_t& amount_commitment, finalized_tx& result, uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED);
|
||||
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, const account_keys& self, uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED);
|
||||
|
||||
bool validate_alias_name(const std::string& al);
|
||||
bool validate_password(const std::string& password);
|
||||
void get_attachment_extra_info_details(const std::vector<attachment_v>& attachment, extra_attachment_info& eai);
|
||||
|
|
@ -227,6 +308,7 @@ namespace currency
|
|||
const std::vector<tx_destination_entry>& destinations,
|
||||
const std::vector<attachment_v>& attachments,
|
||||
transaction& tx,
|
||||
uint64_t tx_version,
|
||||
uint64_t unlock_time,
|
||||
uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED,
|
||||
bool shuffle = true);
|
||||
|
|
@ -236,6 +318,7 @@ namespace currency
|
|||
const std::vector<extra_v>& extra,
|
||||
const std::vector<attachment_v>& attachments,
|
||||
transaction& tx,
|
||||
uint64_t tx_version,
|
||||
crypto::secret_key& one_time_secret_key,
|
||||
uint64_t unlock_time,
|
||||
uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED,
|
||||
|
|
@ -248,6 +331,7 @@ namespace currency
|
|||
const std::vector<extra_v>& extra,
|
||||
const std::vector<attachment_v>& attachments,
|
||||
transaction& tx,
|
||||
uint64_t tx_version,
|
||||
crypto::secret_key& one_time_secret_key,
|
||||
uint64_t unlock_time,
|
||||
const account_public_address& crypt_account,
|
||||
|
|
@ -256,8 +340,10 @@ namespace currency
|
|||
bool shuffle = true,
|
||||
uint64_t flags = 0);
|
||||
|
||||
uint64_t get_tx_version(uint64_t tx_expected_block_height, const hard_forks_descriptor& hfd); // returns tx version based on the height of the block where the transaction is expected to be
|
||||
bool construct_tx(const account_keys& sender_account_keys, const finalize_tx_param& param, finalized_tx& result);
|
||||
|
||||
bool get_or_calculate_asset_id(const asset_descriptor_operation& ado, crypto::point_t* p_result_point, crypto::public_key* p_result_pub_key);
|
||||
const asset_descriptor_base& get_native_coin_asset_descriptor();
|
||||
|
||||
bool sign_multisig_input_in_tx(currency::transaction& tx, size_t ms_input_index, const currency::account_keys& keys, const currency::transaction& source_tx, bool *p_is_input_fully_signed = nullptr);
|
||||
|
||||
|
|
@ -268,32 +354,40 @@ namespace currency
|
|||
bool parse_and_validate_tx_extra(const transaction& tx, crypto::public_key& tx_pub_key);
|
||||
crypto::public_key get_tx_pub_key_from_extra(const transaction& tx);
|
||||
bool add_tx_pub_key_to_extra(transaction& tx, const crypto::public_key& tx_pub_key);
|
||||
bool add_tx_fee_amount_to_extra(transaction& tx, uint64_t fee, bool make_sure_its_unique = true);
|
||||
bool add_tx_extra_userdata(transaction& tx, const blobdata& extra_nonce);
|
||||
|
||||
crypto::hash get_multisig_out_id(const transaction& tx, size_t n);
|
||||
bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::key_derivation& derivation, size_t output_index);
|
||||
bool is_out_to_acc(const account_keys& acc, const txout_multisig& out_multisig, const crypto::key_derivation& derivation, size_t output_index);
|
||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector<size_t>& outs, uint64_t& money_transfered, crypto::key_derivation& derivation);
|
||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector<size_t>& outs, uint64_t& money_transfered, crypto::key_derivation& derivation, std::list<htlc_info>& htlc_info_list);
|
||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered, crypto::key_derivation& derivation);
|
||||
bool decode_output_amount_and_asset_id(const tx_out_zarcanum& zo, const crypto::key_derivation& derivation, const size_t output_index, uint64_t& decoded_amount, crypto::public_key& decoded_asset_id, crypto::scalar_t& amount_blinding_mask, crypto::scalar_t& asset_id_blinding_mask, crypto::scalar_t* derived_h_ptr = nullptr);
|
||||
bool is_out_to_acc(const account_public_address& addr, const txout_to_key& out_key, const crypto::key_derivation& derivation, size_t output_index);
|
||||
bool is_out_to_acc(const account_public_address& addr, const txout_multisig& out_multisig, const crypto::key_derivation& derivation, size_t output_index);
|
||||
bool is_out_to_acc(const account_public_address& addr, const tx_out_zarcanum& zo, const crypto::key_derivation& derivation, size_t output_index, uint64_t& decoded_amount, crypto::public_key& decoded_asset_id, crypto::scalar_t& amount_blinding_mask, crypto::scalar_t& asset_id_blinding_mask);
|
||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector<wallet_out_info>& outs, crypto::key_derivation& derivation);
|
||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector<wallet_out_info>& outs, crypto::key_derivation& derivation, std::list<htlc_info>& htlc_info_list);
|
||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<wallet_out_info>& outs, crypto::key_derivation& derivation);
|
||||
bool get_tx_fee(const transaction& tx, uint64_t & fee);
|
||||
uint64_t get_tx_fee(const transaction& tx);
|
||||
bool derive_ephemeral_key_helper(const account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, keypair& in_ephemeral);
|
||||
bool generate_key_image_helper(const account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki);
|
||||
bool derive_public_key_from_target_address(const account_public_address& destination_addr, const crypto::secret_key& tx_sec_key, size_t index, crypto::public_key& out_eph_public_key, crypto::key_derivation& derivation);
|
||||
bool derive_public_key_from_target_address(const account_public_address& destination_addr, const crypto::secret_key& tx_sec_key, size_t index, crypto::public_key& out_eph_public_key);
|
||||
bool derive_key_pair_from_key_pair(const crypto::public_key& src_pub_key, const crypto::secret_key& src_sec_key, crypto::secret_key& derived_sec_key, crypto::public_key& derived_pub_key, const char(&hs_domain)[32], uint64_t index = 0);
|
||||
uint16_t get_derivation_hint(const crypto::key_derivation& derivation);
|
||||
tx_derivation_hint make_tx_derivation_hint_from_uint16(uint16_t hint);
|
||||
|
||||
std::string short_hash_str(const crypto::hash& h);
|
||||
bool is_mixattr_applicable_for_fake_outs_counter(uint8_t mix_attr, uint64_t fake_attr_count);
|
||||
bool is_mixattr_applicable_for_fake_outs_counter(uint64_t out_tx_version, uint8_t out_mix_attr, uint64_t fake_outputs_count, const core_runtime_config& rtc);
|
||||
bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t current_blockchain_size, uint64_t current_time);
|
||||
crypto::key_derivation get_encryption_key_derivation(bool is_income, const transaction& tx, const account_keys& acc_keys);
|
||||
bool decrypt_payload_items(bool is_income, const transaction& tx, const account_keys& acc_keys, std::vector<payload_items_v>& decrypted_items);
|
||||
void encrypt_attachments(transaction& tx, const account_keys& sender_keys, const account_public_address& destination_addr, const keypair& tx_random_key, crypto::key_derivation& derivation);
|
||||
void encrypt_attachments(transaction& tx, const account_keys& sender_keys, const account_public_address& destination_addr, const keypair& tx_random_key);
|
||||
bool is_derivation_used_to_encrypt(const transaction& tx, const crypto::key_derivation& derivation);
|
||||
bool is_address_like_wrapped(const std::string& addr);
|
||||
void load_wallet_transfer_info_flags(tools::wallet_public::wallet_transfer_info& x);
|
||||
uint64_t get_tx_type(const transaction& tx);
|
||||
uint64_t get_tx_type_ex(const transaction& tx, tx_out& htlc_out, txin_htlc& htlc_in);
|
||||
size_t get_multisig_out_index(const std::vector<tx_out>& outs);
|
||||
uint64_t get_tx_type_ex(const transaction& tx, tx_out_bare& htlc_out, txin_htlc& htlc_in);
|
||||
size_t get_multisig_out_index(const std::vector<tx_out_v>& outs);
|
||||
size_t get_multisig_in_index(const std::vector<txin_v>& inputs);
|
||||
|
||||
uint64_t get_reward_from_miner_tx(const transaction& tx);
|
||||
|
|
@ -304,7 +398,7 @@ namespace currency
|
|||
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b);
|
||||
uint64_t get_inputs_money_amount(const transaction& tx);
|
||||
bool get_inputs_money_amount(const transaction& tx, uint64_t& money);
|
||||
uint64_t get_outs_money_amount(const transaction& tx);
|
||||
uint64_t get_outs_money_amount(const transaction& tx, const currency::account_keys& acc_keys_for_hidden_amounts = currency::null_acc_keys);
|
||||
bool check_inputs_types_supported(const transaction& tx);
|
||||
bool check_outs_valid(const transaction& tx);
|
||||
bool parse_amount(uint64_t& amount, const std::string& str_amount);
|
||||
|
|
@ -325,29 +419,31 @@ namespace currency
|
|||
uint64_t get_block_height(const transaction& coinbase);
|
||||
uint64_t get_block_height(const block& b);
|
||||
std::vector<txout_ref_v> relative_output_offsets_to_absolute(const std::vector<txout_ref_v>& off);
|
||||
std::vector<txout_ref_v> absolute_output_offsets_to_relative(const std::vector<txout_ref_v>& off);
|
||||
bool absolute_sorted_output_offsets_to_relative_in_place(std::vector<txout_ref_v>& offsets) noexcept;
|
||||
|
||||
bool validate_output_key_legit(const crypto::public_key& k);
|
||||
|
||||
// prints amount in format "3.14", "0.0"
|
||||
std::string print_money_brief(uint64_t amount);
|
||||
uint64_t get_actual_timestamp(const block& b); // obsolete and depricated, use get_block_datetime
|
||||
std::string print_money_brief(uint64_t amount, size_t decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT);
|
||||
uint64_t get_block_timestamp_from_miner_tx_extra(const block& b); // remove this function after HF4 -- sowle
|
||||
uint64_t get_block_datetime(const block& b);
|
||||
void set_block_datetime(uint64_t datetime, block& b);
|
||||
|
||||
bool addendum_to_hexstr(const std::vector<crypto::hash>& add, std::string& hex_buff);
|
||||
bool hexstr_to_addendum(const std::string& hex_buff, std::vector<crypto::hash>& add);
|
||||
bool set_payment_id_to_tx(std::vector<attachment_v>& att, const std::string& payment_id);
|
||||
bool set_payment_id_to_tx(std::vector<attachment_v>& att, const std::string& payment_id, bool is_in_hardfork4 = false);
|
||||
bool add_padding_to_tx(transaction& tx, size_t count);
|
||||
bool is_service_tx(const transaction& tx);
|
||||
bool does_tx_have_only_mixin_inputs(const transaction& tx);
|
||||
uint64_t get_hf4_inputs_key_offsets_count(const transaction& tx);
|
||||
bool is_showing_sender_addres(const transaction& tx);
|
||||
uint64_t get_amount_for_zero_pubkeys(const transaction& tx);
|
||||
//std::string get_comment_from_tx(const transaction& tx);
|
||||
bool check_native_coins_amount_burnt_in_outs(const transaction& tx, const uint64_t amount, uint64_t* p_amount_burnt = nullptr);
|
||||
std::string print_stake_kernel_info(const stake_kernel& sk);
|
||||
std::string dump_ring_sig_data(const crypto::hash& hash_for_sig, const crypto::key_image& k_image, const std::vector<const crypto::public_key*>& output_keys_ptrs, const std::vector<crypto::signature>& sig);
|
||||
|
||||
//PoS
|
||||
bool is_pos_block(const block& b);
|
||||
bool is_pos_block(const transaction& tx);
|
||||
bool is_pos_miner_tx(const transaction& tx);
|
||||
wide_difficulty_type correct_difficulty_with_sequence_factor(size_t sequence_factor, wide_difficulty_type diff);
|
||||
void print_currency_details();
|
||||
std::string print_reward_change_first_blocks(size_t n_of_first_blocks);
|
||||
|
|
@ -357,31 +453,56 @@ namespace currency
|
|||
update_alias_rpc_details alias_info_to_rpc_update_alias_info(const currency::extra_alias_entry& ai, const std::string& old_address);
|
||||
size_t get_service_attachments_count_in_tx(const transaction& tx);
|
||||
bool fill_tx_rpc_outputs(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce);
|
||||
bool fill_tx_rpc_inputs(tx_rpc_extended_info& tei, const transaction& tx);
|
||||
bool fill_tx_rpc_details(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce, const crypto::hash& h, uint64_t timestamp, bool is_short = false);
|
||||
|
||||
bool fill_block_rpc_details(block_rpc_extended_info& pei_rpc, const block_extended_info& bei_chain, const crypto::hash& h);
|
||||
void append_per_block_increments_for_tx(const transaction& tx, std::unordered_map<uint64_t, uint32_t>& gindices);
|
||||
std::string get_word_from_timstamp(uint64_t timestamp, bool use_password);
|
||||
uint64_t get_timstamp_from_word(std::string word, bool& password_used, const std::string& buff);
|
||||
uint64_t get_timstamp_from_word(std::string word, bool& password_used);
|
||||
bool parse_vote(const std::string& buff, std::list<std::pair<std::string, bool>>& votes);
|
||||
|
||||
std::string generate_origin_for_htlc(const txout_htlc& htlc, const account_keys& acc_keys);
|
||||
bool validate_ado_update_allowed(const asset_descriptor_base& a, const asset_descriptor_base& b);
|
||||
|
||||
|
||||
void normalize_asset_operation_for_hashing(asset_descriptor_operation& op);
|
||||
crypto::hash get_signature_hash_for_asset_operation(const asset_descriptor_operation& ado);
|
||||
|
||||
template<class t_txin_v>
|
||||
typename std::conditional<std::is_const<t_txin_v>::value, const std::vector<txin_etc_details_v>, std::vector<txin_etc_details_v> >::type& get_txin_etc_options(t_txin_v& in)
|
||||
{
|
||||
static typename std::conditional<std::is_const<t_txin_v>::value, const std::vector<txin_etc_details_v>, std::vector<txin_etc_details_v> >::type stub;
|
||||
|
||||
|
||||
//static stub;
|
||||
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
return boost::get<txin_to_key>(in).etc_details;
|
||||
else if (in.type() == typeid(txin_htlc))
|
||||
return boost::get<txin_htlc>(in).etc_details;
|
||||
else if (in.type() == typeid(txin_multisig))
|
||||
return boost::get<txin_multisig>(in).etc_details;
|
||||
else
|
||||
else if (in.type() == typeid(txin_htlc))
|
||||
return boost::get<txin_htlc>(in).etc_details;
|
||||
else if (in.type() == typeid(txin_zc_input))
|
||||
return boost::get<txin_zc_input>(in).etc_details;
|
||||
else
|
||||
return stub;
|
||||
}
|
||||
|
||||
template<typename out_t>
|
||||
inline bool is_out_burned(const out_t& out) { CHECK_AND_ASSERT_THROW_MES(false, "incorrect out type: " << typeid(out).name()); }
|
||||
template<>
|
||||
inline bool is_out_burned(const txout_to_key& o) { return o.key == null_pkey; }
|
||||
template<>
|
||||
inline bool is_out_burned(const tx_out_zarcanum& o) { return o.stealth_address == null_pkey; }
|
||||
struct zz_is_out_burned_helper_visitor : boost::static_visitor<bool>
|
||||
{
|
||||
template<typename T>
|
||||
bool operator()(const T& v) const { return is_out_burned(v); }
|
||||
};
|
||||
template<>
|
||||
inline bool is_out_burned(const txout_target_v& v) { return boost::apply_visitor(zz_is_out_burned_helper_visitor(), v); }
|
||||
template<>
|
||||
inline bool is_out_burned(const tx_out_v& v) { return boost::apply_visitor(zz_is_out_burned_helper_visitor(), v); }
|
||||
template<>
|
||||
inline bool is_out_burned(const tx_out_bare& o) { return is_out_burned(o.target); }
|
||||
|
||||
template<class t_extra_container>
|
||||
bool add_attachments_info_to_extra(t_extra_container& extra_container, const std::vector<attachment_v>& attachments)
|
||||
{
|
||||
|
|
@ -410,6 +531,7 @@ namespace currency
|
|||
bool parse_payment_id_from_hex_str(const std::string& payment_id_str, payment_id_t& payment_id);
|
||||
bool is_coinbase(const transaction& tx);
|
||||
bool is_coinbase(const transaction& tx, bool& pos_coinbase);
|
||||
bool is_pos_coinbase(const transaction& tx);
|
||||
bool have_attachment_service_in_container(const std::vector<attachment_v>& av, const std::string& service_id, const std::string& instruction);
|
||||
crypto::hash prepare_prefix_hash_for_sign(const transaction& tx, uint64_t in_index, const crypto::hash& tx_id);
|
||||
|
||||
|
|
@ -472,16 +594,34 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// outputs "1391306.970000000000"
|
||||
template<typename t_number>
|
||||
std::string print_fixed_decimal_point(t_number amount, size_t decimal_point)
|
||||
{
|
||||
return epee::string_tools::print_fixed_decimal_point(amount, decimal_point);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// outputs "1391306.97 "
|
||||
template<typename t_number>
|
||||
std::string print_money(t_number amount)
|
||||
std::string print_fixed_decimal_point_with_trailing_spaces(t_number amount, size_t decimal_point)
|
||||
{
|
||||
return print_fixed_decimal_point(amount, CURRENCY_DISPLAY_DECIMAL_POINT);
|
||||
std::string s = epee::string_tools::print_fixed_decimal_point(amount, decimal_point);
|
||||
for(size_t n = s.size() - 1; n != 0 && s[n] == '0' && s[n-1] != '.'; --n)
|
||||
s[n] = ' ';
|
||||
return s;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<typename t_number>
|
||||
std::string print_money(t_number amount, uint64_t decimals = CURRENCY_DISPLAY_DECIMAL_POINT)
|
||||
{
|
||||
return print_fixed_decimal_point(amount, decimals);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
|
||||
template<typename t_number>
|
||||
std::string print_asset_money(t_number amount, size_t decimal_point)
|
||||
{
|
||||
return print_fixed_decimal_point(amount, decimal_point);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<class alias_rpc_details_t>
|
||||
|
|
@ -531,38 +671,8 @@ namespace currency
|
|||
return get_or_add_field_to_variant_vector<extra_t>(extra);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<class variant_t, class variant_type_t>
|
||||
void update_or_add_field_to_extra(std::vector<variant_t>& variant_container, const variant_type_t& v)
|
||||
{
|
||||
for (auto& ev : variant_container)
|
||||
{
|
||||
if (ev.type() == typeid(variant_type_t))
|
||||
{
|
||||
boost::get<variant_type_t>(ev) = v;
|
||||
return;
|
||||
}
|
||||
}
|
||||
variant_container.push_back(v);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<class variant_type_t, class variant_t>
|
||||
void remove_field_of_type_from_extra(std::vector<variant_t>& variant_container)
|
||||
{
|
||||
for (size_t i = 0; i != variant_container.size();)
|
||||
{
|
||||
if (variant_container[i].type() == typeid(variant_type_t))
|
||||
{
|
||||
variant_container.erase(variant_container.begin()+i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<typename t_container>
|
||||
bool get_payment_id_from_tx(const t_container& att, std::string& payment_id)
|
||||
bool get_payment_id_from_decrypted_container(const t_container& att, std::string& payment_id)
|
||||
{
|
||||
tx_service_attachment sa = AUTO_VAL_INIT(sa);
|
||||
if (bc_services::get_first_service_attachment_by_id(att, BC_PAYMENT_ID_SERVICE_ID, "", sa))
|
||||
|
|
@ -647,59 +757,136 @@ namespace currency
|
|||
{
|
||||
decompose_amount_into_digits(amount, dust_threshold, chunk_handler, dust_handler, max_output_allowed, CURRENCY_TX_MAX_ALLOWED_OUTS, 0);
|
||||
}
|
||||
|
||||
// num_digits_to_keep -- how many digits to keep in chunks, 0 means all digits
|
||||
// Ex.: num_digits_to_keep == 3, number_of_outputs == 2 then 1.0 may be decomposed into 0.183 + 0.817
|
||||
// num_digits_to_keep == 0, number_of_outputs == 2 then 1.0 may be decomposed into 0.183374827362 + 0.816625172638
|
||||
template<typename chunk_handler_t>
|
||||
void decompose_amount_randomly(uint64_t amount, chunk_handler_t chunk_cb, size_t number_of_outputs = CURRENCY_TX_MIN_ALLOWED_OUTS, size_t num_digits_to_keep = CURRENCY_TX_OUTS_RND_SPLIT_DIGITS_TO_KEEP)
|
||||
{
|
||||
if (amount < number_of_outputs)
|
||||
return;
|
||||
|
||||
uint64_t boundary = 1000;
|
||||
if (num_digits_to_keep != CURRENCY_TX_OUTS_RND_SPLIT_DIGITS_TO_KEEP)
|
||||
{
|
||||
boundary = 1;
|
||||
for(size_t i = 0; i < num_digits_to_keep; ++i)
|
||||
boundary *= 10;
|
||||
}
|
||||
|
||||
auto trim_digits_and_add_variance = [boundary, num_digits_to_keep](uint64_t& v){
|
||||
if (num_digits_to_keep != 0 && v > 1)
|
||||
{
|
||||
uint64_t multiplier = 1;
|
||||
while(v >= boundary)
|
||||
{
|
||||
v /= 10;
|
||||
multiplier *= 10;
|
||||
}
|
||||
v = v / 2 + crypto::rand<uint64_t>() % (v + 1);
|
||||
v *= multiplier;
|
||||
}
|
||||
};
|
||||
|
||||
uint64_t amount_remaining = amount;
|
||||
for(size_t i = 1; i < number_of_outputs && amount_remaining > 1; ++i) // starting from 1 for one less iteration
|
||||
{
|
||||
uint64_t chunk_amount = amount_remaining / (number_of_outputs - i + 1);
|
||||
trim_digits_and_add_variance(chunk_amount);
|
||||
amount_remaining -= chunk_amount;
|
||||
chunk_cb(chunk_amount);
|
||||
}
|
||||
chunk_cb(amount_remaining);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
/*
|
||||
inline size_t get_input_expected_signatures_count(const txin_v& tx_in)
|
||||
{
|
||||
struct txin_signature_size_visitor : public boost::static_visitor<size_t>
|
||||
{
|
||||
size_t operator()(const txin_gen& /*txin*/) const { return 0; }
|
||||
size_t operator()(const txin_to_key& txin) const { return txin.key_offsets.size(); }
|
||||
size_t operator()(const txin_multisig& txin) const { return txin.sigs_count; }
|
||||
size_t operator()(const txin_htlc& txin) const { return 1; }
|
||||
size_t operator()(const txin_gen& txin) const { return 0; }
|
||||
size_t operator()(const txin_to_key& txin) const { return txin.key_offsets.size(); }
|
||||
size_t operator()(const txin_multisig& txin) const { return txin.sigs_count; }
|
||||
size_t operator()(const txin_htlc& txin) const { return 1; }
|
||||
size_t operator()(const txin_zc_input& txin) const { throw std::runtime_error("Not implemented yet"); }
|
||||
};
|
||||
|
||||
return boost::apply_visitor(txin_signature_size_visitor(), tx_in);
|
||||
}
|
||||
}*/
|
||||
//---------------------------------------------------------------
|
||||
inline const std::vector<txin_etc_details_v>* get_input_etc_details(const txin_v& in)
|
||||
inline size_t get_input_expected_signature_size(const txin_v& tx_in, bool last_input_in_separately_signed_tx)
|
||||
{
|
||||
if (in.type().hash_code() == typeid(txin_to_key).hash_code())
|
||||
return &boost::get<txin_to_key>(in).etc_details;
|
||||
if (in.type().hash_code() == typeid(txin_htlc).hash_code())
|
||||
return &boost::get<txin_htlc>(in).etc_details;
|
||||
if (in.type().hash_code() == typeid(txin_multisig).hash_code())
|
||||
return &boost::get<txin_multisig>(in).etc_details;
|
||||
return nullptr;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
inline std::vector<txin_etc_details_v>* get_input_etc_details(txin_v& in)
|
||||
{
|
||||
if (in.type().hash_code() == typeid(txin_to_key).hash_code())
|
||||
return &boost::get<txin_to_key>(in).etc_details;
|
||||
if (in.type().hash_code() == typeid(txin_htlc).hash_code())
|
||||
return &boost::get<txin_htlc>(in).etc_details;
|
||||
if (in.type().hash_code() == typeid(txin_multisig).hash_code())
|
||||
return &boost::get<txin_multisig>(in).etc_details;
|
||||
return nullptr;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
struct txin_signature_size_visitor : public boost::static_visitor<size_t>
|
||||
{
|
||||
txin_signature_size_visitor(size_t add) : a(add) {}
|
||||
size_t a;
|
||||
size_t operator()(const txin_gen& /*txin*/) const { return 0; }
|
||||
size_t operator()(const txin_to_key& txin) const { return tools::get_varint_packed_size(txin.key_offsets.size() + a) + sizeof(crypto::signature) * (txin.key_offsets.size() + a); }
|
||||
size_t operator()(const txin_multisig& txin) const { return tools::get_varint_packed_size(txin.sigs_count + a) + sizeof(crypto::signature) * (txin.sigs_count + a); }
|
||||
size_t operator()(const txin_htlc& txin) const { return tools::get_varint_packed_size(1 + a) + sizeof(crypto::signature) * (1 + a); }
|
||||
size_t operator()(const txin_zc_input& txin) const { return 97 + tools::get_varint_packed_size(txin.key_offsets.size()) + txin.key_offsets.size() * 32; }
|
||||
};
|
||||
|
||||
return boost::apply_visitor(txin_signature_size_visitor(last_input_in_separately_signed_tx ? 1 : 0), tx_in);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<class txin_t>
|
||||
typename std::conditional<std::is_const<txin_t>::value, const std::vector<txin_etc_details_v>, std::vector<txin_etc_details_v> >::type*
|
||||
get_input_etc_details(txin_t& in)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
return &boost::get<txin_to_key>(in).etc_details;
|
||||
if (in.type() == typeid(txin_multisig))
|
||||
return &boost::get<txin_multisig>(in).etc_details;
|
||||
if (in.type() == typeid(txin_htlc))
|
||||
return &boost::get<txin_htlc>(in).etc_details;
|
||||
if (in.type() == typeid(txin_zc_input))
|
||||
return &boost::get<txin_zc_input>(in).etc_details;
|
||||
return nullptr;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
struct input_amount_getter : public boost::static_visitor<uint64_t>
|
||||
{
|
||||
template<class t_input>
|
||||
uint64_t operator()(const t_input& i) const{return i.amount;}
|
||||
uint64_t operator()(const txin_gen& i) const {return 0;}
|
||||
uint64_t operator()(const t_input& i) const { return i.amount; }
|
||||
uint64_t operator()(const txin_zc_input&) const { return 0; }
|
||||
uint64_t operator()(const txin_gen& i) const { return 0; }
|
||||
};
|
||||
|
||||
inline uint64_t get_amount_from_variant(const txin_v& v)
|
||||
inline uint64_t get_amount_from_variant(const txin_v& v) noexcept
|
||||
{
|
||||
return boost::apply_visitor(input_amount_getter(), v);
|
||||
try
|
||||
{
|
||||
return boost::apply_visitor(input_amount_getter(), v);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
struct output_amount_getter : public boost::static_visitor<uint64_t>
|
||||
{
|
||||
template<class out_t>
|
||||
uint64_t operator()(const out_t&) const { return 0; }
|
||||
uint64_t operator()(const tx_out_bare& ob) const { return ob.amount; }
|
||||
};
|
||||
inline uint64_t get_amount_from_variant(const tx_out_v& out_v)
|
||||
{
|
||||
return boost::apply_visitor(output_amount_getter(), out_v);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
inline const tx_out_bare& get_tx_out_bare_from_out_v(const tx_out_v& o)
|
||||
{
|
||||
//this function will throw if type is not matching
|
||||
return boost::get<tx_out_bare>(o);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template <typename container_t>
|
||||
void create_and_add_tx_payer_to_container_from_address(container_t& container, const account_public_address& addr, uint64_t top_block_height, const core_runtime_config& crc)
|
||||
{
|
||||
if (top_block_height > crc.hard_fork_02_starts_after_height)
|
||||
if (crc.is_hardfork_active_for_height(2, top_block_height))
|
||||
{
|
||||
// after hardfork 2
|
||||
tx_payer result = AUTO_VAL_INIT(result);
|
||||
|
|
@ -721,7 +908,7 @@ namespace currency
|
|||
template <typename container_t>
|
||||
void create_and_add_tx_receiver_to_container_from_address(container_t& container, const account_public_address& addr, uint64_t top_block_height, const core_runtime_config& crc)
|
||||
{
|
||||
if (top_block_height > crc.hard_fork_02_starts_after_height)
|
||||
if (crc.is_hardfork_active_for_height(2, top_block_height))
|
||||
{
|
||||
// after hardfork 2
|
||||
tx_receiver result = AUTO_VAL_INIT(result);
|
||||
|
|
@ -761,5 +948,243 @@ namespace currency
|
|||
const difficulties& b_diff
|
||||
);
|
||||
|
||||
boost::multiprecision::uint1024_t get_a_to_b_relative_cumulative_difficulty_hf4(const wide_difficulty_type& difficulty_pos_at_split_point,
|
||||
const wide_difficulty_type& difficulty_pow_at_split_point,
|
||||
const difficulties& a_diff,
|
||||
const difficulties& b_diff
|
||||
);
|
||||
|
||||
|
||||
struct rpc_tx_payload_handler : public boost::static_visitor<bool>
|
||||
{
|
||||
tx_extra_rpc_entry& tv;
|
||||
rpc_tx_payload_handler(tx_extra_rpc_entry& t) : tv(t)
|
||||
{}
|
||||
|
||||
bool operator()(const tx_service_attachment& ee)
|
||||
{
|
||||
tv.type = "service";
|
||||
tv.short_view = ee.service_id + ":" + ee.instruction;
|
||||
if (ee.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY)
|
||||
tv.short_view += "(encrypted)";
|
||||
else
|
||||
{
|
||||
std::string deflated_buff;
|
||||
const std::string* pfinalbuff = &ee.body;
|
||||
if (ee.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY)
|
||||
{
|
||||
bool r = epee::zlib_helper::unpack(ee.body, deflated_buff);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to unpack");
|
||||
pfinalbuff = &deflated_buff;
|
||||
}
|
||||
if (ee.service_id == BC_PAYMENT_ID_SERVICE_ID || ee.service_id == BC_OFFERS_SERVICE_ID)
|
||||
tv.details_view = *pfinalbuff;
|
||||
else
|
||||
tv.details_view = "BINARY DATA";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_crypto_checksum& ee)
|
||||
{
|
||||
tv.type = "crypto_checksum";
|
||||
tv.short_view = std::string("derivation_hash: ") + epee::string_tools::pod_to_hex(ee.derivation_hash);
|
||||
tv.details_view = std::string("derivation_hash: ") + epee::string_tools::pod_to_hex(ee.derivation_hash) + "\n"
|
||||
+ "encrypted_key_derivation: " + epee::string_tools::pod_to_hex(ee.encrypted_key_derivation);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_time& ee)
|
||||
{
|
||||
tv.type = "pos_time";
|
||||
tv.short_view = std::string("timestamp: ") + std::to_string(ee.v) + " " + epee::misc_utils::get_internet_time_str(ee.v);
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_details_unlock_time& ee)
|
||||
{
|
||||
tv.type = "unlock_time";
|
||||
if (ee.v < CURRENCY_MAX_BLOCK_NUMBER)
|
||||
tv.short_view = std::string("height: ") + std::to_string(ee.v);
|
||||
else
|
||||
tv.short_view = std::string("timestamp: ") + std::to_string(ee.v) + " " + epee::misc_utils::get_internet_time_str(ee.v);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_details_unlock_time2& ee)
|
||||
{
|
||||
tv.type = "unlock_time";
|
||||
std::stringstream ss;
|
||||
ss << "[";
|
||||
for (auto v : ee.unlock_time_array)
|
||||
{
|
||||
ss << " " << v;
|
||||
}
|
||||
ss << "]";
|
||||
tv.short_view = ss.str();
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_details_expiration_time& ee)
|
||||
{
|
||||
tv.type = "expiration_time";
|
||||
if (ee.v < CURRENCY_MAX_BLOCK_NUMBER)
|
||||
tv.short_view = std::string("height: ") + std::to_string(ee.v);
|
||||
else
|
||||
tv.short_view = std::string("timestamp: ") + std::to_string(ee.v) + " " + epee::misc_utils::get_internet_time_str(ee.v);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_details_flags& ee)
|
||||
{
|
||||
tv.type = "details_flags";
|
||||
tv.short_view = epee::string_tools::pod_to_hex(ee.v);
|
||||
return true;
|
||||
}
|
||||
bool operator()(const crypto::public_key& ee)
|
||||
{
|
||||
tv.type = "pub_key";
|
||||
tv.short_view = epee::string_tools::pod_to_hex(ee);
|
||||
return true;
|
||||
}
|
||||
bool operator()(const extra_attachment_info& ee)
|
||||
{
|
||||
tv.type = "attachment_info";
|
||||
tv.short_view = std::to_string(ee.sz) + " bytes";
|
||||
tv.details_view = currency::obj_to_json_str(ee);
|
||||
return true;
|
||||
}
|
||||
bool operator()(const extra_alias_entry& ee)
|
||||
{
|
||||
tv.type = "alias_info";
|
||||
tv.short_view = ee.m_alias + "-->" + get_account_address_as_str(ee.m_address);
|
||||
tv.details_view = currency::obj_to_json_str(ee);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const extra_alias_entry_old& ee)
|
||||
{
|
||||
return operator()(static_cast<const extra_alias_entry&>(ee));
|
||||
}
|
||||
bool operator()(const extra_user_data& ee)
|
||||
{
|
||||
tv.type = "user_data";
|
||||
tv.short_view = std::to_string(ee.buff.size()) + " bytes";
|
||||
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(ee.buff);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const extra_padding& ee)
|
||||
{
|
||||
tv.type = "extra_padding";
|
||||
tv.short_view = std::to_string(ee.buff.size()) + " bytes";
|
||||
if (!ee.buff.empty())
|
||||
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(&ee.buff[0]), ee.buff.size()));
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_comment& ee)
|
||||
{
|
||||
tv.type = "comment";
|
||||
tv.short_view = std::to_string(ee.comment.size()) + " bytes(encrypted)";
|
||||
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(ee.comment);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_payer& ee)
|
||||
{
|
||||
//const tx_payer& ee = boost::get<tx_payer>(extra);
|
||||
tv.type = "payer";
|
||||
tv.short_view = "(encrypted)";
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_payer_old&)
|
||||
{
|
||||
tv.type = "payer_old";
|
||||
tv.short_view = "(encrypted)";
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_receiver& ee)
|
||||
{
|
||||
//const tx_payer& ee = boost::get<tx_payer>(extra);
|
||||
tv.type = "receiver";
|
||||
tv.short_view = "(encrypted)";
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_receiver_old& ee)
|
||||
{
|
||||
tv.type = "receiver_old";
|
||||
tv.short_view = "(encrypted)";
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_derivation_hint& ee)
|
||||
{
|
||||
tv.type = "derivation_hint";
|
||||
tv.short_view = std::to_string(ee.msg.size()) + " bytes";
|
||||
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(ee.msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const std::string& ee)
|
||||
{
|
||||
tv.type = "string";
|
||||
tv.short_view = std::to_string(ee.size()) + " bytes";
|
||||
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(ee);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_flags16_t& dh)
|
||||
{
|
||||
tv.type = "FLAGS16";
|
||||
tv.short_view = epee::string_tools::pod_to_hex(dh);
|
||||
tv.details_view = epee::string_tools::pod_to_hex(dh);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const zarcanum_tx_data_v1& ztxd)
|
||||
{
|
||||
tv.type = "zarcanum_tx_data_v1";
|
||||
tv.short_view = "fee = " + print_money_brief(ztxd.fee);
|
||||
tv.details_view = tv.short_view;
|
||||
return true;
|
||||
}
|
||||
bool operator()(const zc_outs_range_proof& rp)
|
||||
{
|
||||
tv.type = "zc_outs_range_proof";
|
||||
// TODO @#@#
|
||||
//tv.short_view = "outputs_count = " + std::to_string(rp.outputs_count);
|
||||
return true;
|
||||
}
|
||||
bool operator()(const zc_balance_proof& bp)
|
||||
{
|
||||
tv.type = "zc_balance_proof";
|
||||
return true;
|
||||
}
|
||||
template<typename t_type>
|
||||
bool operator()(const t_type& t_t)
|
||||
{
|
||||
tv.type = typeid(t_t).name();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
//------------------------------------------------------------------
|
||||
|
||||
|
||||
template<class t_container>
|
||||
bool fill_tx_rpc_payload_items(std::vector<tx_extra_rpc_entry>& target_vector, const t_container& tc)
|
||||
{
|
||||
//handle extra
|
||||
for (auto& extra : tc)
|
||||
{
|
||||
target_vector.push_back(tx_extra_rpc_entry());
|
||||
tx_extra_rpc_entry& tv = target_vector.back();
|
||||
|
||||
rpc_tx_payload_handler vstr(tv);
|
||||
boost::apply_visitor(vstr, extra);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace currency
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace currency
|
|||
/* */
|
||||
/************************************************************************/
|
||||
template<class t_array>
|
||||
struct array_hasher : std::unary_function<t_array&, std::size_t>
|
||||
struct array_hasher
|
||||
{
|
||||
std::size_t operator()(const t_array& val) const
|
||||
{
|
||||
|
|
@ -91,22 +91,66 @@ namespace currency
|
|||
++result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<typename specific_type_t, typename variant_t_container>
|
||||
bool get_type_in_variant_container(const variant_t_container& av, specific_type_t& a)
|
||||
specific_type_t* get_type_in_variant_container(variant_t_container& av)
|
||||
{
|
||||
for (auto& ai : av)
|
||||
{
|
||||
if (ai.type() == typeid(specific_type_t))
|
||||
{
|
||||
a = boost::get<specific_type_t>(ai);
|
||||
return true;
|
||||
return &boost::get<specific_type_t>(ai);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<typename specific_type_t, typename variant_t_container>
|
||||
bool get_type_in_variant_container(variant_t_container& av, specific_type_t& a)
|
||||
{
|
||||
const specific_type_t* pa = get_type_in_variant_container<const specific_type_t>(av);
|
||||
if (pa)
|
||||
{
|
||||
a = *pa;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
//---------------------------------------------------------------
|
||||
template<typename specific_type_t, typename variant_t_container>
|
||||
specific_type_t& get_type_in_variant_container_by_ref(variant_t_container& av)
|
||||
{
|
||||
for (auto& ai : av)
|
||||
{
|
||||
if (ai.type() == typeid(specific_type_t))
|
||||
{
|
||||
return boost::get<specific_type_t>(ai);
|
||||
}
|
||||
}
|
||||
ASSERT_MES_AND_THROW("Object with type " << typeid(specific_type_t).name() << " was not found in a container");
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// if cb returns true, it means "continue", false -- means "stop"
|
||||
template<typename specific_type_t, typename variant_container_t, typename callback_t>
|
||||
bool process_type_in_variant_container(const variant_container_t& av, callback_t& cb, bool return_value_if_none_found = true)
|
||||
{
|
||||
bool found = false;
|
||||
for (auto& ai : av)
|
||||
{
|
||||
if (ai.type() == typeid(specific_type_t))
|
||||
{
|
||||
found = true;
|
||||
if (!cb(boost::get<specific_type_t>(ai)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
return true;
|
||||
return return_value_if_none_found;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// callback should return true to continue iterating through the container
|
||||
template <typename A, typename B, typename container_t, typename callback_t>
|
||||
bool handle_2_alternative_types_in_variant_container(const container_t& container, callback_t cb)
|
||||
|
|
@ -131,20 +175,158 @@ namespace currency
|
|||
}
|
||||
//---------------------------------------------------------------
|
||||
inline
|
||||
const txin_to_key& get_to_key_input_from_txin_v(const txin_v& in_v)
|
||||
bool get_key_image_from_txin_v(const txin_v& in_v, crypto::key_image& result) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
if (in_v.type() == typeid(txin_to_key))
|
||||
{
|
||||
result = boost::get<txin_to_key>(in_v).k_image;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (in_v.type() == typeid(txin_htlc))
|
||||
{
|
||||
result = boost::get<txin_htlc>(in_v).k_image;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (in_v.type() == typeid(txin_zc_input))
|
||||
{
|
||||
result = boost::get<txin_zc_input>(in_v).k_image;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// should never go here, just precaution
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
inline
|
||||
const crypto::key_image& get_key_image_from_txin_v(const txin_v& in_v)
|
||||
{
|
||||
if (in_v.type() == typeid(txin_to_key))
|
||||
return boost::get<txin_to_key>(in_v).k_image;
|
||||
|
||||
if (in_v.type() == typeid(txin_htlc))
|
||||
return boost::get<txin_htlc>(in_v).k_image;
|
||||
|
||||
if (in_v.type() == typeid(txin_zc_input))
|
||||
return boost::get<txin_zc_input>(in_v).k_image;
|
||||
|
||||
CHECK_AND_ASSERT_THROW_MES(false, "[get_key_image_from_txin_v] Wrong type: " << in_v.type().name());
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
inline
|
||||
const std::vector<currency::txout_ref_v>& get_key_offsets_from_txin_v(const txin_v& in_v)
|
||||
{
|
||||
if (in_v.type() == typeid(txin_to_key))
|
||||
return boost::get<txin_to_key>(in_v).key_offsets;
|
||||
|
||||
if (in_v.type() == typeid(txin_htlc))
|
||||
return boost::get<txin_htlc>(in_v).key_offsets;
|
||||
|
||||
if (in_v.type() == typeid(txin_zc_input))
|
||||
return boost::get<txin_zc_input>(in_v).key_offsets;
|
||||
|
||||
CHECK_AND_ASSERT_THROW_MES(false, "[get_key_offsets_from_txin_v] Wrong type: " << in_v.type().name());
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
inline
|
||||
bool get_mix_attr_from_tx_out_v(const tx_out_v& out_v, uint8_t& result) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
return boost::get<txin_to_key>(in_v);
|
||||
if (out_v.type() == typeid(tx_out_bare))
|
||||
{
|
||||
const tx_out_bare& ob = boost::get<tx_out_bare>(out_v);
|
||||
if (ob.target.type() == typeid(txout_to_key))
|
||||
{
|
||||
result = boost::get<txout_to_key>(ob.target).mix_attr;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (out_v.type() == typeid(tx_out_zarcanum))
|
||||
{
|
||||
result = boost::get<tx_out_zarcanum>(out_v).mix_attr;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (in_v.type() == typeid(txin_htlc))
|
||||
catch(...)
|
||||
{
|
||||
const txin_htlc& in = boost::get<txin_htlc>(in_v);
|
||||
return static_cast<const txin_to_key&>(in);
|
||||
// should never go here, just precaution
|
||||
}
|
||||
else {
|
||||
ASSERT_MES_AND_THROW("[get_to_key_input_from_txin_v] Wrong type " << in_v.type().name());
|
||||
|
||||
return false;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
//, txin_htlc, txin_zc_input
|
||||
inline bool compare_variant_by_types(const txin_multisig& left, const txin_multisig& right)
|
||||
{
|
||||
return (left.multisig_out_id < right.multisig_out_id);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
inline bool compare_variant_by_types(const txin_gen& left, const txin_gen& right)
|
||||
{
|
||||
//actually this should never happen, should we leave it in case it happen in unit tests? @sowle
|
||||
return (left.height < right.height);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<typename type_with_kimage_t>
|
||||
bool compare_variant_by_types(const type_with_kimage_t& left, const type_with_kimage_t& right)
|
||||
{
|
||||
return (left.k_image < right.k_image);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<typename t_type_left, typename t_type_right>
|
||||
bool compare_variant_by_types(const t_type_left& left, const t_type_right& right)
|
||||
{
|
||||
if (typeid(t_type_left) == typeid(t_type_right))
|
||||
{
|
||||
ASSERT_MES_AND_THROW("[compare_varian_by_types] Left and Right types matched type " << typeid(t_type_left).name());
|
||||
}
|
||||
typedef binary_archive<true> bin_archive;
|
||||
typedef variant_serialization_traits<bin_archive, t_type_left> traits_left;
|
||||
typedef variant_serialization_traits<bin_archive, t_type_right> traits_right;
|
||||
return (traits_left::get_tag() < traits_right::get_tag());
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<typename t_type_left>
|
||||
struct right_visitor : public boost::static_visitor<bool>
|
||||
{
|
||||
const t_type_left& m_rleft;
|
||||
|
||||
right_visitor(const t_type_left& left) : m_rleft(left)
|
||||
{}
|
||||
|
||||
template<typename t_type_right>
|
||||
bool operator()(const t_type_right& right)const
|
||||
{
|
||||
return compare_variant_by_types(m_rleft, right);
|
||||
}
|
||||
};
|
||||
|
||||
struct left_visitor : public boost::static_visitor<bool>
|
||||
{
|
||||
const txin_v& m_rright;
|
||||
|
||||
left_visitor(const txin_v& right) : m_rright(right)
|
||||
{}
|
||||
template<typename t_type_left>
|
||||
bool operator()(const t_type_left& left)const
|
||||
{
|
||||
return boost::apply_visitor(right_visitor<t_type_left>(left), m_rright);
|
||||
}
|
||||
};
|
||||
//---------------------------------------------------------------
|
||||
inline bool less_txin_v(const txin_v& left, const txin_v& right)
|
||||
{
|
||||
//predefined type hierarchy based on it's tags defined in currency_basic.h, call compare_variant_by_types via 2-level visitor
|
||||
return boost::apply_visitor(left_visitor(right), left);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<typename variant_container_t>
|
||||
|
|
@ -247,6 +429,26 @@ namespace currency
|
|||
size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size);
|
||||
|
||||
|
||||
inline
|
||||
void put_t_to_buff(std::string& buff)
|
||||
{}
|
||||
|
||||
template <typename T, typename... Types>
|
||||
void put_t_to_buff(std::string& buff, const T& var1, Types&... var2)
|
||||
{
|
||||
static_assert(std::is_pod<T>::value, "T must be a POD type.");
|
||||
buff.append((const char*)&var1, sizeof(var1));
|
||||
put_t_to_buff(buff, var2...);
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
crypto::hash get_hash_from_POD_objects(Types&... var1)
|
||||
{
|
||||
std::string buff;
|
||||
put_t_to_buff(buff, var1...);
|
||||
return crypto::cn_fast_hash(buff.data(), buff.size());
|
||||
}
|
||||
|
||||
|
||||
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \
|
||||
CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "serialization/serialization.h"
|
||||
#include "currency_format_utils.h"
|
||||
#include "currency_format_utils_abstract.h"
|
||||
#include "common/variant_helper.h"
|
||||
|
||||
namespace currency
|
||||
{
|
||||
|
|
@ -24,6 +25,8 @@ namespace currency
|
|||
//------------------------------------------------------------------
|
||||
bool is_tx_expired(const transaction& tx, uint64_t expiration_ts_median)
|
||||
{
|
||||
if (expiration_ts_median == 0)
|
||||
return false;
|
||||
/// tx expiration condition (tx is ok if the following is true)
|
||||
/// tx_expiration_time - TX_EXPIRATION_MEDIAN_SHIFT > get_last_n_blocks_timestamps_median(TX_EXPIRATION_TIMESTAMP_CHECK_WINDOW)
|
||||
uint64_t expiration_time = get_tx_expiration_time(tx);
|
||||
|
|
@ -37,11 +40,17 @@ namespace currency
|
|||
uint64_t res = 0;
|
||||
for (auto& o : tx.vout)
|
||||
{
|
||||
if (o.target.type() == typeid(txout_to_key))
|
||||
{
|
||||
if (boost::get<txout_to_key>(o.target).key == null_pkey)
|
||||
res += o.amount;
|
||||
}
|
||||
VARIANT_SWITCH_BEGIN(o);
|
||||
VARIANT_CASE_CONST(tx_out_bare, o)
|
||||
if (o.target.type() == typeid(txout_to_key))
|
||||
{
|
||||
if (boost::get<txout_to_key>(o.target).key == null_pkey)
|
||||
res += o.amount;
|
||||
}
|
||||
VARIANT_CASE_CONST(tx_out_zarcanum, o)
|
||||
//@#@# TODO obtain info about public burn of native coins in ZC outputs
|
||||
VARIANT_CASE_THROW_ON_OTHER();
|
||||
VARIANT_SWITCH_END();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
@ -203,12 +212,35 @@ namespace currency
|
|||
return total;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
inline size_t get_input_expected_signature_size_local(const txin_v& tx_in, bool last_input_in_separately_signed_tx)
|
||||
{
|
||||
struct txin_signature_size_visitor : public boost::static_visitor<size_t>
|
||||
{
|
||||
txin_signature_size_visitor(size_t add) : a(add) {}
|
||||
size_t a;
|
||||
size_t operator()(const txin_gen& /*txin*/) const { return 0; }
|
||||
size_t operator()(const txin_to_key& txin) const { return tools::get_varint_packed_size(txin.key_offsets.size() + a) + sizeof(crypto::signature) * (txin.key_offsets.size() + a); }
|
||||
size_t operator()(const txin_multisig& txin) const { return tools::get_varint_packed_size(txin.sigs_count + a) + sizeof(crypto::signature) * (txin.sigs_count + a); }
|
||||
size_t operator()(const txin_htlc& txin) const { return tools::get_varint_packed_size(1 + a) + sizeof(crypto::signature) * (1 + a); }
|
||||
size_t operator()(const txin_zc_input& txin) const { return 96 + tools::get_varint_packed_size(txin.key_offsets.size()) + txin.key_offsets.size() * 32; }
|
||||
};
|
||||
|
||||
return boost::apply_visitor(txin_signature_size_visitor(last_input_in_separately_signed_tx ? 1 : 0), tx_in);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size)
|
||||
{
|
||||
size_t tx_blob_size = prefix_blob_size;
|
||||
|
||||
if (is_coinbase(t))
|
||||
{
|
||||
if (is_pos_miner_tx(t) && t.version > TRANSACTION_VERSION_PRE_HF4)
|
||||
{
|
||||
// Zarcanum
|
||||
return tx_blob_size;
|
||||
}
|
||||
return tx_blob_size;
|
||||
}
|
||||
|
||||
// for purged tx, with empty signatures and attachments, this function should return the blob size
|
||||
// which the tx would have if the signatures and attachments were correctly filled with actual data
|
||||
|
|
@ -217,14 +249,13 @@ namespace currency
|
|||
bool separately_signed_tx = get_tx_flags(t) & TX_FLAG_SIGNATURE_MODE_SEPARATE;
|
||||
|
||||
tx_blob_size += tools::get_varint_packed_size(t.vin.size()); // size of transaction::signatures (equals to total inputs count)
|
||||
if (t.version > TRANSACTION_VERSION_PRE_HF4)
|
||||
tx_blob_size += t.vin.size(); // for HF4 txs 'signatures' is a verctor of variants, so it's +1 byte per signature (assuming sigs count equals to inputs count)
|
||||
|
||||
for (size_t i = 0; i != t.vin.size(); i++)
|
||||
{
|
||||
size_t sig_count = get_input_expected_signatures_count(t.vin[i]);
|
||||
if (separately_signed_tx && i == t.vin.size() - 1)
|
||||
++sig_count; // count in one more signature for the last input in a complete separately signed tx
|
||||
tx_blob_size += tools::get_varint_packed_size(sig_count); // size of transaction::signatures[i]
|
||||
tx_blob_size += sizeof(crypto::signature) * sig_count; // size of signatures' data itself
|
||||
size_t sig_size = get_input_expected_signature_size_local(t.vin[i], separately_signed_tx && i == t.vin.size() - 1);
|
||||
tx_blob_size += sig_size;
|
||||
}
|
||||
|
||||
// 2. attachments (try to find extra_attachment_info in tx prefix and count it in if succeed)
|
||||
|
|
@ -260,16 +291,134 @@ namespace currency
|
|||
bool read_keyimages_from_tx(const transaction& tx, std::list<crypto::key_image>& kil)
|
||||
{
|
||||
std::unordered_set<crypto::key_image> ki;
|
||||
BOOST_FOREACH(const auto& in, tx.vin)
|
||||
for(const auto& in : tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key) || in.type() == typeid(txin_htlc))
|
||||
if (in.type() == typeid(txin_to_key) || in.type() == typeid(txin_htlc) || in.type() == typeid(txin_zc_input))
|
||||
{
|
||||
|
||||
if (!ki.insert(get_to_key_input_from_txin_v(in).k_image).second)
|
||||
if (!ki.insert(get_key_image_from_txin_v(in)).second)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool validate_inputs_sorting(const transaction& tx)
|
||||
{
|
||||
if (get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE)
|
||||
return true;
|
||||
|
||||
|
||||
size_t i = 0;
|
||||
for(; i+1 < tx.vin.size(); i++)
|
||||
{
|
||||
//same less_txin_v() function should be used for sorting inputs during transacction creation
|
||||
if (less_txin_v(tx.vin[i+1], tx.vin[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool is_asset_emitting_transaction(const transaction& tx, asset_descriptor_operation* p_ado /* = nullptr */)
|
||||
{
|
||||
if (tx.version <= TRANSACTION_VERSION_PRE_HF4)
|
||||
return false;
|
||||
|
||||
asset_descriptor_operation local_ado{};
|
||||
if (p_ado == nullptr)
|
||||
p_ado = &local_ado;
|
||||
|
||||
if (!get_type_in_variant_container(tx.extra, *p_ado))
|
||||
return false;
|
||||
|
||||
if (p_ado->operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER || p_ado->operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// Prepapres vector of output_entry to be used in key_offsets in a transaction input:
|
||||
// 1) sort all entries by gindex (while moving all ref_by_id to the end, keeping they relative order)
|
||||
// 2) convert absolute global indices to relative key_offsets
|
||||
std::vector<tx_source_entry::output_entry> prepare_outputs_entries_for_key_offsets(const std::vector<tx_source_entry::output_entry>& outputs, size_t old_real_index, size_t& new_real_index) noexcept
|
||||
{
|
||||
TRY_ENTRY()
|
||||
|
||||
std::vector<tx_source_entry::output_entry> result = outputs;
|
||||
if (outputs.size() < 2)
|
||||
{
|
||||
new_real_index = old_real_index;
|
||||
return result;
|
||||
}
|
||||
|
||||
std::sort(result.begin(), result.end(), [](const tx_source_entry::output_entry& lhs, const tx_source_entry::output_entry& rhs)
|
||||
{
|
||||
if (lhs.out_reference.type() == typeid(uint64_t))
|
||||
{
|
||||
if (rhs.out_reference.type() == typeid(uint64_t))
|
||||
return boost::get<uint64_t>(lhs.out_reference) < boost::get<uint64_t>(rhs.out_reference);
|
||||
if (rhs.out_reference.type() == typeid(ref_by_id))
|
||||
return true;
|
||||
CHECK_AND_ASSERT_THROW_MES(false, "unexpected type in out_reference 1: " << rhs.out_reference.type().name());
|
||||
}
|
||||
else if (lhs.out_reference.type() == typeid(ref_by_id))
|
||||
{
|
||||
if (rhs.out_reference.type() == typeid(uint64_t))
|
||||
return false;
|
||||
if (rhs.out_reference.type() == typeid(ref_by_id))
|
||||
return false; // don't change the order of ref_by_id elements
|
||||
CHECK_AND_ASSERT_THROW_MES(false, "unexpected type in out_reference 2: " << rhs.out_reference.type().name());
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// restore index of the selected element, if needed
|
||||
if (old_real_index != SIZE_MAX)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(old_real_index < outputs.size(), "old_real_index is OOB");
|
||||
auto it = std::find(result.begin(), result.end(), outputs[old_real_index]);
|
||||
CHECK_AND_ASSERT_THROW_MES(it != result.end(), "internal error: cannot find old_real_index");
|
||||
new_real_index = it - result.begin();
|
||||
}
|
||||
|
||||
// find the last uint64_t entry - skip ref_by_id entries goint from the end to the beginnning
|
||||
size_t i = result.size() - 1;
|
||||
while (i != 0 && result[i].out_reference.type() == typeid(ref_by_id))
|
||||
--i;
|
||||
|
||||
for (; i != 0; i--)
|
||||
{
|
||||
boost::get<uint64_t>(result[i].out_reference) -= boost::get<uint64_t>(result[i - 1].out_reference);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
CATCH_ENTRY2(std::vector<tx_source_entry::output_entry>{});
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool validate_tx_output_details_againt_tx_generation_context(const transaction& tx, const tx_generation_context& gen_context)
|
||||
{
|
||||
//TODO: Implement this function before mainnet
|
||||
#ifdef TESTNET
|
||||
return true;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string transform_tx_to_str(const currency::transaction& tx)
|
||||
{
|
||||
return currency::obj_to_json_str(tx);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
transaction transform_str_to_tx(const std::string& tx_str)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(false, "transform_str_to_tx shoruld never be called");
|
||||
return transaction();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2018-2019 Zano Project
|
||||
// Copyright (c) 2018-2023 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
|
@ -16,26 +16,60 @@ namespace currency
|
|||
{
|
||||
struct tx_source_entry
|
||||
{
|
||||
typedef serializable_pair<txout_ref_v, crypto::public_key> output_entry; // txout_v is either global output index or ref_by_id; public_key - is output ephemeral pub key
|
||||
struct output_entry
|
||||
{
|
||||
output_entry() = default;
|
||||
output_entry(const output_entry &) = default;
|
||||
output_entry(const txout_ref_v& out_reference, const crypto::public_key& stealth_address)
|
||||
: out_reference(out_reference), stealth_address(stealth_address), concealing_point(null_pkey), amount_commitment(null_pkey) {}
|
||||
output_entry(const txout_ref_v& out_reference, const crypto::public_key& stealth_address, const crypto::public_key& concealing_point, const crypto::public_key& amount_commitment, const crypto::public_key& blinded_asset_id)
|
||||
: out_reference(out_reference), stealth_address(stealth_address), concealing_point(concealing_point), amount_commitment(amount_commitment), blinded_asset_id(blinded_asset_id) {}
|
||||
|
||||
std::vector<output_entry> outputs; //index + key
|
||||
uint64_t real_output; //index in outputs vector of real output_entry
|
||||
crypto::public_key real_out_tx_key; //real output's transaction's public key
|
||||
size_t real_output_in_tx_index; //index in transaction outputs vector
|
||||
uint64_t amount; //money
|
||||
uint64_t transfer_index; //money
|
||||
crypto::hash multisig_id; //if txin_multisig: multisig output id
|
||||
size_t ms_sigs_count; //if txin_multisig: must be equal to output's minimum_sigs
|
||||
size_t ms_keys_count; //if txin_multisig: must be equal to size of output's keys container
|
||||
bool separately_signed_tx_complete; //for separately signed tx only: denotes the last source entry in complete tx to explicitly mark the final step of tx creation
|
||||
std::string htlc_origin; //for htlc, specify origin
|
||||
txout_ref_v out_reference; // either global output index or ref_by_id
|
||||
crypto::public_key stealth_address; // a.k.a output's one-time public key
|
||||
crypto::public_key concealing_point; // only for ZC outputs
|
||||
crypto::public_key amount_commitment; // only for ZC outputs
|
||||
crypto::public_key blinded_asset_id; // only for ZC outputs
|
||||
|
||||
bool is_multisig() const { return ms_sigs_count > 0; }
|
||||
bool operator==(const output_entry& rhs) const { return out_reference == rhs.out_reference; } // used in prepare_outputs_entries_for_key_offsets, it's okay to do partially comparison
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(out_reference)
|
||||
FIELD(stealth_address)
|
||||
FIELD(concealing_point)
|
||||
FIELD(amount_commitment)
|
||||
FIELD(blinded_asset_id)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
//typedef serializable_pair<txout_ref_v, crypto::public_key> output_entry; // txout_ref_v is either global output index or ref_by_id; public_key - is output's stealth address
|
||||
|
||||
std::vector<output_entry> outputs;
|
||||
uint64_t real_output = 0; //index in outputs vector of real output_entry
|
||||
crypto::public_key real_out_tx_key = currency::null_pkey; //real output's transaction's public key
|
||||
crypto::scalar_t real_out_amount_blinding_mask = 0; //blinding mask of real out's amount committment (only for ZC inputs, otherwise must be 0)
|
||||
crypto::scalar_t real_out_asset_id_blinding_mask = 0; //blinding mask of real out's asset_od (only for ZC inputs, otherwise must be 0)
|
||||
size_t real_output_in_tx_index = 0; //index in transaction outputs vector
|
||||
uint64_t amount = 0; //money
|
||||
uint64_t transfer_index = 0; //index in m_transfers
|
||||
crypto::hash multisig_id = currency::null_hash; //if txin_multisig: multisig output id
|
||||
size_t ms_sigs_count = 0; //if txin_multisig: must be equal to output's minimum_sigs
|
||||
size_t ms_keys_count = 0; //if txin_multisig: must be equal to size of output's keys container
|
||||
bool separately_signed_tx_complete = false; //for separately signed tx only: denotes the last source entry in complete tx to explicitly mark the final step of tx creation
|
||||
std::string htlc_origin; //for htlc, specify origin
|
||||
crypto::public_key asset_id = currency::native_coin_asset_id; //asset id (not blinded, not premultiplied by 1/8) TODO @#@# consider changing to crypto::point_t
|
||||
|
||||
bool is_multisig() const { return ms_sigs_count > 0; }
|
||||
bool is_zc() const { return !real_out_amount_blinding_mask.is_zero(); }
|
||||
bool is_native_coin() const { return asset_id == currency::native_coin_asset_id; }
|
||||
uint64_t amount_for_global_output_index() const { return is_zc() ? 0 : amount; } // amount value for global outputs index, it's zero for outputs with hidden amounts
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(outputs)
|
||||
FIELD(real_output)
|
||||
FIELD(real_out_tx_key)
|
||||
FIELD(real_out_amount_blinding_mask)
|
||||
FIELD(real_out_asset_id_blinding_mask)
|
||||
FIELD(real_output_in_tx_index)
|
||||
FIELD(amount)
|
||||
FIELD(transfer_index)
|
||||
|
|
@ -51,8 +85,8 @@ namespace currency
|
|||
//if this struct is present, then creating htlc out, expiration -> number of blocks that htlc proposal is active
|
||||
struct destination_option_htlc_out
|
||||
{
|
||||
uint64_t expiration;
|
||||
crypto::hash htlc_hash;
|
||||
uint64_t expiration = 0;
|
||||
crypto::hash htlc_hash = currency::null_hash;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(expiration)
|
||||
|
|
@ -61,20 +95,34 @@ namespace currency
|
|||
};
|
||||
|
||||
|
||||
enum tx_destination_entry_flags
|
||||
{
|
||||
tdef_none = 0,
|
||||
tdef_explicit_native_asset_id = 0x0001,
|
||||
tdef_explicit_amount_to_provide = 0x0002,
|
||||
tdef_zero_amount_blinding_mask = 0x0004 // currently it's only used for burning native coins
|
||||
};
|
||||
|
||||
struct tx_destination_entry
|
||||
{
|
||||
uint64_t amount; //money
|
||||
std::list<account_public_address> addr; //destination address, in case of 1 address - txout_to_key, in case of more - txout_multisig
|
||||
size_t minimum_sigs; //if txout_multisig: minimum signatures that are required to spend this output (minimum_sigs <= addr.size()) IF txout_to_key - not used
|
||||
uint64_t amount_to_provide; //amount money that provided by initial creator of tx, used with partially created transactions
|
||||
uint64_t unlock_time;
|
||||
destination_option_htlc_out htlc_options; //htlc options
|
||||
uint64_t amount = 0; // money
|
||||
std::list<account_public_address> addr; // destination address, in case of 1 address - txout_to_key, in case of more - txout_multisig
|
||||
size_t minimum_sigs = 0; // if txout_multisig: minimum signatures that are required to spend this output (minimum_sigs <= addr.size()) IF txout_to_key - not used
|
||||
uint64_t amount_to_provide = 0; // amount money that provided by initial creator of tx, used with partially created transactions
|
||||
uint64_t unlock_time = 0;
|
||||
destination_option_htlc_out htlc_options; // htlc options
|
||||
crypto::public_key asset_id = currency::native_coin_asset_id; // not blinded, not premultiplied
|
||||
uint64_t flags = 0; // set of flags (see tx_destination_entry_flags)
|
||||
|
||||
|
||||
tx_destination_entry() : amount(0), minimum_sigs(0), amount_to_provide(0), unlock_time(0), htlc_options(destination_option_htlc_out()){}
|
||||
tx_destination_entry(uint64_t a, const account_public_address& ad) : amount(a), addr(1, ad), minimum_sigs(0), amount_to_provide(0), unlock_time(0), htlc_options(destination_option_htlc_out()) {}
|
||||
tx_destination_entry(uint64_t a, const account_public_address& ad, uint64_t ut) : amount(a), addr(1, ad), minimum_sigs(0), amount_to_provide(0), unlock_time(ut), htlc_options(destination_option_htlc_out()) {}
|
||||
tx_destination_entry(uint64_t a, const std::list<account_public_address>& addr) : amount(a), addr(addr), minimum_sigs(addr.size()), amount_to_provide(0), unlock_time(0), htlc_options(destination_option_htlc_out()) {}
|
||||
tx_destination_entry() = default;
|
||||
tx_destination_entry(uint64_t a, const account_public_address& ad) : amount(a), addr(1, ad) {}
|
||||
tx_destination_entry(uint64_t a, const account_public_address& ad, const crypto::public_key& aid) : amount(a), addr(1, ad), asset_id(aid) {}
|
||||
tx_destination_entry(uint64_t a, const account_public_address& ad, uint64_t ut) : amount(a), addr(1, ad), unlock_time(ut) {}
|
||||
tx_destination_entry(uint64_t a, const std::list<account_public_address>& addr) : amount(a), addr(addr), minimum_sigs(addr.size()){}
|
||||
tx_destination_entry(uint64_t a, const std::list<account_public_address>& addr, const crypto::public_key& aid) : amount(a), addr(addr), minimum_sigs(addr.size()), asset_id(aid) {}
|
||||
|
||||
bool is_native_coin() const { return asset_id == currency::native_coin_asset_id; }
|
||||
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(amount)
|
||||
|
|
@ -83,9 +131,41 @@ namespace currency
|
|||
FIELD(amount_to_provide)
|
||||
FIELD(unlock_time)
|
||||
FIELD(htlc_options)
|
||||
FIELD(asset_id)
|
||||
FIELD(flags)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------
|
||||
template<class variant_t, class variant_type_t>
|
||||
void update_or_add_field_to_extra(std::vector<variant_t>& variant_container, const variant_type_t& v)
|
||||
{
|
||||
for (auto& ev : variant_container)
|
||||
{
|
||||
if (ev.type() == typeid(variant_type_t))
|
||||
{
|
||||
boost::get<variant_type_t>(ev) = v;
|
||||
return;
|
||||
}
|
||||
}
|
||||
variant_container.push_back(v);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<class variant_type_t, class variant_t>
|
||||
void remove_field_of_type_from_extra(std::vector<variant_t>& variant_container)
|
||||
{
|
||||
for (size_t i = 0; i != variant_container.size();)
|
||||
{
|
||||
if (variant_container[i].type() == typeid(variant_type_t))
|
||||
{
|
||||
variant_container.erase(variant_container.begin()+i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<class extra_type_t>
|
||||
uint64_t get_tx_x_detail(const transaction& tx)
|
||||
{
|
||||
|
|
@ -93,6 +173,7 @@ namespace currency
|
|||
get_type_in_variant_container(tx.extra, e);
|
||||
return e.v;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<class extra_type_t>
|
||||
void set_tx_x_detail(transaction& tx, uint64_t v)
|
||||
{
|
||||
|
|
@ -100,7 +181,7 @@ namespace currency
|
|||
e.v = v;
|
||||
update_or_add_field_to_extra(tx.extra, e);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
uint64_t get_tx_unlock_time(const transaction& tx, uint64_t o_i);
|
||||
uint64_t get_tx_max_unlock_time(const transaction& tx);
|
||||
bool get_tx_max_min_unlock_time(const transaction& tx, uint64_t& max_unlock_time, uint64_t& min_unlock_time);
|
||||
|
|
@ -128,6 +209,145 @@ namespace currency
|
|||
blobdata tx_to_blob(const transaction& b);
|
||||
bool tx_to_blob(const transaction& b, blobdata& b_blob);
|
||||
bool read_keyimages_from_tx(const transaction& tx, std::list<crypto::key_image>& kil);
|
||||
bool validate_inputs_sorting(const transaction& tx);
|
||||
bool is_asset_emitting_transaction(const transaction& tx, asset_descriptor_operation* p_ado = nullptr);
|
||||
|
||||
std::vector<tx_source_entry::output_entry> prepare_outputs_entries_for_key_offsets(const std::vector<tx_source_entry::output_entry>& outputs, size_t old_real_index, size_t& new_real_index) noexcept;
|
||||
|
||||
|
||||
}
|
||||
struct tx_generation_context
|
||||
{
|
||||
tx_generation_context() = default;
|
||||
|
||||
void resize(size_t zc_ins_count, size_t outs_count)
|
||||
{
|
||||
asset_ids.resize(outs_count);
|
||||
blinded_asset_ids.resize(outs_count);
|
||||
amount_commitments.resize(outs_count);
|
||||
asset_id_blinding_masks.resize(outs_count);
|
||||
amounts.resize(outs_count);
|
||||
amount_blinding_masks.resize(outs_count);
|
||||
zc_input_amounts.resize(zc_ins_count);
|
||||
}
|
||||
|
||||
// TODO @#@# reconsider this check -- sowle
|
||||
bool check_sizes(size_t zc_ins_count, size_t outs_count) const
|
||||
{
|
||||
return
|
||||
pseudo_outs_blinded_asset_ids.size() == zc_ins_count &&
|
||||
asset_ids.size() == outs_count &&
|
||||
blinded_asset_ids.size() == outs_count &&
|
||||
amount_commitments.size() == outs_count &&
|
||||
asset_id_blinding_masks.size() == outs_count &&
|
||||
amounts.size() == outs_count &&
|
||||
amount_blinding_masks.size() == outs_count;
|
||||
}
|
||||
|
||||
void set_tx_key(const keypair& kp)
|
||||
{
|
||||
tx_key = kp;
|
||||
tx_pub_key_p = crypto::point_t(tx_key.pub);
|
||||
}
|
||||
|
||||
// per output data
|
||||
std::vector<crypto::point_t> asset_ids;
|
||||
std::vector<crypto::point_t> blinded_asset_ids; // generate_zc_outs_range_proof
|
||||
std::vector<crypto::point_t> amount_commitments; // generate_zc_outs_range_proof construct_tx_out
|
||||
crypto::scalar_vec_t asset_id_blinding_masks; // construct_tx_out
|
||||
crypto::scalar_vec_t amounts; // generate_zc_outs_range_proof
|
||||
crypto::scalar_vec_t amount_blinding_masks; // generate_zc_outs_range_proof
|
||||
|
||||
// per zc input data
|
||||
std::vector<crypto::point_t> pseudo_outs_blinded_asset_ids; // generate_asset_surjection_proof
|
||||
crypto::scalar_vec_t pseudo_outs_plus_real_out_blinding_masks; // r_pi + r'_j // generate_asset_surjection_proof
|
||||
std::vector<crypto::point_t> real_zc_ins_asset_ids; // H_i // generate_asset_surjection_proof
|
||||
std::vector<uint64_t> zc_input_amounts; // ZC only input amounts
|
||||
|
||||
// common data: inputs
|
||||
crypto::point_t pseudo_out_amount_commitments_sum = crypto::c_point_0; // generate_tx_balance_proof generate_ZC_sig
|
||||
crypto::scalar_t pseudo_out_amount_blinding_masks_sum = 0; // generate_ZC_sig
|
||||
crypto::scalar_t real_in_asset_id_blinding_mask_x_amount_sum = 0; // = sum( real_out_blinding_mask[i] * amount[i] ) generate_tx_balance_proof generate_ZC_sig
|
||||
|
||||
// common data: outputs
|
||||
crypto::point_t amount_commitments_sum = crypto::c_point_0; // generate_tx_balance_proof
|
||||
crypto::scalar_t amount_blinding_masks_sum = 0; // construct_tx_out generate_tx_balance_proof generate_ZC_sig
|
||||
crypto::scalar_t asset_id_blinding_mask_x_amount_sum = 0; // = sum( blinding_mask[j] * amount[j] ) generate_tx_balance_proof
|
||||
|
||||
// data for ongoing asset operation in tx (if applicable, tx extra should contain asset_descriptor_operation)
|
||||
crypto::public_key ao_asset_id {};
|
||||
crypto::point_t ao_asset_id_pt = crypto::c_point_0;
|
||||
crypto::point_t ao_amount_commitment = crypto::c_point_0;
|
||||
crypto::scalar_t ao_amount_blinding_mask {}; // generate_tx_balance_proof generate_ZC_sig
|
||||
bool ao_commitment_in_outputs = false;
|
||||
|
||||
// per tx data
|
||||
keypair tx_key {}; //
|
||||
crypto::point_t tx_pub_key_p = crypto::c_point_0; // == tx_key.pub
|
||||
|
||||
// consider redesign, some data may possibly be excluded from kv serialization -- sowle
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(asset_ids)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(blinded_asset_ids)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(amount_commitments)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(asset_id_blinding_masks)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(amounts)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(amount_blinding_masks)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(pseudo_outs_blinded_asset_ids)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(pseudo_outs_plus_real_out_blinding_masks)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(real_zc_ins_asset_ids)
|
||||
KV_SERIALIZE(zc_input_amounts)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(pseudo_out_amount_commitments_sum)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(pseudo_out_amount_blinding_masks_sum)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(real_in_asset_id_blinding_mask_x_amount_sum)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(amount_commitments_sum)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(amount_blinding_masks_sum)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(asset_id_blinding_mask_x_amount_sum)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_asset_id)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_asset_id_pt)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_amount_commitment)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_amount_blinding_mask)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_commitment_in_outputs)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(tx_key)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(tx_pub_key_p)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
||||
// solely for consolidated txs, asset opration fields are not serialized
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
VERSION(0)
|
||||
FIELD(asset_ids)
|
||||
FIELD(blinded_asset_ids)
|
||||
FIELD(amount_commitments)
|
||||
FIELD((std::vector<crypto::scalar_t>&)(asset_id_blinding_masks))
|
||||
FIELD((std::vector<crypto::scalar_t>&)(amounts))
|
||||
FIELD((std::vector<crypto::scalar_t>&)(amount_blinding_masks))
|
||||
FIELD(pseudo_outs_blinded_asset_ids)
|
||||
FIELD((std::vector<crypto::scalar_t>&)(pseudo_outs_plus_real_out_blinding_masks))
|
||||
FIELD(real_zc_ins_asset_ids)
|
||||
FIELD(zc_input_amounts)
|
||||
FIELD(pseudo_out_amount_commitments_sum)
|
||||
FIELD(pseudo_out_amount_blinding_masks_sum)
|
||||
FIELD(real_in_asset_id_blinding_mask_x_amount_sum)
|
||||
FIELD(amount_commitments_sum)
|
||||
FIELD(amount_blinding_masks_sum)
|
||||
FIELD(asset_id_blinding_mask_x_amount_sum)
|
||||
|
||||
// no asset operation fields here
|
||||
//ao_asset_id
|
||||
//ao_asset_id_pt
|
||||
//ao_amount_commitment
|
||||
//ao_amount_blinding_mask
|
||||
//ao_commitment_in_outputs
|
||||
|
||||
FIELD(tx_key.pub) // TODO: change to sane serialization FIELD(tx_key)
|
||||
FIELD(tx_key.sec)
|
||||
FIELD(tx_pub_key_p)
|
||||
END_SERIALIZE()
|
||||
}; // struct tx_generation_context
|
||||
|
||||
bool validate_tx_output_details_againt_tx_generation_context(const transaction& tx, const tx_generation_context& gen_context);
|
||||
std::string transform_tx_to_str(const transaction& tx);
|
||||
transaction transform_str_to_tx(const std::string& tx_str);
|
||||
|
||||
|
||||
|
||||
} // namespace currency
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ namespace currency {
|
|||
return res.convert_to<wide_difficulty_type>();
|
||||
}
|
||||
|
||||
wide_difficulty_type next_difficulty_1(vector<uint64_t>& timestamps, vector<wide_difficulty_type>& cumulative_difficulties, size_t target_seconds)
|
||||
wide_difficulty_type next_difficulty_1(vector<uint64_t>& timestamps, vector<wide_difficulty_type>& cumulative_difficulties, size_t target_seconds, const wide_difficulty_type& difficulty_starter)
|
||||
{
|
||||
|
||||
// timestamps - first is latest, back - is oldest timestamps
|
||||
|
|
@ -194,7 +194,7 @@ namespace currency {
|
|||
CHECK_AND_ASSERT_MES(length == cumulative_difficulties.size(), 0, "Check \"length == cumulative_difficulties.size()\" failed");
|
||||
if (length <= 1)
|
||||
{
|
||||
return DIFFICULTY_STARTER;
|
||||
return difficulty_starter;
|
||||
}
|
||||
static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small");
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ namespace currency {
|
|||
return summ / devider;
|
||||
}
|
||||
|
||||
wide_difficulty_type next_difficulty_2(vector<uint64_t>& timestamps, vector<wide_difficulty_type>& cumulative_difficulties, size_t target_seconds)
|
||||
wide_difficulty_type next_difficulty_2(vector<uint64_t>& timestamps, vector<wide_difficulty_type>& cumulative_difficulties, size_t target_seconds, const wide_difficulty_type& difficulty_starter)
|
||||
{
|
||||
|
||||
// timestamps - first is latest, back - is oldest timestamps
|
||||
|
|
@ -236,7 +236,7 @@ namespace currency {
|
|||
CHECK_AND_ASSERT_MES(length == cumulative_difficulties.size(), 0, "Check \"length == cumulative_difficulties.size()\" failed");
|
||||
if (length <= 1)
|
||||
{
|
||||
return DIFFICULTY_STARTER;
|
||||
return difficulty_starter;
|
||||
}
|
||||
static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small");
|
||||
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ namespace currency
|
|||
typedef boost::multiprecision::uint128_t wide_difficulty_type;
|
||||
|
||||
bool check_hash(const crypto::hash &hash, wide_difficulty_type difficulty);
|
||||
wide_difficulty_type next_difficulty_1(std::vector<std::uint64_t>& timestamps, std::vector<wide_difficulty_type>& cumulative_difficulties, size_t target_seconds);
|
||||
wide_difficulty_type next_difficulty_2(std::vector<std::uint64_t>& timestamps, std::vector<wide_difficulty_type>& cumulative_difficulties, size_t target_seconds);
|
||||
wide_difficulty_type next_difficulty_1(std::vector<std::uint64_t>& timestamps, std::vector<wide_difficulty_type>& cumulative_difficulties, size_t target_seconds, const wide_difficulty_type& difficulty_starter);
|
||||
wide_difficulty_type next_difficulty_2(std::vector<std::uint64_t>& timestamps, std::vector<wide_difficulty_type>& cumulative_difficulties, size_t target_seconds, const wide_difficulty_type& difficulty_starter);
|
||||
uint64_t difficulty_to_boundary(wide_difficulty_type difficulty);
|
||||
void difficulty_to_boundary_long(wide_difficulty_type difficulty, crypto::hash& result);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#define CORE_EVENT_ADD_ALIAS "CORE_EVENT_ADD_ALIAS"
|
||||
#define CORE_EVENT_UPDATE_ALIAS "CORE_EVENT_UPDATE_ALIAS"
|
||||
#define CORE_EVENT_BLOCK_ADDED "CORE_EVENT_BLOCK_ADDED"
|
||||
#define CORE_EVENT_ADD_ASSET "CORE_EVENT_ADD_ASSET"
|
||||
|
||||
|
||||
namespace currency
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ namespace currency
|
|||
crypto::hash h = get_block_longhash(height, bd_hash, bl.nonce);
|
||||
if(check_hash(h, diffic))
|
||||
{
|
||||
LOG_PRINT_L0("Found nonce for block: " << get_block_hash(bl) << "[" << height << "]: PoW:" << h << "(diff:" << diffic << "), ts: " << bl.timestamp);
|
||||
LOG_PRINT_L1("Found nonce for block: " << get_block_hash(bl) << "[" << height << "]: PoW:" << h << " (diff:" << diffic << "), ts: " << bl.timestamp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -92,7 +92,7 @@ namespace currency
|
|||
|
||||
|
||||
volatile uint32_t m_stop;
|
||||
::critical_section m_template_lock;
|
||||
epee::critical_section m_template_lock;
|
||||
block m_template;
|
||||
std::atomic<uint32_t> m_template_no;
|
||||
std::atomic<uint32_t> m_starter_nonce;
|
||||
|
|
@ -101,15 +101,15 @@ namespace currency
|
|||
volatile uint32_t m_thread_index;
|
||||
volatile uint32_t m_threads_total;
|
||||
std::atomic<int32_t> m_pausers_count;
|
||||
::critical_section m_miners_count_lock;
|
||||
epee::critical_section m_miners_count_lock;
|
||||
|
||||
std::list<boost::thread> m_threads;
|
||||
::critical_section m_threads_lock;
|
||||
epee::critical_section m_threads_lock;
|
||||
i_miner_handler* m_phandler;
|
||||
//blockchain_storage& m_bc;
|
||||
account_public_address m_mine_address;
|
||||
math_helper::once_a_time_seconds<5> m_update_block_template_interval;
|
||||
math_helper::once_a_time_seconds<2> m_update_merge_hr_interval;
|
||||
epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval;
|
||||
epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval;
|
||||
std::vector<blobdata> m_extra_messages;
|
||||
miner_config m_config;
|
||||
std::string m_config_folder;
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ namespace bc_services
|
|||
{
|
||||
|
||||
//fields filled in UI
|
||||
uint8_t offer_type; // OFFER_TYPE_PRIMARY_TO_TARGET(SELL ORDER) - 0, OFFER_TYPE_TARGET_TO_PRIMARY(BUY ORDER) - 1 etc.
|
||||
uint64_t amount_primary; // amount of the currency
|
||||
uint64_t amount_target; // amount of other currency or goods
|
||||
uint8_t offer_type = 0; // OFFER_TYPE_PRIMARY_TO_TARGET(SELL ORDER) - 0, OFFER_TYPE_TARGET_TO_PRIMARY(BUY ORDER) - 1 etc.
|
||||
uint64_t amount_primary = 0; // amount of the currency
|
||||
uint64_t amount_target = 0; // amount of other currency or goods
|
||||
std::string bonus; //
|
||||
std::string target; // [] currency / goods
|
||||
std::string primary; // currency for goods
|
||||
|
|
@ -33,7 +33,7 @@ namespace bc_services
|
|||
std::string deal_option; // []full amount, by parts
|
||||
std::string category; // []
|
||||
std::string preview_url; // []
|
||||
uint8_t expiration_time; // n-days
|
||||
uint8_t expiration_time = 0; // n-days
|
||||
//-----------------
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
|
|
|
|||
108
src/currency_core/pos_mining.cpp
Normal file
108
src/currency_core/pos_mining.cpp
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// Copyright (c) 2022 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
#include "currency_basic.h"
|
||||
#include "difficulty.h"
|
||||
#include "pos_mining.h"
|
||||
#include "wallet/wallet2.h"
|
||||
#include "crypto/zarcanum.h"
|
||||
#include "crypto_config.h"
|
||||
|
||||
namespace currency
|
||||
{
|
||||
void pos_mining_context::init(const wide_difficulty_type& pos_diff, const stake_modifier_type& sm, bool is_zarcanum)
|
||||
{
|
||||
this->basic_diff = pos_diff;
|
||||
this->sk.stake_modifier = sm;
|
||||
this->zarcanum = is_zarcanum;
|
||||
|
||||
if (is_zarcanum)
|
||||
{
|
||||
this->last_pow_block_id_hashed = crypto::hash_helper_t::hs(CRYPTO_HDS_ZARCANUM_LAST_POW_HASH, this->sk.stake_modifier.last_pow_id);
|
||||
this->z_l_div_z_D = crypto::zarcanum_precalculate_z_l_div_z_D(this->basic_diff);
|
||||
}
|
||||
}
|
||||
|
||||
void pos_mining_context::prepare_entry(uint64_t stake_amount, const crypto::key_image& stake_out_ki, const crypto::public_key& stake_source_tx_pub_key, uint64_t stake_out_in_tx_index,
|
||||
const crypto::scalar_t& stake_out_amount_blinding_mask, const crypto::secret_key& view_secret)
|
||||
{
|
||||
this->stake_amount = stake_amount;
|
||||
this->sk.kimage = stake_out_ki;
|
||||
|
||||
if (this->zarcanum)
|
||||
{
|
||||
crypto::scalar_t v = view_secret;
|
||||
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
|
||||
bool r = crypto::generate_key_derivation(stake_source_tx_pub_key, view_secret, derivation); // 8 * v * R
|
||||
CHECK_AND_ASSERT_MES_NO_RET(r, "generate_key_derivation failed");
|
||||
crypto::scalar_t h = AUTO_VAL_INIT(h);
|
||||
crypto::derivation_to_scalar(derivation, stake_out_in_tx_index, h.as_secret_key()); // h = Hs(8 * v * R, i)
|
||||
|
||||
// q = Hs(domain_sep, Hs(8 * v * R, i) ) * 8 * v
|
||||
this->secret_q = v * 8 * crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_CONCEALING_POINT, h);
|
||||
this->stake_out_amount_blinding_mask = stake_out_amount_blinding_mask;
|
||||
}
|
||||
}
|
||||
|
||||
bool pos_mining_context::do_iteration(uint64_t ts)
|
||||
{
|
||||
// update stake kernel and calculate it's hash
|
||||
this->sk.block_timestamp = ts;
|
||||
{
|
||||
PROFILE_FUNC("calc_hash");
|
||||
this->kernel_hash = crypto::cn_fast_hash(&this->sk, sizeof(this->sk));
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
|
||||
if (this->zarcanum /* && td.is_zc() */)
|
||||
{
|
||||
crypto::mp::uint256_t lhs;
|
||||
crypto::mp::uint512_t rhs;
|
||||
{
|
||||
PROFILE_FUNC("check_zarcanum");
|
||||
found = crypto::zarcanum_check_main_pos_inequality(this->kernel_hash, this->stake_out_amount_blinding_mask, this->secret_q, this->last_pow_block_id_hashed, this->z_l_div_z_D, this->stake_amount, lhs, rhs);
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
found = true;
|
||||
const boost::multiprecision::uint256_t d_mp = lhs / (crypto::c_zarcanum_z_coeff_mp * this->stake_amount) + 1;
|
||||
const boost::multiprecision::uint256_t ba = d_mp * crypto::c_zarcanum_z_coeff_mp * this->stake_amount - lhs;
|
||||
const boost::multiprecision::uint256_t l_div_z_D = this->z_l_div_z_D / crypto::c_zarcanum_z_coeff_mp;
|
||||
LOG_PRINT_GREEN("Found Zarcanum kernel: amount: " << currency::print_money_brief(this->stake_amount) << /* ", gindex: " << td.m_global_output_index << */ ENDL
|
||||
<< "difficulty: " << this->basic_diff << ENDL
|
||||
<< "kernel info: " << ENDL
|
||||
<< print_stake_kernel_info(this->sk)
|
||||
<< "kernel_hash: " << this->kernel_hash << ENDL
|
||||
<< "lhs: 0x" << crypto::scalar_t(lhs).to_string_as_hex_number() << " = 0x" << std::hex << d_mp << " * 2^64 * " << this->stake_amount << " - 0x" << std::hex << ba << ENDL
|
||||
<< "rhs: 0x" << crypto::scalar_t(rhs).to_string_as_hex_number() << ENDL
|
||||
<< "d: 0x" << std::hex << d_mp << ENDL
|
||||
<< "l / floor(z * D): 0x" << std::hex << l_div_z_D
|
||||
, LOG_LEVEL_0);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// old PoS with non-hidden amounts
|
||||
currency::wide_difficulty_type final_diff = this->basic_diff / this->stake_amount;
|
||||
{
|
||||
PROFILE_FUNC("check_hash");
|
||||
found = currency::check_hash(this->kernel_hash, final_diff);
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
LOG_PRINT_GREEN("Found kernel: amount: " << currency::print_money_brief(this->stake_amount)<< /* ", gindex: " << td.m_global_output_index << */ ENDL
|
||||
<< "difficulty: " << this->basic_diff << ", final_diff: " << final_diff << ENDL
|
||||
<< "kernel info: " << ENDL
|
||||
<< print_stake_kernel_info(this->sk)
|
||||
<< "kernel_hash(proof): " << this->kernel_hash,
|
||||
LOG_LEVEL_0);
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
}; // namespace currency
|
||||
32
src/currency_core/pos_mining.h
Normal file
32
src/currency_core/pos_mining.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) 2022 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
namespace currency
|
||||
{
|
||||
|
||||
struct pos_mining_context
|
||||
{
|
||||
// Zarcanum notation:
|
||||
wide_difficulty_type basic_diff; // D
|
||||
stake_kernel sk;
|
||||
crypto::scalar_t last_pow_block_id_hashed; // f'
|
||||
crypto::scalar_t secret_q; // q
|
||||
boost::multiprecision::uint256_t z_l_div_z_D; // z * floor( l / (z * D) ) (max possible value (assuming z=2^64) : z * 2^252 / (z * 1) ~= 2^252)
|
||||
crypto::hash kernel_hash; // h
|
||||
crypto::scalar_t stake_out_amount_blinding_mask; // f
|
||||
uint64_t stake_amount; // a
|
||||
|
||||
bool zarcanum; // false for pre-HF4 classic PoS with explicit amounts
|
||||
|
||||
void init(const wide_difficulty_type& pos_diff, const stake_modifier_type& sm, bool is_zarcanum);
|
||||
|
||||
void prepare_entry(uint64_t stake_amount, const crypto::key_image& stake_out_ki, const crypto::public_key& stake_source_tx_pub_key, uint64_t stake_out_in_tx_index,
|
||||
const crypto::scalar_t& stake_out_blinding_mask, const crypto::secret_key& view_secret);
|
||||
|
||||
bool do_iteration(uint64_t ts);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
#include "crypto/hash.h"
|
||||
#include "profile_tools.h"
|
||||
#include "common/db_backend_selector.h"
|
||||
#include "tx_semantic_validation.h"
|
||||
|
||||
DISABLE_VS_WARNINGS(4244 4345 4503) //'boost::foreach_detail_::or_' : decorated name length exceeded, name was truncated
|
||||
|
||||
|
|
@ -40,6 +41,8 @@ DISABLE_VS_WARNINGS(4244 4345 4503) //'boost::foreach_detail_::or_' : decorated
|
|||
#define LOG_DEFAULT_CHANNEL "tx_pool"
|
||||
ENABLE_CHANNEL_BY_DEFAULT("tx_pool");
|
||||
|
||||
using namespace epee;
|
||||
|
||||
namespace currency
|
||||
{
|
||||
//---------------------------------------------------------------------------------
|
||||
|
|
@ -90,8 +93,23 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::check_tx_fee(const transaction &tx, uint64_t amount_fee)
|
||||
{
|
||||
if (amount_fee < m_blockchain.get_core_runtime_config().tx_pool_min_fee)
|
||||
return false;
|
||||
|
||||
//m_blockchain.get
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::add_tx(const transaction &tx, const crypto::hash &id, uint64_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool from_core)
|
||||
{
|
||||
{
|
||||
bool r = false;
|
||||
|
||||
// defaults
|
||||
tvc.m_added_to_pool = false;
|
||||
tvc.m_verification_failed = true;
|
||||
|
||||
if (!kept_by_block && !from_core && m_blockchain.is_in_checkpoint_zone())
|
||||
{
|
||||
// BCS is in CP zone, tx verification is impossible until it gets synchronized
|
||||
|
|
@ -102,21 +120,13 @@ namespace currency
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!m_blockchain.validate_tx_for_hardfork_specific_terms(tx, id))
|
||||
{
|
||||
//
|
||||
LOG_ERROR("Transaction " << id <<" doesn't fit current hardfork");
|
||||
tvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
r = m_blockchain.validate_tx_for_hardfork_specific_terms(tx, id);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Transaction " << id <<" doesn't fit current hardfork");
|
||||
|
||||
TIME_MEASURE_START_PD(tx_processing_time);
|
||||
TIME_MEASURE_START_PD(check_inputs_types_supported_time);
|
||||
if(!check_inputs_types_supported(tx))
|
||||
{
|
||||
tvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
r = check_inputs_types_supported(tx);
|
||||
CHECK_AND_ASSERT_MES(r, false, "tx " << id << " has wrong inputs types");
|
||||
TIME_MEASURE_FINISH_PD(check_inputs_types_supported_time);
|
||||
|
||||
TIME_MEASURE_START_PD(expiration_validate_time);
|
||||
|
|
@ -132,61 +142,60 @@ namespace currency
|
|||
}
|
||||
TIME_MEASURE_FINISH_PD(expiration_validate_time);
|
||||
|
||||
|
||||
TIME_MEASURE_START_PD(validate_amount_time);
|
||||
uint64_t inputs_amount = 0;
|
||||
if(!get_inputs_money_amount(tx, inputs_amount))
|
||||
{
|
||||
tvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(tx.vout.size() <= CURRENCY_TX_MAX_ALLOWED_OUTS, false, "transaction has too many outs = " << tx.vout.size());
|
||||
|
||||
CHECK_AND_ASSERT_MES_CUSTOM(tx.vout.size() <= CURRENCY_TX_MAX_ALLOWED_OUTS, false, tvc.m_verification_failed = true, "transaction has too many outs = " << tx.vout.size());
|
||||
uint64_t tx_fee = 0;
|
||||
r = get_tx_fee(tx, tx_fee);
|
||||
CHECK_AND_ASSERT_MES(r, false, "get_tx_fee failed");
|
||||
|
||||
uint64_t outputs_amount = get_outs_money_amount(tx);
|
||||
|
||||
if(outputs_amount > inputs_amount)
|
||||
{
|
||||
LOG_PRINT_L0("transaction use more money then it has: use " << outputs_amount << ", have " << inputs_amount);
|
||||
tvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
// @#@# consider removing the following
|
||||
//if (!check_tx_balance(tx)) // TODO (performance): check_tx_balance calls get_tx_fee as well, consider refactoring -- sowle
|
||||
//{
|
||||
// LOG_PRINT_L0("balance check failed for tx " << id);
|
||||
// tvc.m_verification_failed = true;
|
||||
// return false;
|
||||
//}
|
||||
TIME_MEASURE_FINISH_PD(validate_amount_time);
|
||||
|
||||
TIME_MEASURE_START_PD(validate_alias_time);
|
||||
if (!from_core && !validate_alias_info(tx, kept_by_block))
|
||||
{
|
||||
LOG_PRINT_RED_L0("validate_alias_info failed");
|
||||
tvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
r = from_core || validate_alias_info(tx, kept_by_block);
|
||||
CHECK_AND_ASSERT_MES(r, false, "validate_alias_info failed");
|
||||
TIME_MEASURE_FINISH_PD(validate_alias_time);
|
||||
|
||||
TIME_MEASURE_START_PD(check_keyimages_ws_ms_time);
|
||||
//check key images for transaction if it is not kept by block
|
||||
if(!from_core && !kept_by_block)
|
||||
{
|
||||
crypto::key_image spent_ki = AUTO_VAL_INIT(spent_ki);
|
||||
if(have_tx_keyimges_as_spent(tx, &spent_ki))
|
||||
{
|
||||
LOG_ERROR("Transaction " << id << " uses already spent key image " << spent_ki);
|
||||
|
||||
if(!validate_tx_semantic(tx, blob_size))
|
||||
{
|
||||
// tx semantics check failed
|
||||
LOG_PRINT_RED_L0("Transaction " << id << " semantics check failed ");
|
||||
tvc.m_verification_failed = true;
|
||||
tvc.m_should_be_relayed = false;
|
||||
tvc.m_added_to_pool = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
crypto::key_image spent_ki = AUTO_VAL_INIT(spent_ki);
|
||||
r = !have_tx_keyimges_as_spent(tx, &spent_ki);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Transaction " << id << " uses already spent key image " << spent_ki);
|
||||
|
||||
//transaction spam protection, soft rule
|
||||
uint64_t tx_fee = inputs_amount - outputs_amount;
|
||||
if (tx_fee < m_blockchain.get_core_runtime_config().tx_pool_min_fee)
|
||||
if (!check_tx_fee(tx, tx_fee))
|
||||
{
|
||||
if (is_valid_contract_finalization_tx(tx))
|
||||
{
|
||||
//if (is_valid_contract_finalization_tx(tx))
|
||||
//{
|
||||
// that means tx has less fee then allowed by current tx pull rules, but this transaction is actually
|
||||
// a finalization of contract, and template of this contract finalization tx was prepared actually before
|
||||
// fee rules had been changed, so it's ok, let it in.
|
||||
}
|
||||
else
|
||||
//}
|
||||
//else
|
||||
{
|
||||
// this tx has no fee
|
||||
LOG_PRINT_RED_L0("Transaction with id= " << id << " has too small fee: " << tx_fee << ", expected fee: " << m_blockchain.get_core_runtime_config().tx_pool_min_fee);
|
||||
LOG_PRINT_RED_L0("Transaction " << id << " has too small fee: " << print_money_brief(tx_fee) << ", minimum fee: " << print_money_brief(m_blockchain.get_core_runtime_config().tx_pool_min_fee));
|
||||
tvc.m_verification_failed = false;
|
||||
tvc.m_should_be_relayed = false;
|
||||
tvc.m_added_to_pool = false;
|
||||
|
|
@ -209,13 +218,13 @@ namespace currency
|
|||
bool ch_inp_res = m_blockchain.check_tx_inputs(tx, id, max_used_block_height, max_used_block_id);
|
||||
if (!ch_inp_res && !kept_by_block && !from_core)
|
||||
{
|
||||
LOG_PRINT_L0("tx used wrong inputs, rejected");
|
||||
LOG_PRINT_L0("check_tx_inputs failed, tx rejected");
|
||||
tvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
TIME_MEASURE_FINISH_PD(check_inputs_time);
|
||||
|
||||
do_insert_transaction(tx, id, blob_size, kept_by_block, inputs_amount - outputs_amount, ch_inp_res ? max_used_block_id : null_hash, ch_inp_res ? max_used_block_height : 0);
|
||||
do_insert_transaction(tx, id, blob_size, kept_by_block, tx_fee, ch_inp_res ? max_used_block_id : null_hash, ch_inp_res ? max_used_block_height : 0);
|
||||
|
||||
TIME_MEASURE_FINISH_PD(tx_processing_time);
|
||||
tvc.m_added_to_pool = true;
|
||||
|
|
@ -477,10 +486,10 @@ namespace currency
|
|||
should_be_spent_before_height -= CONFLICT_KEY_IMAGE_SPENT_DEPTH_TO_REMOVE_TX_FROM_POOL;
|
||||
for (auto& in : tx_entry.tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
crypto::key_image ki = AUTO_VAL_INIT(ki);
|
||||
if (get_key_image_from_txin_v(in, ki))
|
||||
{
|
||||
// if at least one key image is spent deep enought -- remove such tx
|
||||
const crypto::key_image& ki = boost::get<txin_to_key>(in).k_image;
|
||||
if (m_blockchain.have_tx_keyimg_as_spent(ki, should_be_spent_before_height))
|
||||
{
|
||||
LOG_PRINT_L0("tx " << h << " is about to be removed from tx pool, reason: ki was spent in the blockchain before height " << should_be_spent_before_height << ", tx age: " << misc_utils::get_time_interval_string(tx_age));
|
||||
|
|
@ -528,7 +537,7 @@ namespace currency
|
|||
txs.push_back(tx_rpc_extended_info());
|
||||
tx_rpc_extended_info& trei = txs.back();
|
||||
trei.blob_size = tx_entry.blob_size;
|
||||
fill_tx_rpc_details(trei, tx_entry.tx, nullptr, h, tx_entry.receive_time, true);
|
||||
m_blockchain.fill_tx_rpc_details(trei, tx_entry.tx, nullptr, h, tx_entry.receive_time, true);
|
||||
return true;
|
||||
});
|
||||
|
||||
|
|
@ -580,7 +589,7 @@ namespace currency
|
|||
txs.push_back(tx_rpc_extended_info());
|
||||
tx_rpc_extended_info& trei = txs.back();
|
||||
trei.blob_size = ptei->blob_size;
|
||||
fill_tx_rpc_details(trei, ptei->tx, nullptr, id, ptei->receive_time, false);
|
||||
m_blockchain.fill_tx_rpc_details(trei, ptei->tx, nullptr, id, ptei->receive_time, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -617,7 +626,7 @@ namespace currency
|
|||
if (!ptei)
|
||||
return false;
|
||||
|
||||
fill_tx_rpc_details(trei, ptei->tx, nullptr, id, ptei->receive_time, false);
|
||||
m_blockchain.fill_tx_rpc_details(trei, ptei->tx, nullptr, id, ptei->receive_time, false);
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
|
|
@ -707,16 +716,15 @@ namespace currency
|
|||
{
|
||||
for(const auto& in : tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
crypto::key_image k_image = AUTO_VAL_INIT(k_image);
|
||||
if (get_key_image_from_txin_v(in, k_image))
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, true);//should never fail
|
||||
if (have_tx_keyimg_as_spent(tokey_in.k_image))
|
||||
if (have_tx_keyimg_as_spent(k_image))
|
||||
{
|
||||
if (p_spent_ki)
|
||||
*p_spent_ki = tokey_in.k_image;
|
||||
*p_spent_ki = k_image;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -727,13 +735,13 @@ namespace currency
|
|||
CRITICAL_REGION_LOCAL(m_key_images_lock);
|
||||
for(const auto& in : tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
crypto::key_image k_image = AUTO_VAL_INIT(k_image);
|
||||
if (get_key_image_from_txin_v(in, k_image))
|
||||
{
|
||||
const txin_to_key& tokey_in = boost::get<txin_to_key>(in);
|
||||
auto& id_set = m_key_images[tokey_in.k_image];
|
||||
auto& id_set = m_key_images[k_image];
|
||||
size_t sz_before = id_set.size();
|
||||
id_set.insert(tx_id);
|
||||
LOG_PRINT_L2("tx pool: key image added: " << tokey_in.k_image << ", from tx " << tx_id << ", counter: " << sz_before << " -> " << id_set.size());
|
||||
LOG_PRINT_L2("tx pool: key image added: " << k_image << ", from tx " << tx_id << ", counter: " << sz_before << " -> " << id_set.size());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -787,11 +795,10 @@ namespace currency
|
|||
CRITICAL_REGION_LOCAL(m_key_images_lock);
|
||||
for(const auto& in : tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
crypto::key_image k_image = AUTO_VAL_INIT(k_image);
|
||||
if (get_key_image_from_txin_v(in, k_image))
|
||||
{
|
||||
const txin_to_key& tokey_in = boost::get<txin_to_key>(in);
|
||||
|
||||
auto it_map = epee::misc_utils::it_get_or_insert_value_initialized(m_key_images, tokey_in.k_image);
|
||||
auto it_map = epee::misc_utils::it_get_or_insert_value_initialized(m_key_images, k_image);
|
||||
auto& id_set = it_map->second;
|
||||
size_t count_before = id_set.size();
|
||||
auto it_set = id_set.find(tx_id);
|
||||
|
|
@ -802,22 +809,22 @@ namespace currency
|
|||
if (id_set.size() == 0)
|
||||
m_key_images.erase(it_map);
|
||||
|
||||
LOG_PRINT_L2("tx pool: key image removed: " << tokey_in.k_image << ", from tx " << tx_id << ", counter: " << count_before << " -> " << count_after);
|
||||
LOG_PRINT_L2("tx pool: key image removed: " << k_image << ", from tx " << tx_id << ", counter: " << count_before << " -> " << count_after);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::get_key_images_from_tx_pool(key_image_cache& key_images) const
|
||||
{
|
||||
|
||||
{
|
||||
m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& h, const tx_details &tx_entry)
|
||||
{
|
||||
for (auto& in : tx_entry.tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
crypto::key_image k_image = AUTO_VAL_INIT(k_image);
|
||||
if (get_key_image_from_txin_v(in, k_image))
|
||||
{
|
||||
key_images[boost::get<txin_to_key>(in).k_image].insert(h);
|
||||
key_images[k_image].insert(h);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -921,10 +928,10 @@ namespace currency
|
|||
LOCAL_READONLY_TRANSACTION();
|
||||
for(size_t i = 0; i!= tx.vin.size(); i++)
|
||||
{
|
||||
if (tx.vin[i].type() == typeid(txin_to_key))
|
||||
crypto::key_image k_image = AUTO_VAL_INIT(k_image);
|
||||
if (get_key_image_from_txin_v(tx.vin[i], k_image))
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(tx.vin[i], const txin_to_key, itk, false);
|
||||
if (k_images.count(itk.k_image))
|
||||
if (k_images.count(k_image))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -933,13 +940,13 @@ namespace currency
|
|||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::append_key_images(std::unordered_set<crypto::key_image>& k_images, const transaction& tx)
|
||||
{
|
||||
for(size_t i = 0; i!= tx.vin.size(); i++)
|
||||
for(size_t i = 0; i != tx.vin.size(); i++)
|
||||
{
|
||||
if (tx.vin[i].type() == typeid(txin_to_key))
|
||||
crypto::key_image k_image = AUTO_VAL_INIT(k_image);
|
||||
if (get_key_image_from_txin_v(tx.vin[i], k_image))
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(tx.vin[i], const txin_to_key, itk, false);
|
||||
auto i_res = k_images.insert(itk.k_image);
|
||||
CHECK_AND_ASSERT_MES(i_res.second, false, "internal error: key images pool cache - inserted duplicate image in set: " << itk.k_image);
|
||||
auto i_res = k_images.insert(k_image);
|
||||
CHECK_AND_ASSERT_MES(i_res.second, false, "internal error: key images pool cache - inserted duplicate image in set: " << k_image);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -959,8 +966,8 @@ namespace currency
|
|||
return "(no transactions, the pool is empty)";
|
||||
// sort output by receive time
|
||||
txs.sort([](const std::pair<crypto::hash, tx_details>& lhs, const std::pair<crypto::hash, tx_details>& rhs) -> bool { return lhs.second.receive_time < rhs.second.receive_time; });
|
||||
ss << "# | transaction id | size | fee | ins | outs | outs money | live_time | max used block | last failed block | kept by a block?" << ENDL;
|
||||
// 1234 <f99fe6d4335fc0ddd69e6880a4d95e0f6ea398de0324a6837021a61c6a31cacd> 87157 0.10000111 2000 2000 112000.12345678 d0.h10.m16.s17 123456 <12345..> 123456 <12345..> YES
|
||||
ss << "# | transaction id | size | fee | ins | outs | outs money | live_time | max used block | last failed block | kept by a block?" << ENDL;
|
||||
// 1234 f99fe6d4335fc0ddd69e6880a4d95e0f6ea398de0324a6837021a61c6a31cacd 87157 0.10000111 2000 2000 112000.12345678 d0.h10.m16.s17 123456 <12345..> 123456 <12345..> YES
|
||||
size_t i = 0;
|
||||
for (auto& tx : txs)
|
||||
{
|
||||
|
|
@ -1328,8 +1335,11 @@ namespace currency
|
|||
idx = 0;
|
||||
for (const auto& out : tx.vout)
|
||||
{
|
||||
if (out.target.type() == typeid(txout_multisig))
|
||||
result.push_back(ms_out_info({ get_multisig_out_id(tx, idx), idx, false }));
|
||||
VARIANT_SWITCH_BEGIN(out);
|
||||
VARIANT_CASE_CONST(tx_out_bare, o)
|
||||
if (o.target.type() == typeid(txout_multisig))
|
||||
result.push_back(ms_out_info({ get_multisig_out_id(tx, idx), idx, false }));
|
||||
VARIANT_SWITCH_END();
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
|
@ -1345,8 +1355,11 @@ namespace currency
|
|||
size_t idx = 0;
|
||||
for (const auto& out : tx.vout)
|
||||
{
|
||||
if (out.target.type() == typeid(txout_multisig) && get_multisig_out_id(tx, idx) == multisig_id)
|
||||
return true;
|
||||
VARIANT_SWITCH_BEGIN(out);
|
||||
VARIANT_CASE_CONST(tx_out_bare, o)
|
||||
if (o.target.type() == typeid(txout_multisig) && get_multisig_out_id(tx, idx) == multisig_id)
|
||||
return true;
|
||||
VARIANT_SWITCH_END();
|
||||
++idx;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#pragma once
|
||||
#include "include_base_utils.h"
|
||||
using namespace epee;
|
||||
|
||||
|
||||
#include <set>
|
||||
|
|
@ -146,6 +145,7 @@ namespace currency
|
|||
bool remove_key_images(const crypto::hash &tx_id, const transaction& tx, bool kept_by_block);
|
||||
bool insert_alias_info(const transaction& tx);
|
||||
bool remove_alias_info(const transaction& tx);
|
||||
bool check_tx_fee(const transaction &tx, uint64_t amount_fee);
|
||||
|
||||
bool is_valid_contract_finalization_tx(const transaction &tx)const;
|
||||
void store_db_solo_options_values();
|
||||
|
|
|
|||
|
|
@ -21,27 +21,27 @@ namespace currency
|
|||
//-----------------------------------------------------------------------------------------------
|
||||
bool check_tx_inputs_keyimages_diff(const transaction& tx)
|
||||
{
|
||||
std::unordered_set<crypto::key_image> ki;
|
||||
BOOST_FOREACH(const auto& in, tx.vin)
|
||||
std::unordered_set<crypto::key_image> key_images;
|
||||
crypto::key_image ki{};
|
||||
for(const auto& in_v : tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
if (get_key_image_from_txin_v(in_v, ki))
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
|
||||
if (!ki.insert(tokey_in.k_image).second)
|
||||
return false;
|
||||
}
|
||||
else if (in.type() == typeid(txin_htlc))
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_htlc, htlc_in, false);
|
||||
if (!ki.insert(htlc_in.k_image).second)
|
||||
if (!key_images.insert(ki).second)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool validate_tx_semantic(const transaction& tx, size_t tx_block_size)
|
||||
bool validate_tx_semantic(const transaction& tx, size_t tx_blob_size)
|
||||
{
|
||||
if (tx_blob_size >= CURRENCY_MAX_TRANSACTION_BLOB_SIZE)
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx blob size is " << tx_blob_size << ", it is greater than or equal to allowed maximum of " << CURRENCY_MAX_TRANSACTION_BLOB_SIZE);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!tx.vin.size())
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx with empty inputs, rejected for tx id= " << get_transaction_hash(tx));
|
||||
|
|
@ -56,7 +56,7 @@ namespace currency
|
|||
|
||||
if (!check_outs_valid(tx))
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx with invalid outputs, rejected for tx id= " << get_transaction_hash(tx));
|
||||
LOG_PRINT_RED_L0("tx has invalid outputs, rejected for tx id= " << get_transaction_hash(tx));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -66,22 +66,6 @@ namespace currency
|
|||
return false;
|
||||
}
|
||||
|
||||
uint64_t amount_in = 0;
|
||||
get_inputs_money_amount(tx, amount_in);
|
||||
uint64_t amount_out = get_outs_money_amount(tx);
|
||||
|
||||
if (amount_in < amount_out)
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx with wrong amounts: ins " << amount_in << ", outs " << amount_out << ", rejected for tx id= " << get_transaction_hash(tx));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tx_block_size >= CURRENCY_MAX_TRANSACTION_BLOB_SIZE)
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx has too big size " << tx_block_size << ", expected no bigger than " << CURRENCY_BLOCK_GRANTED_FULL_REWARD_ZONE);
|
||||
return false;
|
||||
}
|
||||
|
||||
//check if tx use different key images
|
||||
if (!check_tx_inputs_keyimages_diff(tx))
|
||||
{
|
||||
|
|
@ -95,6 +79,17 @@ namespace currency
|
|||
return false;
|
||||
}
|
||||
|
||||
// inexpensive check for pre-HF4 txs
|
||||
// post-HF4 txs balance are being checked in check_tx_balance()
|
||||
if (tx.version <= TRANSACTION_VERSION_PRE_HF4)
|
||||
{
|
||||
if (!check_tx_bare_balance(tx))
|
||||
{
|
||||
LOG_PRINT_RED_L0("balance check failed for tx " << get_transaction_hash(tx));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,14 @@
|
|||
// Copyright (c) 2018-2019 Zano Project
|
||||
// Copyright (c) 2018-2023 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "include_base_utils.h"
|
||||
#include "currency_format_utils_transactions.h"
|
||||
|
||||
|
||||
namespace currency
|
||||
{
|
||||
//check correct values, amounts and all lightweight checks not related with database
|
||||
//check correct values, ins and outs types, amounts and all lightweight checks not related to the database
|
||||
bool validate_tx_semantic(const transaction& tx, size_t tx_block_size);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ namespace currency
|
|||
std::stringstream conn_ss;
|
||||
time_t livetime = time(NULL) - cntxt.m_started;
|
||||
conn_ss << std::setw(29) << std::left << std::string(cntxt.m_is_income ? "[INC]":"[OUT]") +
|
||||
string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) + ":" + std::to_string(cntxt.m_remote_port)
|
||||
epst::get_ip_string_from_int32(cntxt.m_remote_ip) + ":" + std::to_string(cntxt.m_remote_port)
|
||||
<< std::setw(20) << std::hex << peer_id
|
||||
<< std::setw(25) << std::to_string(cntxt.m_recv_cnt)+ "(" + std::to_string(time(NULL) - cntxt.m_last_recv) + ")" + "/" + std::to_string(cntxt.m_send_cnt) + "(" + std::to_string(time(NULL) - cntxt.m_last_send) + ")"
|
||||
<< std::setw(25) << get_protocol_state_string(cntxt.m_state)
|
||||
|
|
@ -523,7 +523,7 @@ namespace currency
|
|||
if(!parse_and_validate_block_from_blob(block_entry.block, b))
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("sent wrong block: failed to parse and validate block: \r\n"
|
||||
<< string_tools::buff_to_hex_nodelimer(block_entry.block) << "\r\n dropping connection");
|
||||
<< epst::buff_to_hex_nodelimer(block_entry.block) << "\r\n dropping connection");
|
||||
m_p2p->drop_connection(context);
|
||||
m_p2p->add_ip_fail(context.m_remote_ip);
|
||||
return 1;
|
||||
|
|
@ -547,20 +547,22 @@ namespace currency
|
|||
auto req_it = context.m_priv.m_requested_objects.find(get_block_hash(b));
|
||||
if(req_it == context.m_priv.m_requested_objects.end())
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << string_tools::pod_to_hex(get_blob_hash(block_entry.block))
|
||||
LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epst::pod_to_hex(get_blob_hash(block_entry.block))
|
||||
<< " wasn't requested, dropping connection");
|
||||
m_p2p->drop_connection(context);
|
||||
return 1;
|
||||
}
|
||||
if(b.tx_hashes.size() != block_entry.txs.size())
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << string_tools::pod_to_hex(get_blob_hash(block_entry.block))
|
||||
LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epst::pod_to_hex(get_blob_hash(block_entry.block))
|
||||
<< ", tx_hashes.size()=" << b.tx_hashes.size() << " mismatch with block_complete_entry.m_txs.size()=" << block_entry.txs.size() << ", dropping connection");
|
||||
m_p2p->drop_connection(context);
|
||||
return 1;
|
||||
}
|
||||
|
||||
context.m_priv.m_requested_objects.erase(req_it);
|
||||
|
||||
LOG_PRINT_L4("[NOTIFY_RESPONSE_GET_OBJECTS] BLOCK " << get_block_hash(b) << "[" << get_block_height(b) << "/" << count << "], txs: " << b.tx_hashes.size());
|
||||
}
|
||||
|
||||
LOG_PRINT_CYAN("Block parsing time avr: " << (count > 0 ? total_blocks_parsing_time / count : 0) << " mcs, total for " << count << " blocks: " << total_blocks_parsing_time / 1000 << " ms", LOG_LEVEL_2);
|
||||
|
|
@ -575,29 +577,31 @@ namespace currency
|
|||
|
||||
{
|
||||
m_core.pause_mine();
|
||||
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler(
|
||||
boost::bind(&t_core::resume_mine, &m_core));
|
||||
size_t count = 0;
|
||||
for (const block_complete_entry& block_entry : arg.blocks)
|
||||
{
|
||||
CHECK_STOP_FLAG__DROP_AND_RETURN_IF_SET(1, "Blocks processing interrupted, connection dropped");
|
||||
|
||||
block_verification_context bvc = boost::value_initialized<block_verification_context>();
|
||||
//process transactions
|
||||
size_t count_txs = 0;
|
||||
TIME_MEASURE_START(transactions_process_time);
|
||||
for (const auto& tx_blob : block_entry.txs)
|
||||
{
|
||||
LOG_PRINT_L4("[NOTIFY_RESPONSE_GET_OBJECTS] BL/TX ["<< count << "/" << count_txs << "]: " << epst::buff_to_hex_nodelimer(tx_blob));
|
||||
CHECK_STOP_FLAG__DROP_AND_RETURN_IF_SET(1, "Block txs processing interrupted, connection dropped");
|
||||
crypto::hash tx_id = null_hash;
|
||||
transaction tx = AUTO_VAL_INIT(tx);
|
||||
if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_id))
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("failed to parse tx: "
|
||||
<< string_tools::pod_to_hex(get_blob_hash(tx_blob)) << ", dropping connection");
|
||||
<< epst::pod_to_hex(get_blob_hash(tx_blob)) << ", dropping connection");
|
||||
m_p2p->drop_connection(context);
|
||||
return 1;
|
||||
}
|
||||
bvc.m_onboard_transactions[tx_id] = tx;
|
||||
count_txs++;
|
||||
// tx_verification_context tvc = AUTO_VAL_INIT(tvc);
|
||||
// m_core.handle_incoming_tx(tx_blob, tvc, true);
|
||||
// if(tvc.m_verification_failed)
|
||||
|
|
@ -742,7 +746,7 @@ namespace currency
|
|||
<< "\r\nm_remote_blockchain_height=" << context.m_remote_blockchain_height
|
||||
<< "\r\nm_needed_objects.size()=" << context.m_priv.m_needed_objects.size()
|
||||
<< "\r\nm_requested_objects.size()=" << context.m_priv.m_requested_objects.size()
|
||||
<< "\r\non connection [" << net_utils::print_connection_context_short(context)<< "]");
|
||||
<< "\r\non connection [" << epee::net_utils::print_connection_context_short(context)<< "]");
|
||||
|
||||
context.m_state = currency_connection_context::state_normal;
|
||||
LOG_PRINT_GREEN("[REQUEST_MISSING_OBJECTS]: SYNCHRONIZED OK", LOG_LEVEL_0);
|
||||
|
|
@ -919,7 +923,7 @@ namespace currency
|
|||
void t_currency_protocol_handler<t_core>::set_to_debug_mode(uint32_t ip)
|
||||
{
|
||||
m_debug_ip_address = ip;
|
||||
LOG_PRINT_L0("debug mode is set for IP " << epee::string_tools::get_ip_string_from_int32(m_debug_ip_address));
|
||||
LOG_PRINT_L0("debug mode is set for IP " << epst::get_ip_string_from_int32(m_debug_ip_address));
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
template<class t_core>
|
||||
|
|
@ -944,7 +948,7 @@ namespace currency
|
|||
if(!m_core.have_block(arg.m_block_ids.front().h))
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("sent m_block_ids starting from unknown id: "
|
||||
<< string_tools::pod_to_hex(arg.m_block_ids.front()) << " , dropping connection");
|
||||
<< epst::pod_to_hex(arg.m_block_ids.front()) << " , dropping connection");
|
||||
m_p2p->drop_connection(context);
|
||||
m_p2p->add_ip_fail(context.m_remote_ip);
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ int main(int argc, char* argv[])
|
|||
#endif
|
||||
log_space::get_set_log_detalisation_level(true, LOG_LEVEL_0);
|
||||
log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL);
|
||||
log_space::log_singletone::enable_channels("core,currency_protocol,tx_pool,wallet");
|
||||
log_space::log_singletone::enable_channels("core,currency_protocol,tx_pool,wallet", false);
|
||||
LOG_PRINT_L0("Starting...");
|
||||
|
||||
tools::signal_handler::install_fatal([](int sig_number, void* address) {
|
||||
|
|
@ -162,6 +162,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_no_predownload);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_force_predownload);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_process_predownload_from_path);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_validate_predownload);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_predownload_link);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_disable_ntp);
|
||||
|
|
|
|||
|
|
@ -665,9 +665,9 @@ private:
|
|||
|
||||
if (ptx->signatures.size() == 0)
|
||||
pruned_txs += 1;
|
||||
signatures += ptx->signatures.size();
|
||||
|
||||
txs += 1;
|
||||
signatures += ptx->signatures.size();
|
||||
attachments += ptx->attachment.size();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#define PREPARE_ARG_FROM_JSON(arg_type, var_name) \
|
||||
arg_type var_name = AUTO_VAL_INIT(var_name); \
|
||||
view::api_response default_ar = AUTO_VAL_INIT(default_ar); \
|
||||
LOG_PRINT_BLUE("[REQUEST]: " << param.toStdString(), LOG_LEVEL_3); \
|
||||
if (!epee::serialization::load_t_from_json(var_name, param.toStdString())) \
|
||||
{ \
|
||||
default_ar.error_code = API_RETURN_CODE_BAD_ARG; \
|
||||
|
|
@ -28,6 +29,7 @@ template<typename T>
|
|||
QString make_response(const T& r)
|
||||
{
|
||||
std::string str = epee::serialization::store_t_to_json(r);
|
||||
LOG_PRINT_BLUE("[RESPONSE]: " << str, LOG_LEVEL_3);
|
||||
return str.c_str();
|
||||
}
|
||||
|
||||
|
|
@ -142,6 +144,8 @@ bool MainWindow::init_window()
|
|||
m_view->page()->setWebChannel(m_channel);
|
||||
|
||||
QWidget* central_widget_to_be_set = m_view;
|
||||
double zoom_factor_test = 0.75;
|
||||
m_view->setZoomFactor(zoom_factor_test);
|
||||
|
||||
std::string qt_dev_tools_option = m_backend.get_qt_dev_tools_option();
|
||||
if (!qt_dev_tools_option.empty())
|
||||
|
|
@ -265,7 +269,28 @@ QString MainWindow::request_dummy()
|
|||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
QString MainWindow::call_rpc(const QString& params)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
epee::net_utils::http::http_request_info query_info = AUTO_VAL_INIT(query_info);
|
||||
epee::net_utils::http::http_response_info response_info = AUTO_VAL_INIT(response_info);
|
||||
currency::core_rpc_server::connection_context dummy_context = AUTO_VAL_INIT(dummy_context);
|
||||
|
||||
query_info.m_URI = "/json_rpc";
|
||||
query_info.m_body = params.toStdString();
|
||||
|
||||
m_backend.get_rpc_server().handle_http_request(query_info, response_info, dummy_context);
|
||||
if (response_info.m_response_code != 200)
|
||||
{
|
||||
epee::json_rpc::error_response rsp;
|
||||
rsp.jsonrpc = "2.0";
|
||||
rsp.error.code = response_info.m_response_code;
|
||||
rsp.error.message = response_info.m_response_comment;
|
||||
return QString::fromStdString(epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp)));
|
||||
}
|
||||
return QString::fromStdString(response_info.m_body);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
QString MainWindow::get_default_fee()
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
|
@ -547,6 +572,14 @@ void MainWindow::store_pos(bool consider_showed)
|
|||
void MainWindow::restore_pos(bool consider_showed)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
if (consider_showed)
|
||||
{
|
||||
if (m_config.is_showed)
|
||||
this->showNormal();
|
||||
else
|
||||
this->showMinimized();
|
||||
}
|
||||
|
||||
if (m_config.is_maximazed)
|
||||
{
|
||||
this->setWindowState(windowState() | Qt::WindowMaximized);
|
||||
|
|
@ -578,14 +611,6 @@ void MainWindow::restore_pos(bool consider_showed)
|
|||
}
|
||||
}
|
||||
|
||||
if (consider_showed)
|
||||
{
|
||||
if (m_config.is_showed)
|
||||
this->showNormal();
|
||||
else
|
||||
this->showMinimized();
|
||||
}
|
||||
|
||||
CATCH_ENTRY2(void());
|
||||
}
|
||||
void MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
|
||||
|
|
@ -1055,9 +1080,9 @@ bool MainWindow::money_transfer(const view::transfer_event_info& tei)
|
|||
|
||||
if (!m_tray_icon)
|
||||
return true;
|
||||
if (!tei.ti.is_income)
|
||||
if (tei.ti.has_outgoing_entries())
|
||||
return true;
|
||||
if (!tei.ti.amount)
|
||||
if (!tei.ti.get_native_amount())
|
||||
return true;
|
||||
// if (tei.ti.is_mining && m_wallet_states->operator [](tei.wallet_id) != view::wallet_status_info::wallet_state_ready)
|
||||
// return true;
|
||||
|
|
@ -1071,9 +1096,9 @@ bool MainWindow::money_transfer(const view::transfer_event_info& tei)
|
|||
return true;
|
||||
}
|
||||
|
||||
auto amount_str = currency::print_money_brief(tei.ti.amount);
|
||||
auto amount_str = currency::print_money_brief(tei.ti.get_native_amount()); //@#@ add handling of assets
|
||||
std::string title, msg;
|
||||
if (tei.ti.height == 0) // unconfirmed trx
|
||||
if (tei.ti.height == 0) // unconfirmed tx
|
||||
{
|
||||
msg = amount_str + " " + CURRENCY_NAME_ABR + " " + m_localization[localization_id_is_received];
|
||||
title = m_localization[localization_id_income_transfer_unconfirmed];
|
||||
|
|
@ -1914,6 +1939,17 @@ QString MainWindow::restore_wallet(const QString& param)
|
|||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
QString MainWindow::use_whitelisting(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
//return que_call2<view::restore_wallet_request>("restore_wallet", param, [this](const view::restore_wallet_request& owd, view::api_response& ar){
|
||||
PREPARE_ARG_FROM_JSON(view::api_request_t<bool>, owd);
|
||||
PREPARE_RESPONSE(view::api_responce_return_code, ar);
|
||||
ar.error_code = m_backend.use_whitelisting(owd.wallet_id, owd.req_data);
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
QString MainWindow::open_wallet(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
|
@ -2127,6 +2163,70 @@ QString MainWindow::get_mining_estimate(const QString& param)
|
|||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
QString MainWindow::add_custom_asset_id(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
PREPARE_ARG_FROM_JSON(view::wallet_and_asset_id, waid);
|
||||
PREPARE_RESPONSE(currency::COMMAND_RPC_GET_ASSET_INFO::response, ar);
|
||||
|
||||
ar.error_code = m_backend.add_custom_asset_id(waid.wallet_id, waid.asset_id, ar.response_data.asset_descriptor);
|
||||
ar.response_data.status = ar.error_code;
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
QString MainWindow::remove_custom_asset_id(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
PREPARE_ARG_FROM_JSON(view::wallet_and_asset_id, waid);
|
||||
default_ar.error_code = m_backend.delete_custom_asset_id(waid.wallet_id, waid.asset_id);
|
||||
return MAKE_RESPONSE(default_ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
QString MainWindow::get_wallet_info(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
PREPARE_ARG_FROM_JSON(view::wallet_id_obj, waid);
|
||||
PREPARE_RESPONSE(view::wallet_info, ar);
|
||||
ar.error_code = m_backend.get_wallet_info(waid.wallet_id, ar.response_data);
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
QString MainWindow::create_ionic_swap_proposal(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
PREPARE_ARG_FROM_JSON(view::create_ionic_swap_proposal_request, cispr);
|
||||
PREPARE_RESPONSE(std::string, ar);
|
||||
ar.error_code = m_backend.create_ionic_swap_proposal(cispr.wallet_id, cispr, ar.response_data);
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
QString MainWindow::get_ionic_swap_proposal_info(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
PREPARE_ARG_FROM_JSON(view::api_request_t<std::string>, tx_raw_hex);
|
||||
PREPARE_RESPONSE(tools::wallet_public::ionic_swap_proposal_info, ar);
|
||||
ar.error_code = m_backend.get_ionic_swap_proposal_info(tx_raw_hex.wallet_id, tx_raw_hex.req_data, ar.response_data);
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
|
||||
}
|
||||
|
||||
QString MainWindow::accept_ionic_swap_proposal(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
PREPARE_ARG_FROM_JSON(view::api_request_t<std::string>, tx_raw_hex);
|
||||
PREPARE_RESPONSE(std::string, ar);
|
||||
ar.error_code = m_backend.accept_ionic_swap_proposal(tx_raw_hex.wallet_id, tx_raw_hex.req_data, ar.response_data);
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
QString MainWindow::backup_wallet_keys(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
|
@ -2184,6 +2284,7 @@ QString MainWindow::toggle_autostart(const QString& param)
|
|||
return MAKE_RESPONSE(default_ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
/*
|
||||
QString MainWindow::check_available_sources(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
|
@ -2192,6 +2293,7 @@ QString MainWindow::check_available_sources(const QString& param)
|
|||
return m_backend.check_available_sources(sources.wallet_id, sources.req_data).c_str();
|
||||
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
|
||||
}
|
||||
*/
|
||||
|
||||
QString MainWindow::open_url_in_browser(const QString& param)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ public:
|
|||
QString webkit_launched_script();
|
||||
QString get_smart_wallet_info(const QString& param);
|
||||
QString restore_wallet(const QString& param);
|
||||
QString use_whitelisting(const QString& param);
|
||||
QString is_pos_allowed();
|
||||
QString store_to_file(const QString& path, const QString& buff);
|
||||
QString load_from_file(const QString& path);
|
||||
|
|
@ -168,12 +169,19 @@ public:
|
|||
QString get_default_fee();
|
||||
QString get_options();
|
||||
void bool_toggle_icon(const QString& param);
|
||||
|
||||
QString add_custom_asset_id(const QString& param);
|
||||
QString remove_custom_asset_id(const QString& param);
|
||||
QString get_wallet_info(const QString& param);
|
||||
|
||||
QString create_ionic_swap_proposal(const QString& param);
|
||||
QString get_ionic_swap_proposal_info(const QString& param);
|
||||
QString accept_ionic_swap_proposal(const QString& param);
|
||||
|
||||
bool get_is_disabled_notifications();
|
||||
bool set_is_disabled_notifications(const bool& param);
|
||||
QString export_wallet_history(const QString& param);
|
||||
QString get_log_file();
|
||||
QString check_available_sources(const QString& param);
|
||||
//QString check_available_sources(const QString& param);
|
||||
QString open_url_in_browser(const QString& param);
|
||||
|
||||
void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
|
||||
|
|
@ -188,6 +196,8 @@ public:
|
|||
//for test purposes onlys
|
||||
QString request_dummy();
|
||||
|
||||
QString call_rpc(const QString& params);
|
||||
|
||||
signals:
|
||||
void quit_requested(const QString str);
|
||||
void update_daemon_state(const QString str);
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 047a4602748e0d3e40456f9d2fc2eeef1bc89b06
|
||||
Subproject commit f040b10090a0246ee5f68a37bb4fcc13e6abebcc
|
||||
|
|
@ -56,7 +56,7 @@ int main(int argc, char *argv[])
|
|||
#ifdef _MSC_VER
|
||||
#if _MSC_VER >= 1910
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); //HiDPI pixmaps
|
||||
qputenv("QT_SCALE_FACTOR", "0.75");
|
||||
//qputenv("QT_SCALE_FACTOR", "0.75");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#pragma once
|
||||
#include "p2p_protocol_defs.h"
|
||||
#include "common/crypto_boost_serialization.h"
|
||||
#include "common/crypto_serialization.h"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue