From c97ef1431b6f19640e962b0901546a0229ba6f13 Mon Sep 17 00:00:00 2001 From: Snider Date: Wed, 18 May 2022 15:33:24 +0100 Subject: [PATCH 001/112] docker: adjustable library versions (#331) * Adjustable lib versions via docker build args * gha for docker build. * removes the push to repo * moves arg's to the top of the file. * Delete docker-build.yml --- utils/docker/Dockerfile | 109 ++++++++++++++++++++++++++-------------- 1 file changed, 70 insertions(+), 39 deletions(-) diff --git a/utils/docker/Dockerfile b/utils/docker/Dockerfile index 2fe77a64..580c2a31 100644 --- a/utils/docker/Dockerfile +++ b/utils/docker/Dockerfile @@ -17,12 +17,19 @@ # To stop container: # docker stop zanod # +# To build with different lib versions, pass through --build-arg's +# docker build --build-arg OPENSSL_VERSION_DOT=1.1.1n --build-arg OPENSSL_HASH=40dceb51a4f6a5275bde0e6bf20ef4b91bfc32ed57c0552e2e8e15463372b17a -f utils/docker/Dockerfile . +# +# Available Build Args +# - CMake Version: CMAKE_VERSION_DOT, CMAKE_HASH +# - Boost Version: BOOST_VERSION, BOOST_VERSION_DOT, BOOST_HASH +# - OpenSSL Version: OPENSSL_VERSION_DOT, OPENSSL_HASH # # Build Zano # -FROM ubuntu:18.04 as zano-build +FROM ubuntu:18.04 as build-prep RUN apt update && \ apt install -y build-essential \ @@ -34,47 +41,71 @@ RUN apt update && \ WORKDIR /root -# CMake 3.15.5 +# Lib Settings +ARG CMAKE_VERSION_DOT=3.15.5 +ARG CMAKE_HASH=62e3e7d134a257e13521e306a9d3d1181ab99af8fcae66699c8f98754fc02dda -RUN curl https://github.com/Kitware/CMake/releases/download/v3.15.5/cmake-3.15.5-Linux-x86_64.sh -OL &&\ - echo '62e3e7d134a257e13521e306a9d3d1181ab99af8fcae66699c8f98754fc02dda cmake-3.15.5-Linux-x86_64.sh' | sha256sum -c - &&\ - mkdir /opt/cmake &&\ - sh cmake-3.15.5-Linux-x86_64.sh --prefix=/opt/cmake --skip-license &&\ - ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake &&\ - cmake --version &&\ - rm cmake-3.15.5-Linux-x86_64.sh +ARG BOOST_VERSION=1_70_0 +ARG BOOST_VERSION_DOT=1.70.0 +ARG BOOST_HASH=430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778 +ARG OPENSSL_VERSION_DOT=1.1.1n +ARG OPENSSL_HASH=40dceb51a4f6a5275bde0e6bf20ef4b91bfc32ed57c0552e2e8e15463372b17a -# Boost 1.70 - -RUN curl https://boostorg.jfrog.io/artifactory/main/release/1.70.0/source/boost_1_70_0.tar.bz2 -OL &&\ - echo '430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778 boost_1_70_0.tar.bz2' | sha256sum -c - &&\ - tar -xjf boost_1_70_0.tar.bz2 &&\ - rm boost_1_70_0.tar.bz2 &&\ - cd boost_1_70_0 &&\ - ./bootstrap.sh --with-libraries=system,filesystem,thread,date_time,chrono,regex,serialization,atomic,program_options,locale,timer,log &&\ - ./b2 &&\ - cd .. - -ENV BOOST_ROOT=/root/boost_1_70_0 - - -# OpenSSL 1.1.1n - -RUN curl https://www.openssl.org/source/openssl-1.1.1n.tar.gz -OL &&\ - echo '40dceb51a4f6a5275bde0e6bf20ef4b91bfc32ed57c0552e2e8e15463372b17a openssl-1.1.1n.tar.gz' | sha256sum -c - &&\ - tar xaf openssl-1.1.1n.tar.gz &&\ - rm openssl-1.1.1n.tar.gz &&\ - cd openssl-1.1.1n &&\ - ./config --prefix=/root/openssl --openssldir=/root/openssl shared zlib &&\ - make &&\ - make test &&\ - make install &&\ - cd .. &&\ - rm -rf openssl-1.1.1n - +# Environment Variables +ENV BOOST_ROOT /root/boost_${BOOST_VERSION} ENV OPENSSL_ROOT_DIR=/root/openssl +########################################################## +# Split download & compile to use dockers caching layers # +########################################################## + +# Download CMake +RUN set -ex \ + && curl https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION_DOT}/cmake-${CMAKE_VERSION_DOT}-Linux-x86_64.sh -OL\ + && echo "${CMAKE_HASH} cmake-${CMAKE_VERSION_DOT}-Linux-x86_64.sh" | sha256sum -c + +# Download Boost +RUN set -ex \ + && curl -L -o boost_${BOOST_VERSION}.tar.bz2 https://downloads.sourceforge.net/project/boost/boost/${BOOST_VERSION_DOT}/boost_${BOOST_VERSION}.tar.bz2 \ + && sha256sum boost_${BOOST_VERSION}.tar.bz2 \ + && echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c\ + && tar -xvf boost_${BOOST_VERSION}.tar.bz2 + + +# Download OpenSSL +RUN curl https://www.openssl.org/source/openssl-${OPENSSL_VERSION_DOT}.tar.gz -OL \ + && sha256sum openssl-${OPENSSL_VERSION_DOT}.tar.gz \ + && echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION_DOT}.tar.gz" | sha256sum -c + + +# Compile CMake +RUN set -ex \ + && mkdir /opt/cmake \ + && sh cmake-3.15.5-Linux-x86_64.sh --prefix=/opt/cmake --skip-license\ + && ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake\ + && cmake --version\ + && rm cmake-3.15.5-Linux-x86_64.sh + +# Compile Boost +RUN set -ex \ + && cd boost_${BOOST_VERSION} \ + && ./bootstrap.sh --with-libraries=system,filesystem,thread,date_time,chrono,regex,serialization,atomic,program_options,locale,timer,log \ + && ./b2 + +# Compile OpenSSL +RUN set -ex \ + && tar xaf openssl-${OPENSSL_VERSION_DOT}.tar.gz \ + && rm openssl-${OPENSSL_VERSION_DOT}.tar.gz \ + && cd openssl-${OPENSSL_VERSION_DOT} \ + && ./config --prefix=/root/openssl --openssldir=/root/openssl shared zlib \ + && make \ + && make test \ + && make install \ + && cd .. \ + && rm -rf openssl-${OPENSSL_VERSION_DOT} + +FROM build-prep as build # Zano @@ -102,8 +133,8 @@ RUN useradd -ms /bin/bash zano &&\ USER zano:zano WORKDIR /home/zano -COPY --chown=zano:zano --from=zano-build /root/zano/build/src/zanod . -COPY --chown=zano:zano --from=zano-build /root/zano/build/src/simplewallet . +COPY --chown=zano:zano --from=build /root/zano/build/src/zanod . +COPY --chown=zano:zano --from=build /root/zano/build/src/simplewallet . # blockchain loaction VOLUME /home/zano/.Zano From a0625b062473585dda4cfbe08634cc86efb2793c Mon Sep 17 00:00:00 2001 From: sowle Date: Fri, 3 Jun 2022 22:36:04 +0200 Subject: [PATCH 002/112] fix simplewallet linking for gcc --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index da31da22..734f695f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -174,7 +174,7 @@ 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} dl) ENABLE_SHARED_PCH(simplewallet SIMPLEWALLET) ENABLE_SHARED_PCH_EXECUTABLE(simplewallet) From 5bbae5e23b2fa02e57d7a3e5cbd4dcb6969e44ff Mon Sep 17 00:00:00 2001 From: sowle Date: Fri, 3 Jun 2022 23:04:01 +0200 Subject: [PATCH 003/112] fix annoying warning message about Boost 1.70 (The use of BOOST_*_ENDIAN and BOOST_BYTE_ORDER is deprecated.) --- .../eos/portable_iarchive.hpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/contrib/eos_portable_archive/eos/portable_iarchive.hpp b/contrib/eos_portable_archive/eos/portable_iarchive.hpp index cd087f34..d5a39e08 100644 --- a/contrib/eos_portable_archive/eos/portable_iarchive.hpp +++ b/contrib/eos_portable_archive/eos/portable_iarchive.hpp @@ -88,6 +88,25 @@ // basic headers #include + +// The following sixteen lines disable annoying message in Boost 1.70 (The use of BOOST_*_ENDIAN and BOOST_BYTE_ORDER is deprecated.) +#if BOOST_VERSION == 107000 && !defined(BOOST_PREDEF_DETAIL_ENDIAN_COMPAT_H) +# define BOOST_PREDEF_DETAIL_ENDIAN_COMPAT_H +# include +#if BOOST_ENDIAN_BIG_BYTE +# define BOOST_BIG_ENDIAN +# define BOOST_BYTE_ORDER 4321 +#endif +#if BOOST_ENDIAN_LITTLE_BYTE +# define BOOST_LITTLE_ENDIAN +# define BOOST_BYTE_ORDER 1234 +#endif +#if BOOST_ENDIAN_LITTLE_WORD +# define BOOST_PDP_ENDIAN +# define BOOST_BYTE_ORDER 2134 +#endif +#endif + #include #include #include From 7cf459e9f5fe2eb94b74c1673f086cf35e7fb93d Mon Sep 17 00:00:00 2001 From: ArqTras <33489188+ArqTras@users.noreply.github.com> Date: Thu, 7 Jul 2022 16:55:08 +0200 Subject: [PATCH 004/112] Update README.md (#333) fix for a typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c6ad2f56..2d2950cb 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ For instance, by adding the following lines to `~/.bashrc` 1. Build GUI: cd zano - utils/build_sript_linux.sh + utils/build_script_linux.sh 7. Look for the binaries in `build` folder From 8dd8e5dbce66669549dd0714423fd6544271349d Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Mon, 1 Aug 2022 17:02:43 +0200 Subject: [PATCH 005/112] Removed dl --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 734f695f..da31da22 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -174,7 +174,7 @@ 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} dl) +target_link_libraries(simplewallet wallet rpc currency_core crypto common zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) ENABLE_SHARED_PCH(simplewallet SIMPLEWALLET) ENABLE_SHARED_PCH_EXECUTABLE(simplewallet) From cd01fd3bd291eb471117ca573da075cdbff4e236 Mon Sep 17 00:00:00 2001 From: zano build machine Date: Thu, 22 Dec 2022 17:20:31 +0300 Subject: [PATCH 006/112] === build number: 143 -> 144 === --- src/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h.in b/src/version.h.in index a6d24549..50c2fe88 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -8,6 +8,6 @@ #define PROJECT_REVISION "0" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 143 +#define PROJECT_VERSION_BUILD_NO 144 #define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO) #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]" From 404b20fa03e70af8bf30d7d0aaf322772afd1300 Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 22 Dec 2022 22:12:13 +0100 Subject: [PATCH 007/112] build: win signing temporary disabled --- utils/build_script_windows.bat | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/utils/build_script_windows.bat b/utils/build_script_windows.bat index b5a1451d..4ccd5e09 100644 --- a/utils/build_script_windows.bat +++ b/utils/build_script_windows.bat @@ -168,13 +168,14 @@ IF %ERRORLEVEL% NEQ 0 ( set installer_file=%ACHIVE_NAME_PREFIX%%version%-installer.exe set installer_path=%BUILDS_PATH%\builds\%installer_file% -@echo " SIGNING ...." - -%ZANO_SIGN_CMD% %installer_path% -IF %ERRORLEVEL% NEQ 0 ( - @echo "failed to sign installer" - goto error -) +:: Signing temporary disable +::@echo " SIGNING ...." +:: +::%ZANO_SIGN_CMD% %installer_path% +::IF %ERRORLEVEL% NEQ 0 ( +:: @echo "failed to sign installer" +:: goto error +::) @echo " UPLOADING TO SERVER ...." From e7231271d1b53d9be1565ddccc50b622a0fb119f Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 11 Jan 2023 14:57:51 +0100 Subject: [PATCH 008/112] added detecting of an AppImage and set proper path to html foldr --- contrib/tor-connect | 2 +- src/gui/qt-daemon/layout | 2 +- src/wallet/wallets_manager.cpp | 13 ++++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/contrib/tor-connect b/contrib/tor-connect index aa509880..b589edb1 160000 --- a/contrib/tor-connect +++ b/contrib/tor-connect @@ -1 +1 @@ -Subproject commit aa509880f06292ac8078046f3d49ff854e400716 +Subproject commit b589edb1906dccb387cfeded6ed12286c5f0405f diff --git a/src/gui/qt-daemon/layout b/src/gui/qt-daemon/layout index b091d45a..73d36003 160000 --- a/src/gui/qt-daemon/layout +++ b/src/gui/qt-daemon/layout @@ -1 +1 @@ -Subproject commit b091d45ad697db2d35e94de41be3f175bad0f71d +Subproject commit 73d36003da48622469ebe8f5bd39d2a8ed49a5d5 diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index 54a5cb26..161a6e13 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -331,7 +331,18 @@ bool wallets_manager::init(view::i_view* pview_handler) std::string path_to_html; if (!command_line::has_arg(m_vm, arg_html_folder)) { - path_to_html = string_tools::get_current_module_folder() + "/html"; +#if defined(__unix__) || defined(__linux__) + const char* env_p = std::getenv("APPDIR"); + if (env_p && std::strlen(env_p)) + { + //app running inside AppImage + path_to_html = std::string(env_p) + "usr/bin/html"; + } + else +#endif + { + path_to_html = string_tools::get_current_module_folder() + "/html"; + } } else { From 0ed7ead8df7398ebddf0680d873d7a04ee4bd9ec Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 11 Jan 2023 14:57:51 +0100 Subject: [PATCH 009/112] added detecting of an AppImage and set proper path to html foldr --- contrib/tor-connect | 2 +- src/gui/qt-daemon/layout | 2 +- src/wallet/wallets_manager.cpp | 13 ++++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/contrib/tor-connect b/contrib/tor-connect index aa509880..b589edb1 160000 --- a/contrib/tor-connect +++ b/contrib/tor-connect @@ -1 +1 @@ -Subproject commit aa509880f06292ac8078046f3d49ff854e400716 +Subproject commit b589edb1906dccb387cfeded6ed12286c5f0405f diff --git a/src/gui/qt-daemon/layout b/src/gui/qt-daemon/layout index b091d45a..73d36003 160000 --- a/src/gui/qt-daemon/layout +++ b/src/gui/qt-daemon/layout @@ -1 +1 @@ -Subproject commit b091d45ad697db2d35e94de41be3f175bad0f71d +Subproject commit 73d36003da48622469ebe8f5bd39d2a8ed49a5d5 diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index 54a5cb26..161a6e13 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -331,7 +331,18 @@ bool wallets_manager::init(view::i_view* pview_handler) std::string path_to_html; if (!command_line::has_arg(m_vm, arg_html_folder)) { - path_to_html = string_tools::get_current_module_folder() + "/html"; +#if defined(__unix__) || defined(__linux__) + const char* env_p = std::getenv("APPDIR"); + if (env_p && std::strlen(env_p)) + { + //app running inside AppImage + path_to_html = std::string(env_p) + "usr/bin/html"; + } + else +#endif + { + path_to_html = string_tools::get_current_module_folder() + "/html"; + } } else { From b21823cc952a851eecb0e03dcd2b8139d151e538 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 11 Jan 2023 17:56:56 +0100 Subject: [PATCH 010/112] added openssl to root cmake file --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 99243a7d..3f183c8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,9 @@ if(TESTNET) add_definitions(-DTESTNET) endif() +set(OPENSSL_USE_STATIC_LIBS TRUE) # link statically +find_package(OpenSSL REQUIRED) + if(DISABLE_TOR) message("NOTICE: Building with disabled TOR support!") add_definitions(-DDISABLE_TOR) From a5f6f3208337a3ce4cc4d6dfe0cc1b64d30360e6 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 12 Jan 2023 15:31:53 +0100 Subject: [PATCH 011/112] Added svg app image for Linux AppImage --- resources/app_icon.svg | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 resources/app_icon.svg diff --git a/resources/app_icon.svg b/resources/app_icon.svg new file mode 100644 index 00000000..d5ca861a --- /dev/null +++ b/resources/app_icon.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 1e7dc7dff9b964f62f2b2f0231d9e14b162c18e2 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 12 Jan 2023 15:42:03 +0100 Subject: [PATCH 012/112] added extra logs for AppImage detection debug --- src/wallet/wallets_manager.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index 161a6e13..dfaacc17 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -331,11 +331,18 @@ bool wallets_manager::init(view::i_view* pview_handler) std::string path_to_html; if (!command_line::has_arg(m_vm, arg_html_folder)) { + LOG_PRINT_L0("Detecting APPDIR... "); #if defined(__unix__) || defined(__linux__) const char* env_p = std::getenv("APPDIR"); + LOG_PRINT_L0("APPDIR = " << (void*)env_p); + if (env_p) + { + LOG_PRINT_L0("APPDIR: " << env_p); + } if (env_p && std::strlen(env_p)) { //app running inside AppImage + LOG_PRINT_L0("APPDIR SET: " << env_p); path_to_html = std::string(env_p) + "usr/bin/html"; } else From f873307240781ffc29c4382de6ae6a01ece3b40f Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 12 Jan 2023 17:46:31 +0100 Subject: [PATCH 013/112] added script for building AppImage --- utils/Zano.desktop | 12 +++ utils/build_script_linux_appimage.sh | 117 +++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 utils/Zano.desktop create mode 100644 utils/build_script_linux_appimage.sh diff --git a/utils/Zano.desktop b/utils/Zano.desktop new file mode 100644 index 00000000..8a912f57 --- /dev/null +++ b/utils/Zano.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Version=1.0 +Name=Zano +GenericName=Zano +Comment=Privacy blockchain +Icon=Zano +Terminal=true +Type=Application +Categories=Qt;Utility; +Name[en_US]=Zano +MimeType=x-scheme-handler/zano; + diff --git a/utils/build_script_linux_appimage.sh b/utils/build_script_linux_appimage.sh new file mode 100644 index 00000000..f96949be --- /dev/null +++ b/utils/build_script_linux_appimage.sh @@ -0,0 +1,117 @@ +#!/bin/bash -x + +# Environment prerequisites: +# 1) QT_PREFIX_PATH should be set to Qt libs folder +# 2) BOOST_ROOT should be set to the root of Boost +# 3) OPENSSL_ROOT_DIR should be set to the root of OpenSSL +# +# for example, place these lines to the end of your ~/.bashrc : +# +# export BOOST_ROOT=/home/user/boost_1_66_0 +# export QT_PREFIX_PATH=/home/user/Qt5.10.1/5.10.1/gcc_64 +# export OPENSSL_ROOT_DIR=/home/user/openssl +# export LINUX_DEPLOY_QT=/home/user/QtDeployment.appimage + + +ARCHIVE_NAME_PREFIX=zano-linux-x64- + +: "${BOOST_ROOT:?BOOST_ROOT should be set to the root of Boost, ex.: /home/user/boost_1_66_0}" +: "${QT_PREFIX_PATH:?QT_PREFIX_PATH should be set to Qt libs folder, ex.: /home/user/Qt5.10.1/5.10.1/gcc_64}" +: "${OPENSSL_ROOT_DIR:?OPENSSL_ROOT_DIR should be set to OpenSSL root folder, ex.: /home/user/openssl}" + +if [ -n "$build_prefix" ]; then + ARCHIVE_NAME_PREFIX=${ARCHIVE_NAME_PREFIX}${build_prefix}- + build_prefix_label="$build_prefix " +fi + +if [ "$testnet" == true ]; then + testnet_def="-D TESTNET=TRUE" + testnet_label="testnet " + ARCHIVE_NAME_PREFIX=${ARCHIVE_NAME_PREFIX}testnet- +fi + +if [ "$testnet" == true ] || [ -n "$qt_dev_tools" ]; then + copy_qt_dev_tools=true + copy_qt_dev_tools_label="devtools " + ARCHIVE_NAME_PREFIX=${ARCHIVE_NAME_PREFIX}devtools- +fi + + +prj_root=$(pwd) + +echo "---------------- BUILDING PROJECT ----------------" +echo "--------------------------------------------------" + +echo "Building...." + +rm -rf build; mkdir -p build/release; cd build/release; +cmake $testnet_def -D STATIC=true -D ARCH=x86-64 -D BUILD_GUI=TRUE -D OPENSSL_ROOT_DIR="$OPENSSL_ROOT_DIR" -D CMAKE_PREFIX_PATH="$QT_PREFIX_PATH" -D CMAKE_BUILD_TYPE=Release ../.. +if [ $? -ne 0 ]; then + echo "Failed to run cmake" + exit 1 +fi + +make -j2 daemon simplewallet connectivity_tool +if [ $? -ne 0 ]; then + echo "Failed to make!" + exit 1 +fi + +make -j1 Zano +if [ $? -ne 0 ]; then + echo "Failed to make!" + exit 1 +fi + + +read version_str <<< $(./src/zanod --version | awk '/^Zano/ { print $2 }') +version_str=${version_str} +echo $version_str + +rm -rf Zano; +mkdir -p Zano/usr/bin; +mkdir -p Zano/usr/lib; +mkdir -p Zano/usr/share/applications; +mkdir -p Zano/usr/share/icons/hicolor/scalable; + +rsync -a ../../src/gui/qt-daemon/layout/html ./Zano/usr/bin --exclude less --exclude package.json --exclude gulpfile.js + +cp -Rv src/zanod src/Zano src/simplewallet src/connectivity_tool ./Zano/usr/bin +cp -Rv ../../ultils/Zano.desktop ./Zano/usr/share/application/Zano.desktop +cp -Rv ../../resources/app_icon.svg ./Zano/usr/share/icons/hicolor/scalable/Zano.svg + +echo "Exec=$prj_root/build/release/Zano/usr/bin/Zano --deeplink-params=%u" >> ./Zano/usr/share/application/Zano.desktop + +$LINUX_DEPLOY_QT ./Zano/usr/share/applications/Zano.desktop -appimage -qmake=$QT_PREFIX_PATH/bin/qmake + +rm -f ./Zano-x86_64.AppImage + +package_filename=${ARCHIVE_NAME_PREFIX}${version_str}.AppImage + +mv ./Zano-x86_64.AppImage ./$package_filename + +echo "Build success" + +if [ -z "$upload_build" ]; then + exit 0 +fi + +echo "Uploading..." + +scp $package_filename zano_build_server:/var/www/html/builds +if [ $? -ne 0 ]; then + echo "Failed to upload to remote server" + exit $? +fi + +read checksum <<< $(sha256sum $package_filename | awk '/^/ { print $1 }' ) + +mail_msg="New ${build_prefix_label}${testnet_label}${copy_qt_dev_tools_label}build for linux-x64:
+https://build.zano.org/builds/$package_filename
+sha256: $checksum" + +echo "$mail_msg" + +echo "$mail_msg" | mail -s "Zano linux-x64 ${build_prefix_label}${testnet_label}${copy_qt_dev_tools_label}build $version_str" ${emails} + +exit 0 From 4f831e9a3d6f54aa53541ed2c8f542b3c80c5441 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 12 Jan 2023 18:01:55 +0100 Subject: [PATCH 014/112] added Exacutable flag --- utils/build_script_linux_appimage.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 utils/build_script_linux_appimage.sh diff --git a/utils/build_script_linux_appimage.sh b/utils/build_script_linux_appimage.sh old mode 100644 new mode 100755 From 33f7c58146d14592a570ad18031bb96b7c82ec7b Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 12 Jan 2023 20:01:22 +0100 Subject: [PATCH 015/112] multiple fixes over AppImage build script --- utils/build_script_linux_appimage.sh | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/utils/build_script_linux_appimage.sh b/utils/build_script_linux_appimage.sh index f96949be..98ecb8ac 100755 --- a/utils/build_script_linux_appimage.sh +++ b/utils/build_script_linux_appimage.sh @@ -39,6 +39,7 @@ fi prj_root=$(pwd) + echo "---------------- BUILDING PROJECT ----------------" echo "--------------------------------------------------" @@ -63,10 +64,15 @@ if [ $? -ne 0 ]; then exit 1 fi - read version_str <<< $(./src/zanod --version | awk '/^Zano/ { print $2 }') version_str=${version_str} + +read commit_str <<< $(./src/zanod --version | grep -m 1 -P -o "(?<=\[)[0-9a-f]{7}") +commit_str=${commit_str} + echo $version_str +echo $commit_str + rm -rf Zano; mkdir -p Zano/usr/bin; @@ -77,18 +83,26 @@ mkdir -p Zano/usr/share/icons/hicolor/scalable; rsync -a ../../src/gui/qt-daemon/layout/html ./Zano/usr/bin --exclude less --exclude package.json --exclude gulpfile.js cp -Rv src/zanod src/Zano src/simplewallet src/connectivity_tool ./Zano/usr/bin -cp -Rv ../../ultils/Zano.desktop ./Zano/usr/share/application/Zano.desktop +cp -Rv ../../utils/Zano.desktop ./Zano/usr/share/applications/Zano.desktop cp -Rv ../../resources/app_icon.svg ./Zano/usr/share/icons/hicolor/scalable/Zano.svg -echo "Exec=$prj_root/build/release/Zano/usr/bin/Zano --deeplink-params=%u" >> ./Zano/usr/share/application/Zano.desktop +echo "Exec=$prj_root/build/release/Zano/usr/bin/Zano --deeplink-params=%u" >> ./Zano/usr/share/applications/Zano.desktop +if [ $? -ne 0 ]; then + echo "Failed to append deskyop file" + exit 1 +fi $LINUX_DEPLOY_QT ./Zano/usr/share/applications/Zano.desktop -appimage -qmake=$QT_PREFIX_PATH/bin/qmake +if [ $? -ne 0 ]; then + echo "Failed to run linuxqtdeployment" + exit 1 +fi rm -f ./Zano-x86_64.AppImage package_filename=${ARCHIVE_NAME_PREFIX}${version_str}.AppImage -mv ./Zano-x86_64.AppImage ./$package_filename +mv ./Zano-${commit_str}-x86_64.AppImage ./$package_filename echo "Build success" @@ -114,4 +128,4 @@ echo "$mail_msg" echo "$mail_msg" | mail -s "Zano linux-x64 ${build_prefix_label}${testnet_label}${copy_qt_dev_tools_label}build $version_str" ${emails} -exit 0 +exit 0 \ No newline at end of file From 985af2ba080110b0bf7dc7bfc3d409bfc5ffbedf Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 12 Jan 2023 20:11:42 +0100 Subject: [PATCH 016/112] disabled full rebuild, added missing / symbol in appimage --- src/wallet/wallets_manager.cpp | 2 +- utils/build_script_linux_appimage.sh | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index dfaacc17..05a5ac42 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -343,7 +343,7 @@ bool wallets_manager::init(view::i_view* pview_handler) { //app running inside AppImage LOG_PRINT_L0("APPDIR SET: " << env_p); - path_to_html = std::string(env_p) + "usr/bin/html"; + path_to_html = std::string(env_p) + "/usr/bin/html"; } else #endif diff --git a/utils/build_script_linux_appimage.sh b/utils/build_script_linux_appimage.sh index 98ecb8ac..0257977d 100755 --- a/utils/build_script_linux_appimage.sh +++ b/utils/build_script_linux_appimage.sh @@ -45,7 +45,8 @@ echo "--------------------------------------------------" echo "Building...." -rm -rf build; mkdir -p build/release; cd build/release; +#rm -rf build; mkdir -p build/release; +cd build/release; cmake $testnet_def -D STATIC=true -D ARCH=x86-64 -D BUILD_GUI=TRUE -D OPENSSL_ROOT_DIR="$OPENSSL_ROOT_DIR" -D CMAKE_PREFIX_PATH="$QT_PREFIX_PATH" -D CMAKE_BUILD_TYPE=Release ../.. if [ $? -ne 0 ]; then echo "Failed to run cmake" From 018c2d24da8eb8a411d20374bfb2e349633f93b1 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 12 Jan 2023 21:10:21 +0100 Subject: [PATCH 017/112] fix for appimage logo --- utils/build_script_linux_appimage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/build_script_linux_appimage.sh b/utils/build_script_linux_appimage.sh index 0257977d..1a37bbe1 100755 --- a/utils/build_script_linux_appimage.sh +++ b/utils/build_script_linux_appimage.sh @@ -85,7 +85,7 @@ rsync -a ../../src/gui/qt-daemon/layout/html ./Zano/usr/bin --exclude less --exc cp -Rv src/zanod src/Zano src/simplewallet src/connectivity_tool ./Zano/usr/bin cp -Rv ../../utils/Zano.desktop ./Zano/usr/share/applications/Zano.desktop -cp -Rv ../../resources/app_icon.svg ./Zano/usr/share/icons/hicolor/scalable/Zano.svg +cp -Rv ../../resources/app_icon.svg ./Zano/usr/share/icons/hicolor/scalable/apps/Zano.svg echo "Exec=$prj_root/build/release/Zano/usr/bin/Zano --deeplink-params=%u" >> ./Zano/usr/share/applications/Zano.desktop if [ $? -ne 0 ]; then From 999098351084bc684f32a31ca6b521e1d203ba5c Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 12 Jan 2023 21:11:53 +0100 Subject: [PATCH 018/112] fix for appimage path for logo --- utils/build_script_linux_appimage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/build_script_linux_appimage.sh b/utils/build_script_linux_appimage.sh index 1a37bbe1..8bba7d15 100755 --- a/utils/build_script_linux_appimage.sh +++ b/utils/build_script_linux_appimage.sh @@ -79,7 +79,7 @@ rm -rf Zano; mkdir -p Zano/usr/bin; mkdir -p Zano/usr/lib; mkdir -p Zano/usr/share/applications; -mkdir -p Zano/usr/share/icons/hicolor/scalable; +mkdir -p Zano/usr/share/icons/hicolor/scalable/apps; rsync -a ../../src/gui/qt-daemon/layout/html ./Zano/usr/bin --exclude less --exclude package.json --exclude gulpfile.js From 7e962a8a92ea548d1ecbbb22540a1c638c1c94e7 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 12 Jan 2023 21:25:43 +0100 Subject: [PATCH 019/112] added skip_build option --- utils/build_script_linux_appimage.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/utils/build_script_linux_appimage.sh b/utils/build_script_linux_appimage.sh index 8bba7d15..7e5c5c4b 100755 --- a/utils/build_script_linux_appimage.sh +++ b/utils/build_script_linux_appimage.sh @@ -39,13 +39,15 @@ fi prj_root=$(pwd) - +if [ "$1" == "skip_build" ]; then + echo "Skipping build, only packing..." +else echo "---------------- BUILDING PROJECT ----------------" echo "--------------------------------------------------" echo "Building...." -#rm -rf build; mkdir -p build/release; +rm -rf build; mkdir -p build/release; cd build/release; cmake $testnet_def -D STATIC=true -D ARCH=x86-64 -D BUILD_GUI=TRUE -D OPENSSL_ROOT_DIR="$OPENSSL_ROOT_DIR" -D CMAKE_PREFIX_PATH="$QT_PREFIX_PATH" -D CMAKE_BUILD_TYPE=Release ../.. if [ $? -ne 0 ]; then @@ -65,6 +67,10 @@ if [ $? -ne 0 ]; then exit 1 fi +fi + + + read version_str <<< $(./src/zanod --version | awk '/^Zano/ { print $2 }') version_str=${version_str} From dadc6a6c41293d4c22b500e59664cc294cebab2f Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 12 Jan 2023 21:27:01 +0100 Subject: [PATCH 020/112] added missing changedir --- utils/build_script_linux_appimage.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/build_script_linux_appimage.sh b/utils/build_script_linux_appimage.sh index 7e5c5c4b..e6f27420 100755 --- a/utils/build_script_linux_appimage.sh +++ b/utils/build_script_linux_appimage.sh @@ -41,6 +41,7 @@ prj_root=$(pwd) if [ "$1" == "skip_build" ]; then echo "Skipping build, only packing..." + cd build/release; else echo "---------------- BUILDING PROJECT ----------------" echo "--------------------------------------------------" From 9bdf9a4da719b5847bfff32dd217ba62dc94b93f Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 13 Jan 2023 18:20:24 +0100 Subject: [PATCH 021/112] added logo in png to AppImage --- resources/app_icon_256.png | Bin 0 -> 15775 bytes utils/build_script_linux_appimage.sh | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 resources/app_icon_256.png diff --git a/resources/app_icon_256.png b/resources/app_icon_256.png new file mode 100644 index 0000000000000000000000000000000000000000..dc0ee9275fcab9d14eacc44b4e159a26cc41ae67 GIT binary patch literal 15775 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 QKU=7k> ./Zano/usr/share/applications/Zano.desktop if [ $? -ne 0 ]; then From 6ee87bacf9e3f65ea774095640f85ea18f68ad03 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 13 Jan 2023 18:42:09 +0100 Subject: [PATCH 022/112] added missing folder creation --- utils/build_script_linux_appimage.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/build_script_linux_appimage.sh b/utils/build_script_linux_appimage.sh index 6a18dfa0..3745db28 100755 --- a/utils/build_script_linux_appimage.sh +++ b/utils/build_script_linux_appimage.sh @@ -87,6 +87,8 @@ mkdir -p Zano/usr/bin; mkdir -p Zano/usr/lib; mkdir -p Zano/usr/share/applications; mkdir -p Zano/usr/share/icons/hicolor/scalable/apps; +mkdir -p Zano/usr/share/icons/hicolor/256x256/apps; + rsync -a ../../src/gui/qt-daemon/layout/html ./Zano/usr/bin --exclude less --exclude package.json --exclude gulpfile.js From 976ec782473ed5ae1d35e39810e511b664597cdc Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 13 Jan 2023 19:03:20 +0100 Subject: [PATCH 023/112] fixes AppImage filename derivation --- utils/build_script_linux_appimage.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/utils/build_script_linux_appimage.sh b/utils/build_script_linux_appimage.sh index 3745db28..0af430bb 100755 --- a/utils/build_script_linux_appimage.sh +++ b/utils/build_script_linux_appimage.sh @@ -114,7 +114,12 @@ rm -f ./Zano-x86_64.AppImage package_filename=${ARCHIVE_NAME_PREFIX}${version_str}.AppImage -mv ./Zano-${commit_str}-x86_64.AppImage ./$package_filename +pattern="*.AppImage" +files=( $pattern ) +app_image_file=${files[0]} + + +mv ./$app_image_file ./$package_filename echo "Build success" From 1b898d2afaf9fb756105bedb14a49236689467b7 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Mon, 16 Jan 2023 20:05:43 +0100 Subject: [PATCH 024/112] added disabling sandbox option for qtWebEngine under ubuntu --- src/wallet/wallets_manager.cpp | 6 +++++- utils/build_script_linux_appimage.sh | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index 05a5ac42..f19203c6 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -53,7 +53,6 @@ const command_line::arg_descriptor arg_alloc_win_console ( "alloc-win-console", "Allocates debug console with GUI", false ); const command_line::arg_descriptor arg_html_folder ( "html-path", "Manually set GUI html folder path"); -const command_line::arg_descriptor arg_xcode_stub ( "-NSDocumentRevisionsDebugMode", "Substitute for xcode bug"); const command_line::arg_descriptor arg_enable_gui_debug_mode ( "gui-debug-mode", "Enable debug options in GUI"); const command_line::arg_descriptor arg_qt_remote_debugging_port ( "remote-debugging-port", "Specify port for Qt remote debugging"); const command_line::arg_descriptor arg_remote_node ( "remote-node", "Switch GUI to work with remote node instead of local daemon"); @@ -62,6 +61,9 @@ const command_line::arg_descriptor arg_disable_logs_init("disable-logs-ini const command_line::arg_descriptor arg_qt_dev_tools ( "qt-dev-tools", "Enable main web page inspection with Chromium DevTools, [,scale], e.g. \"horizontal,1.3\"", ""); const command_line::arg_descriptor arg_disable_price_fetch("gui-disable-price-fetch", "Disable price fetching in UI(for privacy matter)"); +const command_line::arg_descriptor arg_xcode_stub("-NSDocumentRevisionsDebugMode", "Substitute for xcode bug"); +const command_line::arg_descriptor arg_sandbox_disable("no-sandbox", "Substitute for ubuntu/linux rendering problem"); + wallets_manager::wallets_manager():m_pview(&m_view_stub), m_stop_singal_sent(false), #ifndef MOBILE_WALLET_BUILD @@ -172,7 +174,9 @@ bool wallets_manager::init_command_line(int argc, char* argv[], std::string& fai command_line::add_arg(desc_cmd_sett, command_line::arg_log_level); command_line::add_arg(desc_cmd_sett, command_line::arg_console); command_line::add_arg(desc_cmd_only, command_line::arg_show_details); + command_line::add_arg(desc_cmd_sett, arg_alloc_win_console); + command_line::add_arg(desc_cmd_sett, arg_sandbox_disable); command_line::add_arg(desc_cmd_sett, arg_html_folder); command_line::add_arg(desc_cmd_only, arg_xcode_stub); command_line::add_arg(desc_cmd_sett, arg_enable_gui_debug_mode); diff --git a/utils/build_script_linux_appimage.sh b/utils/build_script_linux_appimage.sh index 0af430bb..77dff12c 100755 --- a/utils/build_script_linux_appimage.sh +++ b/utils/build_script_linux_appimage.sh @@ -98,7 +98,7 @@ cp -Rv ../../resources/app_icon.svg ./Zano/usr/share/icons/hicolor/scalable/apps cp -Rv ../../resources/app_icon_256.png ./Zano/usr/share/icons/hicolor/256x256/apps/Zano.png -echo "Exec=$prj_root/build/release/Zano/usr/bin/Zano --deeplink-params=%u" >> ./Zano/usr/share/applications/Zano.desktop +echo "Exec=$prj_root/build/release/Zano/usr/bin/Zano --no-sandbox --deeplink-params=%u" >> ./Zano/usr/share/applications/Zano.desktop if [ $? -ne 0 ]; then echo "Failed to append deskyop file" exit 1 From f7b44e552b27b820fe28a9bf57b1ea9de7eecfbc Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Mon, 16 Jan 2023 22:29:09 +0100 Subject: [PATCH 025/112] fixes to crete manual script in appimage --- utils/Zano_appimage_wrapper.sh | 41 ++++++++++++++++++++++++++++ utils/build_script_linux_appimage.sh | 25 ++++++++++++----- 2 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 utils/Zano_appimage_wrapper.sh diff --git a/utils/Zano_appimage_wrapper.sh b/utils/Zano_appimage_wrapper.sh new file mode 100644 index 00000000..3d8ef13a --- /dev/null +++ b/utils/Zano_appimage_wrapper.sh @@ -0,0 +1,41 @@ +#!/bin/bash -x +script_dir=$( dirname "$(readlink -f "$0")" ) + +out_dir=~/.local/share/applications +out_file_name="${out_dir}/Zano.desktop" + +call_app() +{ + pushd $script_dir + usr/bin/Zano "$@" + popd + exit +} + + +create_desktop_icon() +{ + target_file_name=$1 + echo "Generating icon file: $target_file_name..." + rm -f "${out_dir}/Zano.png" + rm -f $target_file_name + cp -Rv "${APPDIR}/usr/share/icons/hicolor/256x256/apps/Zano.png" "${out_dir}/Zano.png" + echo [Desktop Entry] | tee -a $target_file_name > /dev/null + echo Version=1.0 | tee -a $target_file_name > /dev/null + echo Name=Zano | tee -a $target_file_name > /dev/null + echo GenericName=Zano | tee -a $target_file_name > /dev/null + echo Comment=Privacy blockchain | tee -a $target_file_name > /dev/null + echo Icon=${out_dir}/Zano.png | tee -a $target_file_name > /dev/null + echo Exec=$0 --deeplink-params=%u | tee -a $target_file_name > /dev/null + echo Terminal=true | tee -a $target_file_name > /dev/null + echo Type=Application | tee -a $target_file_name > /dev/null + echo "Categories=Qt;Utility;" | tee -a $target_file_name > /dev/null + echo "MimeType=x-scheme-handler/zano;" | tee -a $target_file_name > /dev/null +} + + +create_desktop_icon $out_file_name + +xdg-mime default Zano.desktop x-scheme-handler/zano + +call_app "$@" \ No newline at end of file diff --git a/utils/build_script_linux_appimage.sh b/utils/build_script_linux_appimage.sh index 77dff12c..94cb3cce 100755 --- a/utils/build_script_linux_appimage.sh +++ b/utils/build_script_linux_appimage.sh @@ -11,6 +11,7 @@ # export QT_PREFIX_PATH=/home/user/Qt5.10.1/5.10.1/gcc_64 # export OPENSSL_ROOT_DIR=/home/user/openssl # export LINUX_DEPLOY_QT=/home/user/QtDeployment.appimage +# export LINUX_APPIMAGE_TOOL=/home/user/AppImageTool.appimage ARCHIVE_NAME_PREFIX=zano-linux-x64- @@ -98,28 +99,38 @@ cp -Rv ../../resources/app_icon.svg ./Zano/usr/share/icons/hicolor/scalable/apps cp -Rv ../../resources/app_icon_256.png ./Zano/usr/share/icons/hicolor/256x256/apps/Zano.png -echo "Exec=$prj_root/build/release/Zano/usr/bin/Zano --no-sandbox --deeplink-params=%u" >> ./Zano/usr/share/applications/Zano.desktop +echo "Exec=$prj_root/build/release/Zano/usr/bin/Zano" >> ./Zano/usr/share/applications/Zano.desktop if [ $? -ne 0 ]; then echo "Failed to append deskyop file" exit 1 fi -$LINUX_DEPLOY_QT ./Zano/usr/share/applications/Zano.desktop -appimage -qmake=$QT_PREFIX_PATH/bin/qmake +$LINUX_DEPLOY_QT ./Zano/usr/share/applications/Zano.desktop -qmake=$QT_PREFIX_PATH/bin/qmake if [ $? -ne 0 ]; then echo "Failed to run linuxqtdeployment" exit 1 fi -rm -f ./Zano-x86_64.AppImage +rm -f $prj_root/build/release/Zano/AppRun +cp -Rv ../../utils/Zano_appimage_wrapper.sh $prj_root/build/release/Zano/AppRun package_filename=${ARCHIVE_NAME_PREFIX}${version_str}.AppImage -pattern="*.AppImage" -files=( $pattern ) -app_image_file=${files[0]} +$LINUX_APPIMAGE_TOOL ./Zano ./$package_filename +if [ $? -ne 0 ]; then + echo "Failed to run appimagetool" + exit 1 +fi -mv ./$app_image_file ./$package_filename + + +#pattern="*.AppImage" +#files=( $pattern ) +#app_image_file=${files[0]} + + +#mv ./$app_image_file ./$package_filename echo "Build success" From 26db77219d3882805232a49a706cb2488aa8b505 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Tue, 17 Jan 2023 14:39:41 +0100 Subject: [PATCH 026/112] fix in appimage wrapper script --- utils/Zano_appimage_wrapper.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 utils/Zano_appimage_wrapper.sh diff --git a/utils/Zano_appimage_wrapper.sh b/utils/Zano_appimage_wrapper.sh old mode 100644 new mode 100755 index 3d8ef13a..1dd26c6d --- a/utils/Zano_appimage_wrapper.sh +++ b/utils/Zano_appimage_wrapper.sh @@ -26,7 +26,7 @@ create_desktop_icon() echo GenericName=Zano | tee -a $target_file_name > /dev/null echo Comment=Privacy blockchain | tee -a $target_file_name > /dev/null echo Icon=${out_dir}/Zano.png | tee -a $target_file_name > /dev/null - echo Exec=$0 --deeplink-params=%u | tee -a $target_file_name > /dev/null + echo Exec=$APPIMAGE --deeplink-params=%u | tee -a $target_file_name > /dev/null echo Terminal=true | tee -a $target_file_name > /dev/null echo Type=Application | tee -a $target_file_name > /dev/null echo "Categories=Qt;Utility;" | tee -a $target_file_name > /dev/null From a4c332e1363d52144d424f0366b070f8d2ee9157 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Tue, 17 Jan 2023 15:48:15 +0100 Subject: [PATCH 027/112] disabling sandbox for qtwebengine --- utils/Zano_appimage_wrapper.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/utils/Zano_appimage_wrapper.sh b/utils/Zano_appimage_wrapper.sh index 1dd26c6d..5c8183cd 100755 --- a/utils/Zano_appimage_wrapper.sh +++ b/utils/Zano_appimage_wrapper.sh @@ -4,6 +4,8 @@ script_dir=$( dirname "$(readlink -f "$0")" ) out_dir=~/.local/share/applications out_file_name="${out_dir}/Zano.desktop" +export QTWEBENGINE_DISABLE_SANDBOX=1 + call_app() { pushd $script_dir @@ -31,6 +33,7 @@ create_desktop_icon() echo Type=Application | tee -a $target_file_name > /dev/null echo "Categories=Qt;Utility;" | tee -a $target_file_name > /dev/null echo "MimeType=x-scheme-handler/zano;" | tee -a $target_file_name > /dev/null + echo "StartupWMClass=Zano" | tee -a $target_file_name > /dev/null } From d9120d8249c967bb9c3183f063e644846a1dcacc Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 18 Jan 2023 14:00:13 +0100 Subject: [PATCH 028/112] replaced icon from png to svg --- utils/Zano_appimage_wrapper.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/Zano_appimage_wrapper.sh b/utils/Zano_appimage_wrapper.sh index 5c8183cd..43b7de5c 100755 --- a/utils/Zano_appimage_wrapper.sh +++ b/utils/Zano_appimage_wrapper.sh @@ -21,13 +21,13 @@ create_desktop_icon() echo "Generating icon file: $target_file_name..." rm -f "${out_dir}/Zano.png" rm -f $target_file_name - cp -Rv "${APPDIR}/usr/share/icons/hicolor/256x256/apps/Zano.png" "${out_dir}/Zano.png" + cp -Rv "${APPDIR}/usr/share/icons/hicolor/scalable/apps/Zano.svg" "${out_dir}/Zano.Svg" echo [Desktop Entry] | tee -a $target_file_name > /dev/null echo Version=1.0 | tee -a $target_file_name > /dev/null echo Name=Zano | tee -a $target_file_name > /dev/null echo GenericName=Zano | tee -a $target_file_name > /dev/null echo Comment=Privacy blockchain | tee -a $target_file_name > /dev/null - echo Icon=${out_dir}/Zano.png | tee -a $target_file_name > /dev/null + echo Icon=${out_dir}/Zano.svg | tee -a $target_file_name > /dev/null echo Exec=$APPIMAGE --deeplink-params=%u | tee -a $target_file_name > /dev/null echo Terminal=true | tee -a $target_file_name > /dev/null echo Type=Application | tee -a $target_file_name > /dev/null From d39c86207b13125141fe9eebe06e867492486166 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 18 Jan 2023 15:13:49 +0100 Subject: [PATCH 029/112] Replace image with rounded shape --- resources/app_icon_256.png | Bin 15775 -> 9869 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/resources/app_icon_256.png b/resources/app_icon_256.png index dc0ee9275fcab9d14eacc44b4e159a26cc41ae67..c2cb15254cc9cd6689594c8267945fe485c123d1 100644 GIT binary patch literal 9869 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 literal 15775 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 QKU=7k Date: Wed, 18 Jan 2023 15:15:13 +0100 Subject: [PATCH 030/112] Update Zano_appimage_wrapper.sh --- utils/Zano_appimage_wrapper.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/Zano_appimage_wrapper.sh b/utils/Zano_appimage_wrapper.sh index 43b7de5c..7aace196 100755 --- a/utils/Zano_appimage_wrapper.sh +++ b/utils/Zano_appimage_wrapper.sh @@ -21,13 +21,13 @@ create_desktop_icon() echo "Generating icon file: $target_file_name..." rm -f "${out_dir}/Zano.png" rm -f $target_file_name - cp -Rv "${APPDIR}/usr/share/icons/hicolor/scalable/apps/Zano.svg" "${out_dir}/Zano.Svg" + cp -Rv "${APPDIR}/usr/share/icons/hicolor/256x256/apps/Zano.png" "${out_dir}/Zano.png" echo [Desktop Entry] | tee -a $target_file_name > /dev/null echo Version=1.0 | tee -a $target_file_name > /dev/null echo Name=Zano | tee -a $target_file_name > /dev/null echo GenericName=Zano | tee -a $target_file_name > /dev/null echo Comment=Privacy blockchain | tee -a $target_file_name > /dev/null - echo Icon=${out_dir}/Zano.svg | tee -a $target_file_name > /dev/null + echo Icon=${out_dir}/Zano.png | tee -a $target_file_name > /dev/null echo Exec=$APPIMAGE --deeplink-params=%u | tee -a $target_file_name > /dev/null echo Terminal=true | tee -a $target_file_name > /dev/null echo Type=Application | tee -a $target_file_name > /dev/null @@ -41,4 +41,4 @@ create_desktop_icon $out_file_name xdg-mime default Zano.desktop x-scheme-handler/zano -call_app "$@" \ No newline at end of file +call_app "$@" From 3850b194257b7c3aa6e17d964c4c618c8ba61047 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 18 Jan 2023 18:36:25 +0100 Subject: [PATCH 031/112] added helper message to script --- utils/Zano_appimage_wrapper.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/utils/Zano_appimage_wrapper.sh b/utils/Zano_appimage_wrapper.sh index 7aace196..51130654 100755 --- a/utils/Zano_appimage_wrapper.sh +++ b/utils/Zano_appimage_wrapper.sh @@ -10,6 +10,10 @@ call_app() { pushd $script_dir usr/bin/Zano "$@" + if [ $? -ne 0 ]; then + echo -e "If Zano failed to launch, it might need to install xinerama extension for the X C Binding with this command:\n sudo apt-get install libxcb-xinerama0e" + fi + popd exit } From 293d9f7d8d502d391ca06279dab99cecce62a4ee Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 18 Jan 2023 19:20:05 +0100 Subject: [PATCH 032/112] Update Zano_appimage_wrapper.sh --- utils/Zano_appimage_wrapper.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/Zano_appimage_wrapper.sh b/utils/Zano_appimage_wrapper.sh index 51130654..bc458c59 100755 --- a/utils/Zano_appimage_wrapper.sh +++ b/utils/Zano_appimage_wrapper.sh @@ -11,7 +11,7 @@ call_app() pushd $script_dir usr/bin/Zano "$@" if [ $? -ne 0 ]; then - echo -e "If Zano failed to launch, it might need to install xinerama extension for the X C Binding with this command:\n sudo apt-get install libxcb-xinerama0e" + echo $'\n\n\x1b[1mIf Zano fails to launch, it might need to install xinerama extension for the X C Binding with this command:\n\x1b[2m sudo apt-get install libxcb-xinerama0e\n\n' fi popd From 17212f16eacec35f1d618c50d0c8a9c748c73185 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 18 Jan 2023 19:58:54 +0100 Subject: [PATCH 033/112] Removed echo fro launch wrapper --- utils/Zano_appimage_wrapper.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/Zano_appimage_wrapper.sh b/utils/Zano_appimage_wrapper.sh index bc458c59..87e98dba 100755 --- a/utils/Zano_appimage_wrapper.sh +++ b/utils/Zano_appimage_wrapper.sh @@ -1,4 +1,4 @@ -#!/bin/bash -x +#!/bin/bash script_dir=$( dirname "$(readlink -f "$0")" ) out_dir=~/.local/share/applications From dc3d6f8cfe414717dd0645f43324b2f498e8e6b5 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 18 Jan 2023 20:27:15 +0100 Subject: [PATCH 034/112] Fixed typo --- utils/Zano_appimage_wrapper.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/Zano_appimage_wrapper.sh b/utils/Zano_appimage_wrapper.sh index 87e98dba..9c588e61 100755 --- a/utils/Zano_appimage_wrapper.sh +++ b/utils/Zano_appimage_wrapper.sh @@ -11,7 +11,7 @@ call_app() pushd $script_dir usr/bin/Zano "$@" if [ $? -ne 0 ]; then - echo $'\n\n\x1b[1mIf Zano fails to launch, it might need to install xinerama extension for the X C Binding with this command:\n\x1b[2m sudo apt-get install libxcb-xinerama0e\n\n' + echo $'\n\n\x1b[1mIf Zano fails to launch, it might need to install xinerama extension for the X C Binding with this command:\n\x1b[2m sudo apt-get install libxcb-xinerama0\n\n' fi popd From 394384faccd7df2745c640deb7e48187f2d8f21a Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 18 Jan 2023 21:00:29 +0100 Subject: [PATCH 035/112] moved UI to proper commit --- src/gui/qt-daemon/layout | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/qt-daemon/layout b/src/gui/qt-daemon/layout index 73d36003..b091d45a 160000 --- a/src/gui/qt-daemon/layout +++ b/src/gui/qt-daemon/layout @@ -1 +1 @@ -Subproject commit 73d36003da48622469ebe8f5bd39d2a8ed49a5d5 +Subproject commit b091d45ad697db2d35e94de41be3f175bad0f71d From f2375f0156083e4708734566a21f978c4c1900a0 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 1 Feb 2023 21:58:26 +0100 Subject: [PATCH 036/112] confidential assets: work in progress --- src/common/crypto_serialization.h | 19 ++++++ src/crypto/clsag.cpp | 18 ++++- src/crypto/clsag.h | 39 ++++++++++- src/currency_core/blockchain_storage.cpp | 13 ++-- src/currency_core/blockchain_storage.h | 6 +- src/currency_core/crypto_config.h | 3 +- src/currency_core/currency_basic.h | 87 +++++++++++++----------- 7 files changed, 135 insertions(+), 50 deletions(-) diff --git a/src/common/crypto_serialization.h b/src/common/crypto_serialization.h index 89b05d8f..80dfb6df 100644 --- a/src/common/crypto_serialization.h +++ b/src/common/crypto_serialization.h @@ -94,6 +94,25 @@ namespace crypto END_BOOST_SERIALIZATION() }; + struct CLSAG_GGX_signature_serialized : public CLSAG_GGX_signature + { + BEGIN_SERIALIZE_OBJECT() + FIELD(c) + FIELD((std::vector&)(r_g)) + FIELD((std::vector&)(r_x)) + FIELD(K1) + FIELD(K2) + END_SERIALIZE() + + BEGIN_BOOST_SERIALIZATION() + BOOST_SERIALIZE(c) + BOOST_SERIALIZE((std::vector&)(r_g)) + BOOST_SERIALIZE((std::vector&)(r_x)) + BOOST_SERIALIZE(K1) + BOOST_SERIALIZE(K2) + END_BOOST_SERIALIZATION() + }; + struct CLSAG_GGXG_signature_serialized : public CLSAG_GGXG_signature { BEGIN_SERIALIZE_OBJECT() diff --git a/src/crypto/clsag.cpp b/src/crypto/clsag.cpp index bcc369e1..c4e1198f 100644 --- a/src/crypto/clsag.cpp +++ b/src/crypto/clsag.cpp @@ -171,7 +171,23 @@ namespace crypto return c_prev == sig.c; } - + + //--------------------------------------------------------------- + + + bool generate_CLSAG_GGX(const hash& m, const std::vector& 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) + { + return false; + } + + bool verify_CLSAG_GGX(const hash& m, const std::vector& ring, const public_key& pseudo_out_amount_commitment, + const public_key& pseudo_out_asset_id, const key_image& ki, const CLSAG_GGX_signature& sig) + { + return false; + } + + //--------------------------------------------------------------- diff --git a/src/crypto/clsag.h b/src/crypto/clsag.h index 8a4400e5..9b7f2156 100644 --- a/src/crypto/clsag.h +++ b/src/crypto/clsag.h @@ -47,7 +47,44 @@ namespace crypto bool verify_CLSAG_GG(const hash& m, const std::vector& ring, const public_key& pseudo_out_amount_commitment, const key_image& ki, const CLSAG_GG_signature& sig); - + + // + // 3-CLSAG + // + + + // 3-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& 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& 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-CLSAG // diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 57fc8ea4..823e4c05 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -3528,10 +3528,10 @@ bool blockchain_storage::unprocess_blockchain_tx_extra(const transaction& tx) if (ei.m_asset_operation.operation_type != ASSET_DESCRIPTOR_OPERATION_UNDEFINED) { - crypto::hash asset_id = currency::null_hash; + crypto::public_key asset_id = currency::null_pkey; if (ei.m_asset_operation.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER) { - asset_id = get_asset_id_from_descriptor(ei.m_asset_operation.descriptor); + calculate_asset_id(ei.m_asset_operation.descriptor, nullptr, &asset_id); } else { @@ -3565,7 +3565,7 @@ uint64_t blockchain_storage::get_aliases_count() const return m_db_aliases.size(); } //------------------------------------------------------------------ -bool blockchain_storage::get_asset_info(const crypto::hash& asset_id, asset_descriptor_base& info)const +bool blockchain_storage::get_asset_info(const crypto::public_key& asset_id, asset_descriptor_base& result) const { CRITICAL_REGION_LOCAL(m_read_lock); auto as_ptr = m_db_assets.find(asset_id); @@ -3573,7 +3573,7 @@ bool blockchain_storage::get_asset_info(const crypto::hash& asset_id, asset_desc { if (as_ptr->size()) { - info = as_ptr->back().descriptor; + result = as_ptr->back().descriptor; return true; } } @@ -3768,7 +3768,7 @@ bool blockchain_storage::put_alias_info(const transaction & tx, extra_alias_entr return true; } //------------------------------------------------------------------ -bool blockchain_storage::pop_asset_info(const crypto::hash& asset_id) +bool blockchain_storage::pop_asset_info(const crypto::public_key& asset_id) { CRITICAL_REGION_LOCAL(m_read_lock); @@ -3791,7 +3791,8 @@ bool blockchain_storage::put_asset_info(const transaction & tx, asset_descriptor CRITICAL_REGION_LOCAL(m_read_lock); if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER) { - crypto::hash asset_id = get_asset_id_from_descriptor(ado.descriptor); + crypto::public_key asset_id{}; + calculate_asset_id(ado.descriptor, nullptr, &asset_id); auto asset_history_ptr = m_db_assets.find(asset_id); CHECK_AND_ASSERT_MES(!asset_history_ptr, false, "Asset id already existing"); assets_container::t_value_type local_asset_history = AUTO_VAL_INIT(local_asset_history); diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index 7537919d..fc68d95a 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -288,7 +288,7 @@ 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 get_asset_info(const crypto::hash& asset_id, asset_descriptor_base& info)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; @@ -492,7 +492,7 @@ namespace currency typedef tools::db::cached_key_value_accessor solo_options_container; typedef tools::db::basic_key_value_accessor per_block_gindex_increments_container; // height => [(amount, gindex_increment), ...] - typedef tools::db::cached_key_value_accessor, true, false> assets_container; + typedef tools::db::cached_key_value_accessor, true, false> assets_container; //----------------------------------------- @@ -654,7 +654,7 @@ namespace currency bool unprocess_blockchain_tx_attachments(const transaction& tx, uint64_t h, uint64_t timestamp); 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::hash& asset_id); + bool pop_asset_info(const crypto::public_key& asset_id); bool put_asset_info(const transaction & tx, asset_descriptor_operation & ado); void fill_addr_to_alias_dict(); //bool resync_spent_tx_flags(); diff --git a/src/currency_core/crypto_config.h b/src/currency_core/crypto_config.h index 087c1cfd..f97a9bad 100644 --- a/src/currency_core/crypto_config.h +++ b/src/currency_core/crypto_config.h @@ -8,7 +8,8 @@ // #define CRYPTO_HDS_OUT_AMOUNT_MASK "ZANO_HDS_OUT_AMOUNT_MASK_______" -#define CRYPTO_HDS_OUT_BLINDING_MASK "ZANO_HDS_OUT_BLINDING_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___" diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h index d79c5122..f725c626 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -56,6 +56,7 @@ namespace currency const static crypto::hash gdefault_genesis = epee::string_tools::hex_to_pod("CC608F59F8080E2FBFE3C8C80EB6E6A953D47CF2D6AEBD345BADA3A1CAB99852"); const static crypto::hash ffff_hash = epee::string_tools::hex_to_pod("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + const static crypto::public_key ffff_pkey = epee::string_tools::hex_to_pod("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); const static wide_difficulty_type global_difficulty_pow_starter = DIFFICULTY_POW_STARTER; const static wide_difficulty_type global_difficulty_pos_starter = DIFFICULTY_POS_STARTER; @@ -214,22 +215,8 @@ namespace currency uint32_t n_extras; }; - //!!!!this is temporary struct!!! - //needed only to hold asset_id of input/output while zarcanum extension being developed - struct open_asset_id - { - crypto::hash asset_id; - BEGIN_SERIALIZE_OBJECT() - FIELD(asset_id) // referring_input - END_SERIALIZE() - BEGIN_BOOST_SERIALIZATION() - BOOST_SERIALIZE(asset_id) - END_BOOST_SERIALIZATION() - }; - - - typedef boost::variant txin_etc_details_v; + typedef boost::variant txin_etc_details_v; struct referring_input @@ -394,8 +381,6 @@ namespace currency END_BOOST_SERIALIZATION() }; - typedef boost::variant txout_etc_details_v; - struct tx_out_zarcanum { tx_out_zarcanum() {} @@ -407,27 +392,26 @@ namespace currency 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 - uint64_t encrypted_amount; - uint8_t mix_attr; - std::vector etc_details; - //crypto::public_key token_masked_generator; + 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) - FIELD(etc_details) 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) - BOOST_SERIALIZE(etc_details) END_BOOST_SERIALIZATION() }; @@ -444,21 +428,45 @@ namespace currency END_BOOST_SERIALIZATION() }; - // non-consoditated txs must have one of this objects in the attachments (outputs_count == vout.size()) - // consolidated -- one pre consolidated part (sum(outputs_count) == vout.size()) + // each output has another amount commitment using generators U and G for range proof aggregation + struct zc_out_range_proof_aggregation_item + { + crypto::public_key amount_commitment_for_range_proof; // U = e_j * U + y'_j * G + crypto::scalar_t y0; // linear proof scalars + crypto::scalar_t y1; + + BEGIN_SERIALIZE_OBJECT() + FIELD(amount_commitment_for_range_proof) + FIELD(y0) + FIELD(y1) + END_SERIALIZE() + + BEGIN_BOOST_SERIALIZATION() + BOOST_SERIALIZE(amount_commitment_for_range_proof) + BOOST_SERIALIZE(y0) + BOOST_SERIALIZE(y1) + END_BOOST_SERIALIZATION() + }; + + // non-consoditated txs must have one of this objects in the attachments (aggregation_items.size() == vout.size()) + // consolidated -- one pre consolidated part (sum(aggregation_items.size()) == vout.size()) struct zc_outs_range_proof { crypto::bpp_signature_serialized bpp; - uint8_t outputs_count = 0; // how many outputs are included in the proof + //std::vector aggregation_items; // size = outputs count, per each output + crypto::vector_aggregation_proof aggregation_proof; + //uint8_t outputs_count = 0; // how many outputs are included in the proof BEGIN_SERIALIZE_OBJECT() FIELD(bpp) - FIELD(outputs_count) + FIELD(aggregation_proof) + //FIELD(outputs_count) END_SERIALIZE() BEGIN_BOOST_SERIALIZATION() BOOST_SERIALIZE(bpp) - BOOST_SERIALIZE(outputs_count) + BOOST_SERIALIZE(aggregation_proof) + //BOOST_SERIALIZE(outputs_count) END_BOOST_SERIALIZATION() }; @@ -466,19 +474,23 @@ namespace currency struct ZC_sig { crypto::public_key pseudo_out_amount_commitment = null_pkey; // premultiplied by 1/8 - crypto::CLSAG_GG_signature_serialized clsags_gg; + crypto::public_key pseudo_out_asset_id = null_pkey; // premultiplied by 1/8 + crypto::CLSAG_GGX_signature_serialized clsags_ggx; BEGIN_SERIALIZE_OBJECT() FIELD(pseudo_out_amount_commitment) - FIELD(clsags_gg) + FIELD(pseudo_out_asset_id) + FIELD(clsags_ggx) END_SERIALIZE() BEGIN_BOOST_SERIALIZATION() BOOST_SERIALIZE(pseudo_out_amount_commitment) - BOOST_SERIALIZE(clsags_gg) + BOOST_SERIALIZE(pseudo_out_asset_id) + BOOST_SERIALIZE(clsags_ggx) END_BOOST_SERIALIZATION() }; + // only for txs with no ZC inputs (cancels out G component of outputs' amount commitments, asset tags assumed to be H_0 (native coin), non-blinded) struct zc_balance_proof { crypto::signature s = null_sig; @@ -777,7 +789,7 @@ namespace currency struct asset_descriptor_with_id: public asset_descriptor_base { - crypto::hash asset_id = currency::null_hash; + crypto::public_key asset_id = currency::null_pkey; /* BEGIN_VERSIONED_SERIALIZE() @@ -797,6 +809,7 @@ namespace currency #define ASSET_DESCRIPTOR_OPERATION_REGISTER 1 #define ASSET_DESCRIPTOR_OPERATION_EMMIT 2 #define ASSET_DESCRIPTOR_OPERATION_UPDATE 3 +#define ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN 4 struct asset_descriptor_operation @@ -804,7 +817,7 @@ namespace currency uint8_t operation_type = ASSET_DESCRIPTOR_OPERATION_UNDEFINED; std::vector proof; asset_descriptor_base descriptor; - std::vector asset_id; //questionable regarding form of optional fields + std::vector asset_id; //questionable regarding form of optional fields // premultiplied by 1/8 BEGIN_VERSIONED_SERIALIZE() @@ -1215,12 +1228,10 @@ 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_outs_range_proof, 46, "zc_outs_range_proof"); -SET_VARIANT_TAGS(currency::zc_balance_proof, 47, "zc_balance_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::open_asset_id, 48, "asset_id"); - -SET_VARIANT_TAGS(currency::asset_descriptor_operation, 48, "asset_descriptor_base"); +SET_VARIANT_TAGS(currency::asset_descriptor_operation, 49, "asset_descriptor_base"); From 5568e0eeaf6cdec7dcb9edfdc6cb2ead1bc3e783 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 8 Feb 2023 18:16:04 +0100 Subject: [PATCH 037/112] crypto: generator U + assertion tests for generators --- src/crypto/crypto-sugar.cpp | 2 +- src/crypto/crypto-sugar.h | 8 ++++++++ tests/functional_tests/crypto_tests.cpp | 17 +++++++++++++++++ .../crypto_tests_range_proofs.h | 11 ----------- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/crypto/crypto-sugar.cpp b/src/crypto/crypto-sugar.cpp index 1823833a..0f0be387 100644 --- a/src/crypto/crypto-sugar.cpp +++ b/src/crypto/crypto-sugar.cpp @@ -23,7 +23,7 @@ namespace crypto const point_t c_point_H = { 0x05087c1f5b9b32d6, 0x00547595f445c3b5, 0x764df64578552f2a, 0x8a49a651e0e0da45 }; // == Hp(G), this is being checked in bpp_basics const point_t c_point_H2 = { 0x70c8d1ab9dbf1cc0, 0xc561bb12639a8516, 0x3cfff1def9e5b268, 0xe0936386f3bcce1a }; // == Hp("h2_generator"), checked in bpp_basics - + const point_t c_point_U = { 0xc9d2f543dbbc253a, 0x87099e9ac33d06dd, 0x76bcf12dcf6ffcba, 0x20384a4a88752d32 }; // == Hp("U_generator"), checked in const point_t c_point_X = { 0xc9d2f543dbbc253a, 0x87099e9ac33d06dd, 0x76bcf12dcf6ffcba, 0x20384a4a88752d32 }; // == Hp("X_generator"), checked in clsag_ggxg_basics const point_t c_point_0 = point_t(point_t::tag_zero()); diff --git a/src/crypto/crypto-sugar.h b/src/crypto/crypto-sugar.h index 7ebe078e..7f1b56b4 100644 --- a/src/crypto/crypto-sugar.h +++ b/src/crypto/crypto-sugar.h @@ -917,6 +917,7 @@ namespace crypto extern const point_t c_point_H; extern const point_t c_point_H2; + extern const point_t c_point_U; extern const point_t c_point_X; extern const point_t c_point_0; extern const point_t c_point_H_plus_G; @@ -1199,6 +1200,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 diff --git a/tests/functional_tests/crypto_tests.cpp b/tests/functional_tests/crypto_tests.cpp index a893b27b..fe1f0358 100644 --- a/tests/functional_tests/crypto_tests.cpp +++ b/tests/functional_tests/crypto_tests.cpp @@ -12,6 +12,7 @@ #include "common/crypto_stream_operators.h" #include "common/varint.h" #include "currency_core/difficulty.h" +#include "currency_core/currency_basic.h" #include "crypto/crypto-sugar.h" #include "crypto/range_proofs.h" @@ -500,6 +501,22 @@ struct test_keeper_t // Tests // +TEST(crypto, basics) +{ + ASSERT_EQ(c_point_H, hash_helper_t::hp(c_point_G)); + ASSERT_EQ(c_point_H2, hash_helper_t::hp("h2_generator")); + ASSERT_EQ(c_point_U, hash_helper_t::hp("U_generator")); + ASSERT_EQ(c_point_X, hash_helper_t::hp("X_generator")); + + ASSERT_EQ(currency::native_coin_asset_id, c_point_H.to_public_key()); + + LOG_PRINT_L0("c_point_0 = " << c_point_0 << " = { " << c_point_0.to_hex_comma_separated_uint64_str() << " }"); + LOG_PRINT_L0("Zano G = " << c_point_G << " = { " << c_point_G.to_hex_comma_separated_bytes_str() << " }"); + LOG_PRINT_L0("Zano H = " << c_point_H << " = { " << c_point_H.to_hex_comma_separated_uint64_str() << " }"); + LOG_PRINT_L0("Zano H2 = " << c_point_H2 << " = { " << c_point_H2.to_hex_comma_separated_uint64_str() << " }"); +} + + #include "crypto_tests_performance.h" TEST(crypto, ge_scalarmult_vartime_p3) diff --git a/tests/functional_tests/crypto_tests_range_proofs.h b/tests/functional_tests/crypto_tests_range_proofs.h index 6be87120..16a6bda0 100644 --- a/tests/functional_tests/crypto_tests_range_proofs.h +++ b/tests/functional_tests/crypto_tests_range_proofs.h @@ -58,17 +58,6 @@ TEST(bpp, basics) std::cout << scalar_t::random().to_string_as_secret_key() << ENDL; */ - point_t H = hash_helper_t::hp(c_point_G); - ASSERT_EQ(H, c_point_H); - std::string h2_hash_str("h2_generator"); - point_t H2 = hash_helper_t::hp(h2_hash_str.c_str(), h2_hash_str.size()); - ASSERT_EQ(H2, c_point_H2); - LOG_PRINT_L0("c_point_0 = " << c_point_0 << " = { " << c_point_0.to_hex_comma_separated_uint64_str() << " }"); - LOG_PRINT_L0("Zano G = " << c_point_G << " = { " << c_point_G.to_hex_comma_separated_bytes_str() << " }"); - LOG_PRINT_L0("Zano H = " << H << " = { " << H.to_hex_comma_separated_uint64_str() << " }"); - LOG_PRINT_L0("Zano H2 = " << H2 << " = { " << H2.to_hex_comma_separated_uint64_str() << " }"); - - auto foo = [&](scalar_t v){ scalar_vec_t values = { v }; scalar_vec_t masks = { scalar_t::random() }; From 47b1338d328562853d8ef1871a1502318d839953 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 8 Feb 2023 18:31:07 +0100 Subject: [PATCH 038/112] crypto: vector_UG_aggregation_proof and zc_asset_surjection_proof stubs --- src/common/crypto_serialization.h | 19 ++++++++++++++ src/crypto/zarcanum.h | 41 +++++++++++++++++++++++++++++ src/currency_core/currency_basic.h | 42 +++++++++++++++++++----------- 3 files changed, 87 insertions(+), 15 deletions(-) diff --git a/src/common/crypto_serialization.h b/src/common/crypto_serialization.h index 80dfb6df..588deb69 100644 --- a/src/common/crypto_serialization.h +++ b/src/common/crypto_serialization.h @@ -19,6 +19,7 @@ #include "crypto/hash.h" #include "crypto/range_proofs.h" #include "crypto/clsag.h" +#include "crypto/zarcanum.h" #include "boost_serialization_maps.h" #include "serialization/keyvalue_enable_POD_serialize_as_string.h" // @@ -134,6 +135,24 @@ namespace crypto 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&)(y0s)) + FIELD((std::vector&)(y1s)) + FIELD(c) + END_SERIALIZE() + + BEGIN_BOOST_SERIALIZATION() + BOOST_SERIALIZE(amount_commitments_for_rp_aggregation) + BOOST_SERIALIZE((std::vector&)(y0s)) + BOOST_SERIALIZE((std::vector&)(y1s)) + BOOST_SERIALIZE(c) + END_BOOST_SERIALIZATION() + }; + + } // namespace crypto BLOB_SERIALIZER(crypto::chacha8_iv); diff --git a/src/crypto/zarcanum.h b/src/crypto/zarcanum.h index 0562efd0..25056142 100644 --- a/src/crypto/zarcanum.h +++ b/src/crypto/zarcanum.h @@ -55,4 +55,45 @@ namespace crypto const mp::uint128_t& pos_difficulty, const zarcanum_proof& sig, uint8_t* p_err = nullptr); + + + // TODO: improve this proof using random weightning factor + struct vector_UG_aggregation_proof + { + std::vector 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_secrets, + const std::vector& amount_commitments, + const std::vector& amount_commitments_for_rp_aggregation, + const std::vector& blinded_asset_ids, + vector_UG_aggregation_proof& result, uint8_t* p_err = nullptr) + { + // proof of knowing e_j and y'' in zero knowledge in the following eq: + // E_j + E'_j = e_j * (T'_j + U) + y'' * 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] + amount_commitments_for_rp_aggregation[j] + // == + // u_secrets[j] * (blinded_asset_ids[j] + U) + g_secrets[j] * G + + + return false; + } + + + bool verify_vector_UG_aggregation_proof(const hash& m, const std::vector amount_commitments, const std::vector blinded_asset_ids, + const vector_UG_aggregation_proof& sig, uint8_t* p_err = nullptr) + { + return false; + } + + } // namespace crypto diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h index f725c626..ddf8e7f8 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -392,7 +392,7 @@ namespace currency 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 + crypto::public_key blinded_asset_id; // group element T, premultiplied by 1/8 uint64_t encrypted_amount = 0; uint8_t mix_attr = 0; @@ -428,6 +428,20 @@ namespace currency END_BOOST_SERIALIZATION() }; + struct zc_asset_surjection_proof + { + int stub = 0; // TODO: one-out-of-many Groth-Bootle-Esgin proof here, adapted version of membership Groth-Kohlweis proof with optimisations from Bootle et. al. and Esgin et. al. + + BEGIN_SERIALIZE_OBJECT() + FIELD(stub) + END_SERIALIZE() + + BEGIN_BOOST_SERIALIZATION() + BOOST_SERIALIZE(stub) + END_BOOST_SERIALIZATION() + }; + + /* // each output has another amount commitment using generators U and G for range proof aggregation struct zc_out_range_proof_aggregation_item { @@ -447,45 +461,42 @@ namespace currency BOOST_SERIALIZE(y1) END_BOOST_SERIALIZATION() }; + */ - // non-consoditated txs must have one of this objects in the attachments (aggregation_items.size() == vout.size()) - // consolidated -- one pre consolidated part (sum(aggregation_items.size()) == vout.size()) + // 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; - //std::vector aggregation_items; // size = outputs count, per each output - crypto::vector_aggregation_proof aggregation_proof; - //uint8_t outputs_count = 0; // how many outputs are included in the 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) - //FIELD(outputs_count) END_SERIALIZE() BEGIN_BOOST_SERIALIZATION() BOOST_SERIALIZE(bpp) BOOST_SERIALIZE(aggregation_proof) - //BOOST_SERIALIZE(outputs_count) END_BOOST_SERIALIZATION() }; - // Zarcanum-aware CLSAG signature + // 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_asset_id = 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_asset_id) + FIELD(pseudo_out_blinded_asset_id) FIELD(clsags_ggx) END_SERIALIZE() BEGIN_BOOST_SERIALIZATION() BOOST_SERIALIZE(pseudo_out_amount_commitment) - BOOST_SERIALIZE(pseudo_out_asset_id) + BOOST_SERIALIZE(pseudo_out_blinded_asset_id) BOOST_SERIALIZE(clsags_ggx) END_BOOST_SERIALIZATION() }; @@ -902,10 +913,10 @@ namespace currency END_SERIALIZE() }; - typedef boost::mpl::vector25< + typedef boost::mpl::vector26< 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, zarcanum_tx_data_v1, zc_outs_range_proof, zc_balance_proof, asset_descriptor_operation + tx_payer, tx_receiver, extra_alias_entry, zarcanum_tx_data_v1, zc_asset_surjection_proof, zc_outs_range_proof, zc_balance_proof, asset_descriptor_operation > all_payload_types; typedef boost::make_variant_over::type payload_items_v; @@ -1228,6 +1239,7 @@ 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"); From abf99ece5e4b98e872f50ef135121c44d0d7a479 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 8 Feb 2023 18:42:29 +0100 Subject: [PATCH 039/112] confidential assets: global core refactoring (wip) --- src/currency_core/currency_basic.h | 4 +- src/currency_core/currency_format_utils.cpp | 369 +++++++++++------- src/currency_core/currency_format_utils.h | 23 +- .../currency_format_utils_transactions.h | 39 +- src/rpc/core_rpc_server_commands_defs.h | 15 +- 5 files changed, 278 insertions(+), 172 deletions(-) diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h index ddf8e7f8..e15b7506 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -56,7 +56,9 @@ namespace currency const static crypto::hash gdefault_genesis = epee::string_tools::hex_to_pod("CC608F59F8080E2FBFE3C8C80EB6E6A953D47CF2D6AEBD345BADA3A1CAB99852"); const static crypto::hash ffff_hash = epee::string_tools::hex_to_pod("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - const static crypto::public_key ffff_pkey = epee::string_tools::hex_to_pod("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + const static crypto::public_key ffff_pkey = epee::string_tools::hex_to_pod("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // TODO @#@# consider getting rid of this + + extern const crypto::public_key native_coin_asset_id; const static wide_difficulty_type global_difficulty_pow_starter = DIFFICULTY_POW_STARTER; const static wide_difficulty_type global_difficulty_pos_starter = DIFFICULTY_POS_STARTER; diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index fd93da34..e990ac59 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -35,6 +35,7 @@ using namespace epee; namespace currency { + const crypto::public_key native_coin_asset_id = crypto::point_t(0x05087c1f5b9b32d6, 0x00547595f445c3b5, 0x764df64578552f2a, 0x8a49a651e0e0da45).to_public_key(); // == crypto::c_point_H, checked in crypto_basics test //--------------------------------------------------------------- bool add_tx_extra_alias(transaction& tx, const extra_alias_entry& alinfo) @@ -66,27 +67,84 @@ namespace currency pos_entry()); }*/ - //-------------------------------------------------------------------------------- - bool generate_zc_outs_range_proof(size_t out_index_start, size_t outs_count, const crypto::scalar_vec_t& amounts, const crypto::scalar_vec_t& blinding_masks, - const std::vector& vouts, zc_outs_range_proof& result) + struct outputs_generation_context { - //TODO: review for Andre - CHECK_AND_ASSERT_MES(amounts.size() == outs_count, false, ""); - CHECK_AND_ASSERT_MES(blinding_masks.size() == outs_count, false, ""); - CHECK_AND_ASSERT_MES(out_index_start + outs_count == vouts.size(), false, ""); + outputs_generation_context(size_t outs_count) + : asset_ids(outs_count) + , blinded_asset_ids(outs_count) + , amount_commitments(outs_count) + , asset_id_blinding_masks(outs_count) + , amounts(outs_count) + , amount_blinding_masks(outs_count) + {} - std::vector commitments_1div8; - for (size_t out_index = out_index_start, i = 0; i < outs_count; ++out_index, ++i) + bool check_sizes(size_t outs_count) const { - const tx_out_zarcanum& toz = boost::get(vouts[out_index]); // may throw an exception, only zarcanum outputs are exprected - const crypto::public_key* p = &toz.amount_commitment; - commitments_1div8.push_back(p); + return + 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; } - result.outputs_count = outs_count; + // per output data + std::vector asset_ids; + std::vector blinded_asset_ids; + std::vector amount_commitments; + crypto::scalar_vec_t asset_id_blinding_masks; + crypto::scalar_vec_t amounts; + crypto::scalar_vec_t amount_blinding_masks; + + // common data + crypto::scalar_t asset_id_blinding_masks_sum = 0; + crypto::scalar_t local_asset_id_blinding_masks_sum = 0; + crypto::scalar_t amount_blinding_masks_sum = 0; + crypto::scalar_t local_amount_blinding_masks_sum = 0; + }; + //-------------------------------------------------------------------------------- + bool generate_asset_surjection_proof(zc_asset_surjection_proof& result) + { + // TODO: membership proof here + return false; + } + //-------------------------------------------------------------------------------- + bool generate_zc_outs_range_proof(size_t out_index_start, size_t outs_count, const outputs_generation_context& outs_gen_context, + const std::vector& vouts, zc_outs_range_proof& result) + { + CHECK_AND_ASSERT_MES(outs_gen_context.check_sizes(outs_count), false, ""); + CHECK_AND_ASSERT_MES(out_index_start + outs_count == vouts.size(), false, ""); + + // prepare data for aggregation proof + std::vector amount_commitments_for_rp_aggregation; // E' = amount * U + y' * G + crypto::scalar_vec_t g_secrets; // amount + y' + crypto::scalar_vec_t y_primes; // y' + for (size_t out_index = out_index_start, i = 0; i < outs_count; ++out_index, ++i) + { + crypto::scalar_t y_prime = crypto::scalar_t::random(); + amount_commitments_for_rp_aggregation.emplace_back(outs_gen_context.amounts[i] * crypto::c_point_U + y_prime * crypto::c_point_G); // E'_j = e_j * U + y'_j * G + g_secrets.emplace_back(outs_gen_context.amount_blinding_masks[i] + y_prime); + y_primes.emplace_back(std::move(y_prime)); + } + + // aggregation proof + // TODO: @#@# use appropriate hash for context binding uint8_t err = 0; - bool r = crypto::bpp_gen<>(amounts, blinding_masks, commitments_1div8, result.bpp, &err); + bool r = crypto::generate_vector_UG_aggregation_proof(null_hash, outs_gen_context.amounts, g_secrets, + outs_gen_context.amount_commitments, + amount_commitments_for_rp_aggregation, + outs_gen_context.blinded_asset_ids, result.aggregation_proof, &err); + CHECK_AND_ASSERT_MES(r, false, "generate_vector_UG_aggregation_proof failed with error " << (int)err); + + // aggregated range proof + std::vector commitments_1div8(result.aggregation_proof.amount_commitments_for_rp_aggregation.size()); + for(size_t i = 0, sz = result.aggregation_proof.amount_commitments_for_rp_aggregation.size(); i < sz; ++i) + commitments_1div8[i] = &result.aggregation_proof.amount_commitments_for_rp_aggregation[i]; + + err = 0; + r = crypto::bpp_gen<>(outs_gen_context.amounts, y_primes, commitments_1div8, result.bpp, &err); CHECK_AND_ASSERT_MES(r, false, "bpp_gen failed with error " << (int)err); return true; @@ -104,10 +162,10 @@ namespace currency } //------------------------------------------------------------------ // for txs with no zc inputs (and thus no zc signatures) but with zc outputs - bool generate_tx_balance_proof(transaction &tx, const crypto::scalar_t& outputs_blinding_masks_sum, uint64_t block_reward_for_miner_tx = 0) + bool generate_tx_balance_proof(transaction &tx, const outputs_generation_context& outs_gen_context, uint64_t block_reward_for_miner_tx = 0) { CHECK_AND_ASSERT_MES(tx.version > TRANSACTION_VERSION_PRE_HF4, false, "unsupported tx.version: " << tx.version); - CHECK_AND_ASSERT_MES(count_type_in_variant_container(tx.signatures) == 0, false, ""); + CHECK_AND_ASSERT_MES(count_type_in_variant_container(tx.signatures) == 0, false, "ZC_sig is unexpected"); uint64_t bare_inputs_sum = block_reward_for_miner_tx; // TODO: condider remove the followin cycle @@ -149,7 +207,7 @@ namespace currency //crypto::scalar_t witness = outputs_blinding_masks_sum; // TODO: consider adding more data to message - crypto::generate_signature(null_hash, commitment_to_zero.to_public_key(), outputs_blinding_masks_sum.as_secret_key(), balance_proof.s); + crypto::generate_signature(null_hash, commitment_to_zero.to_public_key(), outs_gen_context.amount_blinding_masks_sum.as_secret_key(), balance_proof.s); tx.attachment.push_back(balance_proof); return true; @@ -289,19 +347,20 @@ namespace currency } // fill outputs - crypto::scalar_vec_t blinding_masks(destinations.size()); // vector of secret blinging masks for each output. For range proof generation - crypto::scalar_vec_t amounts(destinations.size()); // vector of amounts, converted to scalars. For ranage proof generation - crypto::scalar_t blinding_masks_sum = 0; + outputs_generation_context outs_gen_context(destinations.size()); // auxiliary data for each output uint64_t output_index = 0; for (auto& d : destinations) { std::set deriv_cache; finalized_tx result = AUTO_VAL_INIT(result); uint8_t tx_outs_attr = 0; - r = construct_tx_out(d, txkey.sec, output_index, tx, deriv_cache, account_keys(), blinding_masks[output_index], result, tx_outs_attr); + r = construct_tx_out(d, txkey.sec, output_index, tx, deriv_cache, account_keys(), + outs_gen_context.asset_id_blinding_masks[output_index], outs_gen_context.amount_blinding_masks[output_index], + outs_gen_context.blinded_asset_ids[output_index], outs_gen_context.amount_commitments[output_index], result, tx_outs_attr); CHECK_AND_ASSERT_MES(r, false, "construct_tx_out failed, output #" << output_index << ", amount: " << print_money_brief(d.amount)); - amounts[output_index] = d.amount; - blinding_masks_sum += blinding_masks[output_index]; + outs_gen_context.amounts[output_index] = d.amount; + outs_gen_context.asset_id_blinding_masks_sum += outs_gen_context.asset_id_blinding_masks[output_index]; + outs_gen_context.amount_blinding_masks_sum += outs_gen_context.amount_blinding_masks[output_index]; ++output_index; } @@ -309,13 +368,13 @@ namespace currency { //add range proofs currency::zc_outs_range_proof range_proofs = AUTO_VAL_INIT(range_proofs); - bool r = generate_zc_outs_range_proof(0, amounts.size(), amounts, blinding_masks, tx.vout, range_proofs); + bool r = generate_zc_outs_range_proof(0, destinations.size(), outs_gen_context, tx.vout, range_proofs); CHECK_AND_ASSERT_MES(r, false, "Failed to generate zc_outs_range_proof()"); tx.attachment.push_back(range_proofs); if (!pos) { - r = generate_tx_balance_proof(tx, blinding_masks_sum, block_reward); + r = generate_tx_balance_proof(tx, outs_gen_context, block_reward); CHECK_AND_ASSERT_MES(r, false, "generate_tx_balance_proof failed"); } } @@ -330,7 +389,7 @@ namespace currency } if (blinding_masks_sum_ptr) - *blinding_masks_sum_ptr = blinding_masks_sum; + *blinding_masks_sum_ptr = outs_gen_context.amount_blinding_masks_sum; // TODO @#@# return true; } @@ -339,16 +398,8 @@ namespace currency { if (tx.version > TRANSACTION_VERSION_PRE_HF4) { - //@#@ TODO: This is just a temporary code - uint64_t assets_emmited = 0; - asset_descriptor_operation ado = AUTO_VAL_INIT(ado); - if (get_type_in_variant_container(tx.extra, ado) && ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER) - { - assets_emmited += ado.descriptor.current_supply; - } - size_t zc_inputs_count = 0; - uint64_t bare_inputs_sum = additional_inputs_amount_and_fees_for_mining_tx + assets_emmited; + uint64_t bare_inputs_sum = additional_inputs_amount_and_fees_for_mining_tx; for(auto& vin : tx.vin) { VARIANT_SWITCH_BEGIN(vin); @@ -363,7 +414,7 @@ namespace currency VARIANT_SWITCH_END(); } - crypto::point_t outs_commitments_sum = crypto::c_point_0; + crypto::point_t outs_commitments_sum = crypto::c_point_0; // TODO: consider adding additional commitments / spends / burns here for(auto& vout : tx.vout) { CHECK_AND_ASSERT_MES(vout.type() == typeid(tx_out_zarcanum), false, "unexpected type in outs: " << vout.type().name()); @@ -378,8 +429,15 @@ namespace currency CHECK_AND_ASSERT_MES(additional_inputs_amount_and_fees_for_mining_tx == 0 || fee == 0, false, "invalid tx: fee = " << print_money_brief(fee) << ", additional inputs + fees = " << print_money_brief(additional_inputs_amount_and_fees_for_mining_tx)); - size_t zc_sigs_count = 0; crypto::point_t sum_of_pseudo_out_amount_commitments = crypto::c_point_0; + // take into account newly emitted assets + asset_descriptor_operation ado = AUTO_VAL_INIT(ado); + if (get_type_in_variant_container(tx.extra, ado) && ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER) // @#@ TODO: Support other asset operations + { + CHECK_AND_ASSERT_MES(ado.asset_id.size() == 1, false, "invalid size of ado.asset_id: " << ado.asset_id.size()); + sum_of_pseudo_out_amount_commitments += crypto::scalar_t(ado.descriptor.current_supply) * crypto::point_t(ado.asset_id.back()).modify_mul8(); + } + size_t zc_sigs_count = 0; for(auto& sig_v : tx.signatures) { VARIANT_SWITCH_BEGIN(sig_v); @@ -393,27 +451,22 @@ namespace currency } sum_of_pseudo_out_amount_commitments.modify_mul8(); - CHECK_AND_ASSERT_MES(zc_inputs_count == zc_sigs_count, false, "zc inputs count (" << zc_inputs_count << ") and zc sigs count (" << zc_sigs_count << ") missmatch"); + // (sum(bare inputs' amounts) - fee) * H + sum(pseudo outs commitments for ZC inputs) - sum(outputs' commitments) = 0 OR = lin(G) + crypto::point_t commitment_to_zero = (crypto::scalar_t(bare_inputs_sum) - crypto::scalar_t(fee)) * crypto::c_point_H + sum_of_pseudo_out_amount_commitments - outs_commitments_sum; + CHECK_AND_ASSERT_MES(zc_inputs_count == zc_sigs_count, false, "zc inputs count (" << zc_inputs_count << ") and zc sigs count (" << zc_sigs_count << ") missmatch"); if (zc_inputs_count > 0) { - // no need for additional Schnorr proof for commitment to zero - - // sum(bare inputs' amounts) * H + sum(pseudo outs commitments for ZC inputs) = sum(outputs' commitments) + fee * H - // <=> - // (sum(bare inputs' amounts) - fee) * H + sum(pseudo outs commitments for ZC inputs) - sum(outputs' commitments) = 0 - crypto::point_t Z = (crypto::scalar_t(bare_inputs_sum) - crypto::scalar_t(fee)) * crypto::c_point_H + sum_of_pseudo_out_amount_commitments - outs_commitments_sum; - CHECK_AND_ASSERT_MES(Z.is_zero(), false, "balace equation does not hold"); + // no need for additional proof for commitment to zero + CHECK_AND_ASSERT_MES(commitment_to_zero.is_zero(), false, "balace equation does not hold"); } else { - // no zc inputs -- there should be Schnorr proof for commitment to zero + // no zc inputs -- there should be an explicit proof structure (Schnorr proof), proving that: + // (sum(bare inputs' amounts) - fee) * H + sum(pseudo outs commitments for ZC inputs) - sum(outputs' commitments) = residual_g * G zc_balance_proof balance_proof = AUTO_VAL_INIT(balance_proof); bool r = get_type_in_variant_container(tx.attachment, balance_proof); CHECK_AND_ASSERT_MES(r, false, "no zc inputs are present, but at the same time there's no zc_balance_proof in attachment"); - - // (fee - sum(bare inputs' amounts)) * H + sum(outputs' commitments) = residual * G - crypto::point_t commitment_to_zero = (crypto::scalar_t(fee) - crypto::scalar_t(bare_inputs_sum)) * crypto::c_point_H + outs_commitments_sum; r = crypto::check_signature(null_hash, commitment_to_zero.to_public_key(), balance_proof.s); CHECK_AND_ASSERT_MES(r, false, "zc_balance_proof is invalid"); } @@ -809,6 +862,8 @@ namespace currency return derive_public_key_from_target_address(destination_addr, tx_sec_key, index, out_eph_public_key, derivation); } //--------------------------------------------------------------- + // derived_sec_key = Hs(domain, 8 * src_sec_key * src_pub_key, index) + // derived_pub_key = derived_sec_key * G 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) { crypto::key_derivation derivation = AUTO_VAL_INIT(derivation); @@ -878,30 +933,25 @@ namespace currency return origin_blob; } //--------------------------------------------------------------- - bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set& deriv_cache, const account_keys& self, uint8_t tx_outs_attr) + bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set& deriv_cache, const account_keys& self, uint8_t tx_outs_attr /* = CURRENCY_TO_KEY_OUT_RELAXED */) { finalized_tx result = AUTO_VAL_INIT(result); - crypto::scalar_t out_blinding_mask = AUTO_VAL_INIT(out_blinding_mask); - return construct_tx_out(de, tx_sec_key, output_index, tx, deriv_cache, self, out_blinding_mask, result, tx_outs_attr); + crypto::scalar_t asset_blinding_mask{}, amount_blinding_mask{}; + crypto::point_t blinded_asset_id{}, amount_commitment{}; + return construct_tx_out(de, tx_sec_key, output_index, tx, deriv_cache, self, asset_blinding_mask, amount_blinding_mask, blinded_asset_id, amount_commitment, result, tx_outs_attr); } //--------------------------------------------------------------- bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set& deriv_cache, - const account_keys& self, crypto::scalar_t& out_blinding_mask, finalized_tx& result, uint8_t tx_outs_attr) + 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) { if (tx.version > TRANSACTION_VERSION_PRE_HF4) { // create tx_out_zarcanum - CHECK_AND_ASSERT_MES(de.addr.size() == 1, false, "zarcanum multisig not implemented yet"); + CHECK_AND_ASSERT_MES(de.addr.size() == 1, false, "zarcanum multisig not implemented for tx_out_zarcanum yet"); // TODO @#@# implement multisig support tx_out_zarcanum out = AUTO_VAL_INIT(out); - //@#@ - //TODO: TEMPORARY - if (de.asset_id != currency::null_hash) - { - out.etc_details.push_back(open_asset_id{ de.asset_id }); - } - //@#@ const account_public_address& apa = de.addr.front(); if (apa.spend_public_key == null_pkey && apa.view_public_key == null_pkey) @@ -916,9 +966,14 @@ namespace currency crypto::scalar_t amount_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_AMOUNT_MASK, h); out.encrypted_amount = de.amount ^ amount_mask.m_u64[0]; - out_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_BLINDING_MASK, h); // f = Hs(domain_sep, d, i) - out.amount_commitment = (crypto::c_scalar_1div8 * de.amount * crypto::c_point_H + crypto::c_scalar_1div8 * out_blinding_mask * crypto::c_point_G).to_public_key(); // A = 1/8 * a * H + 1/8 * f * G + asset_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_ASSET_BLINDING_MASK, h); // f = Hs(domain_sep, d, i) + blinded_asset_id = crypto::point_t(de.asset_id) + asset_blinding_mask * crypto::c_point_X; + out.blinded_asset_id = (crypto::c_scalar_1div8 * blinded_asset_id).to_public_key(); // T = 1/8 * (H_asset + s * X) + amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_AMOUNT_BLINDING_MASK, h); // f = Hs(domain_sep, d, i) + amount_commitment = de.amount * blinded_asset_id + amount_blinding_mask * crypto::c_point_G; + out.amount_commitment = (crypto::c_scalar_1div8 * amount_commitment).to_public_key(); // E = 1/8 * e * T + 1/8 * y * G + out.mix_attr = tx_outs_attr; // TODO @#@# @CZ check this } else @@ -934,8 +989,13 @@ namespace currency crypto::scalar_t amount_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_AMOUNT_MASK, h); out.encrypted_amount = de.amount ^ amount_mask.m_u64[0]; - out_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_BLINDING_MASK, h); // f = Hs(domain_sep, Hs(8 * r * V, i) ) - out.amount_commitment = (crypto::c_scalar_1div8 * de.amount * crypto::c_point_H + crypto::c_scalar_1div8 * out_blinding_mask * crypto::c_point_G).to_public_key(); // A = 1/8 * a * H + 1/8 * f * G + asset_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_ASSET_BLINDING_MASK, h); // f = Hs(domain_sep, d, i) + blinded_asset_id = crypto::point_t(de.asset_id) + asset_blinding_mask * crypto::c_point_X; + out.blinded_asset_id = (crypto::c_scalar_1div8 * blinded_asset_id).to_public_key(); // T = 1/8 * (H_asset + s * X) + + amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_AMOUNT_BLINDING_MASK, h); // f = Hs(domain_sep, d, i) + amount_commitment = de.amount * blinded_asset_id + amount_blinding_mask * crypto::c_point_G; + out.amount_commitment = (crypto::c_scalar_1div8 * amount_commitment).to_public_key(); // E = 1/8 * e * T + 1/8 * y * G if (de.addr.front().is_auditable()) out.mix_attr = CURRENCY_TO_KEY_OUT_FORCED_NO_MIX; // override mix_attr to 1 for auditable target addresses @@ -956,6 +1016,7 @@ namespace currency { // create tx_out_bare, this section can be removed after HF4 CHECK_AND_ASSERT_MES(de.addr.size() == 1 || (de.addr.size() > 1 && de.minimum_sigs <= de.addr.size()), false, "Invalid destination entry: amount: " << de.amount << " minimum_sigs: " << de.minimum_sigs << " addr.size(): " << de.addr.size()); + CHECK_AND_ASSERT_MES(de.asset_id == currency::null_pkey, false, "assets are not allowed prior to HF4"); std::vector target_keys; target_keys.reserve(de.addr.size()); @@ -1602,7 +1663,7 @@ namespace currency }; //-------------------------------------------------------------------------------- bool generate_ZC_sig(const crypto::hash& tx_hash_for_signature, size_t input_index, const tx_source_entry& se, const input_generation_context_data& in_context, - const account_keys& sender_account_keys, const crypto::scalar_t& blinding_masks_sum, const uint64_t tx_flags, crypto::scalar_t& local_blinding_masks_sum, transaction& tx, bool last_output) + const account_keys& sender_account_keys, const uint64_t tx_flags, outputs_generation_context& outs_gen_context, transaction& tx, bool last_output) { bool watch_only_mode = sender_account_keys.spend_secret_key == null_skey; CHECK_AND_ASSERT_MES(se.is_zarcanum(), false, "sources contains a non-zarcanum input"); @@ -1620,26 +1681,36 @@ namespace currency { crypto::point_t source_amount_commitment = crypto::c_scalar_1div8 * se.amount * crypto::c_point_H + crypto::c_scalar_1div8 * se.real_out_amount_blinding_mask * crypto::c_point_G; CHECK_AND_ASSERT_MES(in_context.outputs[in_context.real_out_index].amount_commitment == source_amount_commitment.to_public_key(), false, "real output amount commitment check failed"); + crypto::point_t source_blinded_asset_id = crypto::c_scalar_1div8 * crypto::point_t(se.asset_id) + crypto::c_scalar_1div8 * se.real_out_asset_id_blinding_mask * crypto::c_point_X; + CHECK_AND_ASSERT_MES(in_context.outputs[in_context.real_out_index].blinded_asset_id == source_blinded_asset_id.to_public_key(), false, "real output blinded asset id check failed"); } #endif - crypto::scalar_t blinding_mask = 0; + crypto::scalar_t amount_blinding_mask = 0; + crypto::scalar_t asset_id_blinding_mask = 0; if ((last_output && (tx_flags & TX_FLAG_SIGNATURE_MODE_SEPARATE) == 0) || se.separately_signed_tx_complete) { // either normal tx or the last signature of consolidated tx -- in both cases we need to calculate non-random blinding mask for pseudo output commitment - blinding_mask = blinding_masks_sum + local_blinding_masks_sum; + amount_blinding_mask = outs_gen_context.amount_blinding_masks_sum + outs_gen_context.local_amount_blinding_masks_sum; + asset_id_blinding_mask = outs_gen_context.asset_id_blinding_masks_sum + outs_gen_context.local_asset_id_blinding_masks_sum; // @#@ TODO additional check for the last iteration ? } else { - blinding_mask.make_random(); - local_blinding_masks_sum -= blinding_mask; // pseudo out masks are taken into account with negative sign + amount_blinding_mask.make_random(); + asset_id_blinding_mask.make_random(); + outs_gen_context.local_amount_blinding_masks_sum -= amount_blinding_mask; // pseudo out masks are taken into account with negative sign + outs_gen_context.local_asset_id_blinding_masks_sum -= asset_id_blinding_mask; // } - crypto::point_t pseudo_out_amount_commitment = se.amount * crypto::c_point_H + blinding_mask * crypto::c_point_G; + crypto::point_t pseudo_out_amount_commitment = se.amount * crypto::c_point_H + amount_blinding_mask * crypto::c_point_G; sig.pseudo_out_amount_commitment = (crypto::c_scalar_1div8 * pseudo_out_amount_commitment).to_public_key(); - // = two-layers ring signature data outline = + + crypto::point_t pseudo_out_blinded_asset_id = crypto::point_t(se.asset_id) + asset_id_blinding_mask * crypto::c_point_X; + sig.pseudo_out_blinded_asset_id = (crypto::c_scalar_1div8 * pseudo_out_blinded_asset_id).to_public_key(); + + // = three-layers ring signature data outline = // (j in [0, ring_size-1]) // layer 0 ring // se.outputs[j].stealth_address; @@ -1651,13 +1722,20 @@ namespace currency // layer 1 ring // crypto::point_t(se.outputs[j].amount_commitment) - pseudo_out_amount_commitment; // layer 1 secret (with respect to G) - // se.real_out_amount_blinding_mask - blinding_mask; + // se.real_out_amount_blinding_mask - amount_blinding_mask; + // + // layer 2 ring + // crypto::point_t(se.outputs[j].blinded_asset_id) - pseudo_out_asset_id; + // layer 2 secret (with respect to X) + // se.real_out_asset_id_blinding_mask - asset_id_blinding_mask; - std::vector ring; + std::vector ring; for(size_t j = 0; j < in_context.outputs.size(); ++j) - ring.emplace_back(in_context.outputs[j].stealth_address, in_context.outputs[j].amount_commitment); + ring.emplace_back(in_context.outputs[j].stealth_address, in_context.outputs[j].amount_commitment, in_context.outputs[j].blinded_asset_id); - return crypto::generate_CLSAG_GG(tx_hash_for_signature, ring, pseudo_out_amount_commitment, in.k_image, in_context.in_ephemeral.sec, se.real_out_amount_blinding_mask - blinding_mask, in_context.real_out_index, sig.clsags_gg); + return crypto::generate_CLSAG_GGX(tx_hash_for_signature, ring, pseudo_out_amount_commitment, pseudo_out_blinded_asset_id, in.k_image, in_context.in_ephemeral.sec, + se.real_out_amount_blinding_mask - amount_blinding_mask, + se.real_out_asset_id_blinding_mask - asset_id_blinding_mask, in_context.real_out_index, sig.clsags_ggx); } //-------------------------------------------------------------------------------- bool generate_NLSAG_sig(const crypto::hash& tx_hash_for_signature, const crypto::hash& tx_prefix_hash, size_t input_index, const tx_source_entry& src_entr, @@ -1714,10 +1792,21 @@ namespace currency return true; } - - crypto::hash get_asset_id_from_descriptor(const asset_descriptor_base& adb) +#define CRYPTO_HASH_ASSET_ID_ITERATIONS 1024 + void calculate_asset_id(const crypto::public_key& asset_owner, crypto::point_t* p_result_point, crypto::public_key* p_result_pub_key) { - return get_hash_from_POD_objects(CRYPTO_HDS_ASSET_ID, adb.owner); + crypto::hash h = get_hash_from_POD_objects(CRYPTO_HDS_ASSET_ID, asset_owner); + + // this hash function needs to be computationally expensive (s.e. the whitepaper) + for(uint64_t i = 0; i < CRYPTO_HASH_ASSET_ID_ITERATIONS; ++i) + h = get_hash_from_POD_objects(CRYPTO_HDS_ASSET_ID, h, i); + + crypto::point_t local_point{}; + if (!p_result_point) + p_result_point = &local_point; + *p_result_point = crypto::hash_helper_t::hp(&h, sizeof h); + if (p_result_pub_key) + p_result_point->to_public_key(*p_result_pub_key); } @@ -1803,20 +1892,21 @@ namespace currency } - uint64_t summary_inputs_money = 0; + uint64_t native_coins_input_sum = 0; - crypto::hash asset_id_for_destinations = currency::null_hash; + crypto::public_key asset_id_for_asset_operation = currency::null_pkey; asset_descriptor_operation* pado = nullptr; if (tx.version > TRANSACTION_VERSION_PRE_HF4) { pado = get_type_in_variant_container(tx.extra); if (pado) { + CHECK_AND_ASSERT_MES(pado->operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER, false, "unsupported asset operation"); crypto::secret_key stub = AUTO_VAL_INIT(stub); bool r = derive_key_pair_from_key_pair(sender_account_keys.account_address.spend_public_key, one_time_secret_key, stub, pado->descriptor.owner, CRYPTO_HDS_ASSET_CONTROL_KEY); CHECK_AND_ASSERT_MES(r, false, "Failed to derive_public_key_from_tx_and_account_pub_key()"); //also assign this asset id to destinations - asset_id_for_destinations = get_asset_id_from_descriptor(pado->descriptor); + calculate_asset_id(pado->descriptor.owner, nullptr, &asset_id_for_asset_operation); } } @@ -1843,7 +1933,7 @@ namespace currency if(src_entr.is_multisig()) {//multisig input txin_multisig input_multisig = AUTO_VAL_INIT(input_multisig); - summary_inputs_money += input_multisig.amount = src_entr.amount; + input_multisig.amount = src_entr.amount; input_multisig.multisig_out_id = src_entr.multisig_id; input_multisig.sigs_count = src_entr.ms_sigs_count; tx.vin.push_back(input_multisig); @@ -1858,7 +1948,6 @@ namespace currency LOG_ERROR("htlc in: wrong output src_entr.outputs.size() = " << src_entr.outputs.size()); return false; } - summary_inputs_money += src_entr.amount; //key_derivation recv_derivation; crypto::key_image img; @@ -1889,8 +1978,6 @@ namespace currency CHECK_AND_ASSERT_MES(in_context.real_out_index < in_context.outputs.size(), false, "real_output index (" << in_context.real_out_index << ") greater than or equal to in_context.outputs.size()=" << in_context.outputs.size()); - summary_inputs_money += src_entr.amount; - //key_derivation recv_derivation; crypto::key_image img; if (!generate_key_image_helper(sender_account_keys, src_entr.real_out_tx_key, src_entr.real_output_in_tx_index, in_context.in_ephemeral, img)) @@ -1918,13 +2005,7 @@ namespace currency txin_zc_input zc_in = AUTO_VAL_INIT(zc_in); zc_in.k_image = img; zc_in.key_offsets = std::move(key_offsets); - //TEMPORARY - if (src_entr.asset_id != currency::null_hash) - { - zc_in.etc_details.push_back(open_asset_id{ src_entr.asset_id }); - } tx.vin.push_back(zc_in); - } else { @@ -1935,25 +2016,26 @@ namespace currency tx.vin.push_back(input_to_key); } } + + if (src_entr.is_native_coin()) + native_coins_input_sum += src_entr.amount; } - uint64_t amount_of_assets = 0; + uint64_t amount_of_emitted_asset = 0; std::vector shuffled_dsts(destinations); - if (asset_id_for_destinations != currency::null_hash) + if (asset_id_for_asset_operation != currency::null_pkey) { //must be asset publication for (auto& item : shuffled_dsts) { - if (item.asset_id == currency::ffff_hash) + if (item.asset_id == currency::ffff_pkey) { - item.asset_id = asset_id_for_destinations; - amount_of_assets += item.amount; + item.asset_id = asset_id_for_asset_operation; + amount_of_emitted_asset += item.amount; } } CHECK_AND_ASSERT_MES(pado, false, "pado is null ??"); - pado->descriptor.current_supply = amount_of_assets; - //TODO: temporary - summary_inputs_money += amount_of_assets; + pado->descriptor.current_supply = amount_of_emitted_asset; // TODO: consider setting current_supply beforehand, not setting it hear in ad-hoc manner -- sowle } @@ -1964,35 +2046,37 @@ namespace currency // TODO: consider "Shuffle" inputs - uint64_t summary_outs_money = 0; - //fill outputs + // construct outputs + uint64_t native_coins_output_sum = 0; size_t output_index = tx.vout.size(); // in case of append mode we need to start output indexing from the last one + 1 + size_t outputs_to_be_constructed = shuffled_dsts.size(); + outputs_generation_context outs_gen_context(outputs_to_be_constructed); // auxiliary data for each output uint64_t range_proof_start_index = output_index; std::set deriv_cache; - crypto::scalar_vec_t blinding_masks(tx.vout.size() + destinations.size()); // vector of secret blinging masks for each output. For range proof generation - crypto::scalar_vec_t amounts(tx.vout.size() + destinations.size()); // vector of amounts, converted to scalars. For ranage proof generation - crypto::scalar_t blinding_masks_sum = 0; - for(const tx_destination_entry& dst_entr : shuffled_dsts) + for(size_t j = 0; j < outputs_to_be_constructed; ++j, ++output_index) { + const tx_destination_entry& dst_entr = shuffled_dsts[j]; CHECK_AND_ASSERT_MES(dst_entr.amount > 0, false, "Destination with wrong amount: " << dst_entr.amount); // <<-- TODO @#@# consider removing this check - r = construct_tx_out(dst_entr, txkey.sec, output_index, tx, deriv_cache, sender_account_keys, blinding_masks[output_index], result, tx_outs_attr); + r = construct_tx_out(dst_entr, txkey.sec, output_index, tx, deriv_cache, sender_account_keys, + outs_gen_context.asset_id_blinding_masks[j], outs_gen_context.amount_blinding_masks[j], + outs_gen_context.blinded_asset_ids[j], outs_gen_context.amount_commitments[j], result, tx_outs_attr); CHECK_AND_ASSERT_MES(r, false, "Failed to construct tx out"); - amounts[output_index - range_proof_start_index] = dst_entr.amount; - summary_outs_money += dst_entr.amount; - blinding_masks_sum += blinding_masks[output_index]; - output_index++; + outs_gen_context.amounts[j] = dst_entr.amount; + outs_gen_context.asset_id_blinding_masks_sum += outs_gen_context.asset_id_blinding_masks[j]; + outs_gen_context.amount_blinding_masks_sum += outs_gen_context.amount_blinding_masks[j]; + if (dst_entr.is_native_coin()) + native_coins_output_sum += dst_entr.amount; } //check money - if (!(flags&TX_FLAG_SIGNATURE_MODE_SEPARATE)) - { - if (summary_outs_money > summary_inputs_money) - { - LOG_ERROR("Transaction inputs money (" << print_money_brief(summary_inputs_money) << ") is less than outputs money (" << print_money_brief(summary_outs_money) << ")"); - return false; - } - } - + //if (!(flags&TX_FLAG_SIGNATURE_MODE_SEPARATE)) + //{ + // if (summary_outs_money > summary_inputs_money) + // { + // LOG_ERROR("Transaction inputs money (" << print_money_brief(summary_inputs_money) << ") is less than outputs money (" << print_money_brief(summary_outs_money) << ")"); + // return false; + // } + //} //process offers and put there offers derived keys uint64_t att_count = 0; @@ -2026,19 +2110,25 @@ namespace currency if (tx.version > TRANSACTION_VERSION_PRE_HF4) { + // asset surjeciton proof + currency::zc_asset_surjection_proof asp{}; + bool r = generate_asset_surjection_proof(asp); + CHECK_AND_ASSERT_MES(r, false, "generete_asset_surjection_proof failed"); + tx.attachment.push_back(asp); + // add range proofs currency::zc_outs_range_proof range_proofs = AUTO_VAL_INIT(range_proofs); - bool r = generate_zc_outs_range_proof(range_proof_start_index, amounts.size(), amounts, blinding_masks, tx.vout, range_proofs); + r = generate_zc_outs_range_proof(range_proof_start_index, outputs_to_be_constructed, outs_gen_context, tx.vout, range_proofs); CHECK_AND_ASSERT_MES(r, false, "Failed to generate zc_outs_range_proof()"); tx.attachment.push_back(range_proofs); // add explicit fee info - r = add_tx_fee_amount_to_extra(tx, summary_inputs_money - summary_outs_money); + r = add_tx_fee_amount_to_extra(tx, native_coins_input_sum - native_coins_output_sum); CHECK_AND_ASSERT_MES(r, false, "add_tx_fee_amount_to_extra failed"); if (!has_zc_inputs) { - r = generate_tx_balance_proof(tx, blinding_masks_sum, amount_of_assets); + r = generate_tx_balance_proof(tx, outs_gen_context); CHECK_AND_ASSERT_MES(r, false, "generate_tx_balance_proof failed"); } } @@ -2071,7 +2161,6 @@ namespace currency get_transaction_prefix_hash(tx, tx_prefix_hash); //size_t input_index = input_starter_index; //size_t in_context_index = 0; - crypto::scalar_t local_blinding_masks_sum = 0; // ZC only r = false; for (size_t i_ = 0; i_ != sources.size(); i_++) { @@ -2086,8 +2175,7 @@ namespace currency { // ZC // blinding_masks_sum is supposed to be sum(mask of all tx output) - sum(masks of all pseudo out commitments) - r = generate_ZC_sig(tx_hash_for_signature, i_ + input_starter_index, source_entry, in_contexts[i_mapped], sender_account_keys, blinding_masks_sum, flags, - local_blinding_masks_sum, tx, i_ + 1 == sources.size()); + r = generate_ZC_sig(tx_hash_for_signature, i_ + input_starter_index, source_entry, in_contexts[i_mapped], sender_account_keys, flags, outs_gen_context, tx, i_ + 1 == sources.size()); CHECK_AND_ASSERT_MES(r, false, "generate_ZC_sigs failed"); } else @@ -2490,7 +2578,8 @@ namespace currency return true; } - 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::scalar_t& blinding_mask) + 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::scalar_t& amount_blinding_mask, crypto::scalar_t& asset_id_blinding_mask) { crypto::scalar_t h; // = crypto::hash_helper_t::hs(reinterpret_cast(derivation), output_index); // h = Hs(8 * r * V, i) crypto::derivation_to_scalar(derivation, output_index, h.as_secret_key()); // h = Hs(8 * r * V, i) @@ -2506,13 +2595,18 @@ namespace currency crypto::scalar_t amount_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_AMOUNT_MASK, h); decoded_amount = zo.encrypted_amount ^ amount_mask.m_u64[0]; - blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_BLINDING_MASK, h); // f = Hs(domain_sep, h) + amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_AMOUNT_BLINDING_MASK, h); // f = Hs(domain_sep, h) - crypto::point_t A_prime; - A_prime.assign_mul_plus_G(decoded_amount, crypto::c_point_H, blinding_mask); // A' * 8 =? a * H + f * G + crypto::point_t blinded_asset_id = crypto::point_t(zo.blinded_asset_id).modify_mul8(); + crypto::point_t A_prime = decoded_amount * blinded_asset_id + amount_blinding_mask * crypto::c_point_G; // A' * 8 =? a * T + f * G if (A_prime != crypto::point_t(zo.amount_commitment).modify_mul8()) return false; + asset_id_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_ASSET_BLINDING_MASK, h); // f = Hs(domain_sep, d, i) + + // crypto::point_t asset_id = blinded_asset_id - asset_id_blinding_mask * crypto::c_point_X; // H = T - s * X + + return true; } @@ -2631,15 +2725,11 @@ namespace currency } VARIANT_CASE_CONST(tx_out_zarcanum, zo) uint64_t amount = 0; - crypto::scalar_t blinding_mask = 0; - if (is_out_to_acc(acc.account_address, zo, derivation, output_index, amount, blinding_mask)) + crypto::scalar_t amount_blinding_mask = 0, asset_id_blinding_mask = 0; + if (is_out_to_acc(acc.account_address, zo, derivation, output_index, amount, amount_blinding_mask, asset_id_blinding_mask)) { - outs.emplace_back(output_index, amount, blinding_mask); - open_asset_id v = AUTO_VAL_INIT(v); - if (get_type_in_variant_container(zo.etc_details, v)) - { - outs.back().asset_id = v.asset_id; - } + crypto::point_t asset_id_pt = crypto::point_t(zo.blinded_asset_id) - asset_id_blinding_mask * crypto::c_point_X; + outs.emplace_back(output_index, amount, amount_blinding_mask, asset_id_blinding_mask, asset_id_pt.to_public_key()); money_transfered += amount; } VARIANT_SWITCH_END(); @@ -3379,7 +3469,8 @@ namespace currency bool operator()(const zc_outs_range_proof& rp) { tv.type = "zc_outs_range_proof"; - tv.short_view = "outputs_count = " + std::to_string(rp.outputs_count); + // TODO @#@# + //tv.short_view = "outputs_count = " + std::to_string(rp.outputs_count); return true; } bool operator()(const zc_balance_proof& bp) diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index db3f690a..8e71ee5f 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -205,16 +205,19 @@ namespace currency : index(index) , amount(amount) {} - wallet_out_info(size_t index, uint64_t amount, const crypto::scalar_t& blinding_mask) + 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) - , blinding_mask(blinding_mask) + , 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 blinding_mask = 0; - crypto::hash asset_id = currency::null_hash; + 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? }; @@ -249,8 +252,9 @@ namespace currency const keypair* tx_one_time_key_to_use = nullptr); //--------------------------------------------------------------- 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& deriv_cache, const account_keys& self, crypto::scalar_t& out_blinding_mask, 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& 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& 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, extra_attachment_info& eai); @@ -293,7 +297,8 @@ namespace currency 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); - crypto::hash get_asset_id_from_descriptor(const asset_descriptor_base& adb); + void calculate_asset_id(const crypto::public_key& asset_owner, crypto::point_t* p_result_point, crypto::public_key* p_result_pub_key); + 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); @@ -311,7 +316,7 @@ namespace currency crypto::hash get_multisig_out_id(const transaction& tx, size_t n); 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::scalar_t& blinding_mask); + 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::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& 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& outs, uint64_t& money_transfered, crypto::key_derivation& derivation, std::list& htlc_info_list); bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& money_transfered, crypto::key_derivation& derivation); diff --git a/src/currency_core/currency_format_utils_transactions.h b/src/currency_core/currency_format_utils_transactions.h index d123a54a..ed1a4c4f 100644 --- a/src/currency_core/currency_format_utils_transactions.h +++ b/src/currency_core/currency_format_utils_transactions.h @@ -22,13 +22,14 @@ namespace currency 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) - : out_reference(out_reference), stealth_address(stealth_address), concealing_point(concealing_point), amount_commitment(amount_commitment) {} + 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) {} 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 zarcaum outputs - crypto::public_key amount_commitment; // only for zarcaum outputs + 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 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 @@ -37,6 +38,7 @@ namespace currency FIELD(stealth_address) FIELD(concealing_point) FIELD(amount_commitment) + FIELD(blinded_asset_id) END_SERIALIZE() }; @@ -45,7 +47,8 @@ namespace currency std::vector 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; //blinding mask of real out's amount committment (only for zarcanum inputs, otherwise must be 0) + 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 @@ -54,16 +57,18 @@ namespace currency 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::hash asset_id = currency::null_hash; //asset id + 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_zarcanum() const { return !real_out_amount_blinding_mask.is_zero(); } + bool is_multisig() const { return ms_sigs_count > 0; } + bool is_zarcanum() const { return !real_out_amount_blinding_mask.is_zero(); } + bool is_native_coin() const { return asset_id == currency::native_coin_asset_id; } 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) @@ -91,21 +96,23 @@ namespace currency struct tx_destination_entry { - uint64_t amount = 0; //money - std::list 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 amount = 0; // money + std::list 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::hash asset_id = currency::null_hash; + destination_option_htlc_out htlc_options; // htlc options + crypto::public_key asset_id = currency::native_coin_asset_id; 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::hash& aid) : amount(a), addr(1, ad), asset_id(aid) {} + 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& addr) : amount(a), addr(addr), minimum_sigs(addr.size()){} - tx_destination_entry(uint64_t a, const std::list& addr, const crypto::hash& aid) : amount(a), addr(addr), minimum_sigs(addr.size()), asset_id(aid) {} + tx_destination_entry(uint64_t a, const std::list& 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() diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index ce904da3..b99e5752 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -84,7 +84,7 @@ namespace currency struct asset_id_kv { - crypto::hash asset_id; + crypto::public_key asset_id; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE_POD_AS_HEX_STRING(asset_id) @@ -359,16 +359,17 @@ namespace currency struct out_entry { out_entry() = default; - out_entry(uint64_t global_amount_index, const crypto::public_key& stealth_address, const crypto::public_key& amount_commitment, const crypto::public_key& concealing_point) - : global_amount_index(global_amount_index), stealth_address(stealth_address), amount_commitment(amount_commitment), concealing_point(concealing_point) - {} out_entry(uint64_t global_amount_index, const crypto::public_key& stealth_address) - : global_amount_index(global_amount_index), stealth_address(stealth_address), amount_commitment{}, concealing_point{} + : global_amount_index(global_amount_index), stealth_address(stealth_address), concealing_point{}, amount_commitment{}, blinded_asset_id{} + {} + out_entry(uint64_t global_amount_index, const crypto::public_key& stealth_address, const crypto::public_key& amount_commitment, const crypto::public_key& concealing_point, const crypto::public_key& blinded_asset_id) + : global_amount_index(global_amount_index), stealth_address(stealth_address), concealing_point(concealing_point), amount_commitment(amount_commitment), blinded_asset_id(blinded_asset_id) {} uint64_t global_amount_index; crypto::public_key stealth_address; - crypto::public_key concealing_point; - crypto::public_key amount_commitment; + crypto::public_key concealing_point; // premultiplied by 1/8 + crypto::public_key amount_commitment; // premultiplied by 1/8 + crypto::public_key blinded_asset_id; // premultiplied by 1/8 }; #pragma pack(pop) From cf2f806f3041f3d6a4e1daa0e22164d7212d0a61 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 8 Feb 2023 18:50:26 +0100 Subject: [PATCH 040/112] confidential assets: global wallet refactoring (WIP), mainly asset_id type change (hash -> public_key) and blinded_asset_id integration --- src/wallet/wallet2.cpp | 146 +++++++++++++----------- src/wallet/wallet2.h | 81 ++++++++----- src/wallet/wallet_errors.h | 6 +- src/wallet/wallet_public_structs_defs.h | 4 +- 4 files changed, 140 insertions(+), 97 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index d710c52e..5d998c43 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -615,7 +615,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t WLT_LOG_RED(ss.str(), LOG_LEVEL_0); if (m_wcallback) m_wcallback->on_message(i_wallet2_callback::ms_red, ss.str()); - tx_money_got_in_outs -= outs[i_in_outs].amount; + tx_money_got_in_outs -= out.amount; continue; // skip the output } @@ -626,11 +626,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t td.m_ptx_wallet_info = pwallet_info; td.m_internal_output_index = o; td.m_key_image = ki; - if (outs[i_in_outs].asset_id != currency::null_hash) - { - td.m_asset_id.reset(new crypto::hash(outs[i_in_outs].asset_id)); - } - td.m_amount = outs[i_in_outs].amount; + td.m_amount = out.amount; if (m_use_deffered_global_outputs) { if (pglobal_indexes && pglobal_indexes->size() > o) @@ -654,7 +650,9 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t } if (out_type_zc) - td.m_opt_blinding_mask.reset(new crypto::scalar_t(out.blinding_mask)); + { + td.m_zc_info_ptr.reset(new transfer_details_base::ZC_out_info(out.amount_blinding_mask, out.asset_id_blinding_mask, out.asset_id)); + } size_t transfer_index = m_transfers.size() - 1; if (out_is_to_htlc(out_v)) @@ -775,17 +773,21 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t LOG_ERROR("Public key from asset_descriptor_operation(" << ado.descriptor.owner << ") not much with derived public key(" << self_check << "), for tx" << get_transaction_hash(tx)); } else - { - wallet_own_asset_context& asset_context = m_own_asset_descriptors[get_hash_from_POD_objects(CRYPTO_HDS_ASSET_ID, ado.descriptor.owner)]; + { + crypto::public_key asset_id{}; + calculate_asset_id(ado.descriptor.owner, nullptr, &asset_id); + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(m_own_asset_descriptors.count(asset_id) == 0, "asset with asset_id " << asset_id << " has already been registered in the wallet as own asset"); + wallet_own_asset_context& asset_context = m_own_asset_descriptors[asset_id]; asset_context.asset_descriptor = ado.descriptor; asset_context.height = height; std::stringstream ss; - ss << "New Asset Registered:" - << ENDL << "Name: " << asset_context.asset_descriptor.full_name - << ENDL << "Ticker: " << asset_context.asset_descriptor.ticker + ss << "New Asset Registered:" + << ENDL << "asset id: " << asset_id + << ENDL << "Name: " << asset_context.asset_descriptor.full_name + << ENDL << "Ticker: " << asset_context.asset_descriptor.ticker << ENDL << "Total Max Supply: " << print_asset_money(asset_context.asset_descriptor.total_max_supply, asset_context.asset_descriptor.decimal_point) - << ENDL << "Current Supply: " << print_asset_money(asset_context.asset_descriptor.current_supply, asset_context.asset_descriptor.decimal_point) - << ENDL << "DecimalPoint: " << asset_context.asset_descriptor.decimal_point; + << ENDL << "Current Supply: " << print_asset_money(asset_context.asset_descriptor.current_supply, asset_context.asset_descriptor.decimal_point) + << ENDL << "Decimal Point: " << asset_context.asset_descriptor.decimal_point; WLT_LOG_MAGENTA(ss.str(), LOG_LEVEL_0); if (m_wcallback) @@ -1876,7 +1878,7 @@ detail::split_strategy_id_t wallet2::get_current_split_strategy() return tools::detail::ssi_void; } // -void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx, const crypto::hash& asset_id) +void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx, const crypto::public_key& asset_id /* = currency::native_coin_asset_id */) { std::vector extra; std::vector attachments; @@ -1890,7 +1892,7 @@ void wallet2::transfer(uint64_t amount, const currency::account_public_address& } //---------------------------------------------------------------------------------------------------- void wallet2::transfer(uint64_t amount, size_t fake_outs_count, const currency::account_public_address& acc, uint64_t fee /* = TX_DEFAULT_FEE*/, - const crypto::hash& asset_id /* = currency::null_hash */) + const crypto::public_key& asset_id /* = currency::native_coin_asset_id */) { std::vector extra; std::vector attachments; @@ -1904,7 +1906,7 @@ void wallet2::transfer(uint64_t amount, size_t fake_outs_count, const currency:: this->transfer(dst, fake_outs_count, 0, fee, extra, attachments, get_current_split_strategy(), tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD), result_tx); } //---------------------------------------------------------------------------------------------------- -void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc, const crypto::hash& asset_id) +void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc, const crypto::public_key& asset_id /* = currency::native_coin_asset_id */) { transaction result_tx = AUTO_VAL_INIT(result_tx); this->transfer(amount, acc, result_tx, asset_id); @@ -3083,16 +3085,16 @@ uint64_t wallet2::balance(uint64_t& unloked) const return balance(unloked, fake, fake, fake); } //---------------------------------------------------------------------------------------------------- -uint64_t wallet2::balance(uint64_t& unlocked, uint64_t& awaiting_in, uint64_t& awaiting_out, uint64_t& mined) const +uint64_t wallet2::balance(uint64_t& unlocked, uint64_t& awaiting_in, uint64_t& awaiting_out, uint64_t& mined, const crypto::public_key& asset_id /* = currency::native_coin_asset_id */) const { uint64_t total = 0; unlocked = 0; awaiting_in = 0; awaiting_out = 0; mined = 0; - std::unordered_map balances; + std::unordered_map balances; balance(balances, mined); - auto it = balances.find(currency::null_hash); + auto it = balances.find(asset_id); if (it != balances.end()) { total = it->second.total; @@ -3103,7 +3105,7 @@ uint64_t wallet2::balance(uint64_t& unlocked, uint64_t& awaiting_in, uint64_t& a return total; } //---------------------------------------------------------------------------------------------------- -bool wallet2::balance(std::unordered_map& balances, uint64_t& mined) const +bool wallet2::balance(std::unordered_map& balances, uint64_t& mined) const { mined = 0; @@ -3145,9 +3147,9 @@ bool wallet2::balance(std::list& balances, u { load_whitelisted_tokens_if_not_loaded(); balances.clear(); - std::unordered_map balances_map; + std::unordered_map balances_map; this->balance(balances_map, mined); - std::unordered_map custom_assets_local = m_custom_assets; + std::unordered_map custom_assets_local = m_custom_assets; for (auto& own_asset : m_own_asset_descriptors) { @@ -3158,10 +3160,10 @@ bool wallet2::balance(std::list& balances, u } asset_descriptor_base native_asset_info = AUTO_VAL_INIT(native_asset_info); - native_asset_info.full_name = CURRENCY_NAME_SHORT_BASE; - native_asset_info.ticker = CURRENCY_NAME_ABR; - native_asset_info.decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT; - custom_assets_local[currency::null_hash] = native_asset_info; + native_asset_info.full_name = CURRENCY_NAME_SHORT_BASE; + native_asset_info.ticker = CURRENCY_NAME_ABR; + native_asset_info.decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT; + custom_assets_local[currency::native_coin_asset_id] = native_asset_info; for (const auto& item : balances_map) { @@ -3212,7 +3214,7 @@ uint64_t wallet2::balance() const return balance(stub, stub, stub, stub); } //---------------------------------------------------------------------------------------------------- -bool wallet2::add_custom_asset_id(const crypto::hash& asset_id, asset_descriptor_base& asset_descriptor) +bool wallet2::add_custom_asset_id(const crypto::public_key& asset_id, asset_descriptor_base& asset_descriptor) { currency::COMMAND_RPC_GET_ASSET_INFO::request req = AUTO_VAL_INIT(req); currency::COMMAND_RPC_GET_ASSET_INFO::response resp = AUTO_VAL_INIT(resp); @@ -3228,7 +3230,7 @@ bool wallet2::add_custom_asset_id(const crypto::hash& asset_id, asset_descriptor return false; } //---------------------------------------------------------------------------------------------------- -bool wallet2::delete_custom_asset_id(const crypto::hash& asset_id) +bool wallet2::delete_custom_asset_id(const crypto::public_key& asset_id) { auto it = m_custom_assets.find(asset_id); if (it != m_custom_assets.end()) @@ -3271,8 +3273,8 @@ void wallet2::get_transfers(wallet2::transfer_container& incoming_transfers) con bool wallet2::generate_packing_transaction_if_needed(currency::transaction& tx, uint64_t fake_outputs_number) { prepare_free_transfers_cache(0); - auto it = m_found_free_amounts[currency::null_hash].find(CURRENCY_BLOCK_REWARD); - if (it == m_found_free_amounts[currency::null_hash].end() || it->second.size() <= m_pos_mint_packing_size) + auto it = m_found_free_amounts[currency::native_coin_asset_id].find(CURRENCY_BLOCK_REWARD); + if (it == m_found_free_amounts[currency::native_coin_asset_id].end() || it->second.size() <= m_pos_mint_packing_size) return false; //let's check if we have at least WALLET_POS_MINT_PACKING_SIZE transactions which is ready to go @@ -3875,7 +3877,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, currency::bl WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(decoys_resp.outs[0].outs.size() == required_decoys_count + 1, "for PoS stake tx got less decoys to mix than requested: " << decoys_resp.outs[0].outs.size() << " < " << required_decoys_count + 1); auto& decoys = decoys_resp.outs[0].outs; - decoys.emplace_front(td.m_global_output_index, stake_out.stealth_address, stake_out.amount_commitment, stake_out.concealing_point); + decoys.emplace_front(td.m_global_output_index, stake_out.stealth_address, stake_out.amount_commitment, stake_out.concealing_point, stake_out.blinded_asset_id); std::unordered_set used_gindices; size_t good_outs_count = 0; @@ -3921,7 +3923,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, currency::bl #ifndef NDEBUG { - crypto::point_t source_amount_commitment = crypto::c_scalar_1div8 * td.m_amount * crypto::c_point_H + crypto::c_scalar_1div8 * *td.m_opt_blinding_mask * crypto::c_point_G; + crypto::point_t source_amount_commitment = crypto::c_scalar_1div8 * td.m_amount * crypto::c_point_H + crypto::c_scalar_1div8 * td.m_zc_info_ptr->amount_blinding_mask * crypto::c_point_G; CHECK_AND_ASSERT_MES(stake_out.amount_commitment == source_amount_commitment.to_public_key(), false, "real output amount commitment check failed"); CHECK_AND_ASSERT_MES(ring[secret_index].amount_commitment == stake_out.amount_commitment, false, "ring secret member doesn't match with the stake output"); } @@ -3999,12 +4001,12 @@ void wallet2::do_pos_mining_prepare_entry(mining_context& context, size_t transf CHECK_AND_ASSERT_MES_NO_RET(transfer_index < m_transfers.size(), "transfer_index is out of bounds: " << transfer_index); const transfer_details& td = m_transfers[transfer_index]; - crypto::scalar_t blinding_mask{}; - if (td.m_opt_blinding_mask) - blinding_mask = *td.m_opt_blinding_mask; + crypto::scalar_t amount_blinding_mask{}; + if (td.is_zc()) + amount_blinding_mask = td.m_zc_info_ptr->amount_blinding_mask; context.prepare_entry(td.amount(), td.m_key_image, get_tx_pub_key_from_extra(td.m_ptx_wallet_info->m_tx), td.m_internal_output_index, - blinding_mask, m_account.get_keys().view_secret_key); + amount_blinding_mask, m_account.get_keys().view_secret_key); } //------------------------------------------------------------------ bool wallet2::do_pos_mining_iteration(mining_context& context, size_t transfer_index, uint64_t ts) @@ -4320,7 +4322,7 @@ void wallet2::request_alias_registration(currency::extra_alias_entry& ai, curren transfer(destinations, 0, 0, fee, extra, attachments, get_current_split_strategy(), tx_dust_policy(DEFAULT_DUST_THRESHOLD), res_tx, CURRENCY_TO_KEY_OUT_RELAXED, false); } //---------------------------------------------------------------------------------------------------- -void wallet2::publish_new_asset(const currency::asset_descriptor_base& asset_info, const std::vector& destinations, currency::transaction& result_tx, crypto::hash& asset_id) +void wallet2::publish_new_asset(const currency::asset_descriptor_base& asset_info, const std::vector& destinations, currency::transaction& result_tx, crypto::public_key& new_asset_id) { asset_descriptor_operation asset_reg_info = AUTO_VAL_INIT(asset_reg_info); asset_reg_info.descriptor = asset_info; @@ -4336,7 +4338,7 @@ void wallet2::publish_new_asset(const currency::asset_descriptor_base& asset_inf currency::asset_descriptor_operation ado = AUTO_VAL_INIT(ado); bool r = get_type_in_variant_container(result_tx.extra, ado); CHECK_AND_ASSERT_THROW_MES(r, "Failed find asset info in tx"); - asset_id = get_asset_id_from_descriptor(ado.descriptor); + calculate_asset_id(ado.descriptor.owner, nullptr, &new_asset_id); } //---------------------------------------------------------------------------------------------------- void wallet2::request_alias_update(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward) @@ -4881,8 +4883,11 @@ bool wallet2::check_htlc_redeemed(const crypto::hash& htlc_tx_id, std::string& o bool wallet2::prepare_tx_sources_for_packing(uint64_t items_to_pack, size_t fake_outputs_count, std::vector& sources, std::vector& selected_indicies, uint64_t& found_money) { prepare_free_transfers_cache(fake_outputs_count); - auto it = m_found_free_amounts[currency::null_hash].find(CURRENCY_BLOCK_REWARD); - if (it == m_found_free_amounts[currency::null_hash].end() || it->second.size() < m_pos_mint_packing_size) + + free_amounts_cache_type& free_amounts_for_native_coin = m_found_free_amounts[currency::native_coin_asset_id]; + + auto it = free_amounts_for_native_coin.find(CURRENCY_BLOCK_REWARD); + if (it == free_amounts_for_native_coin.end() || it->second.size() < m_pos_mint_packing_size) return false; for (auto set_it = it->second.begin(); set_it != it->second.end() && selected_indicies.size() <= m_pos_mint_packing_size; ) @@ -4899,7 +4904,7 @@ bool wallet2::prepare_tx_sources_for_packing(uint64_t items_to_pack, size_t fake set_it++; } if (!it->second.size()) - m_found_free_amounts[currency::null_hash].erase(it); + free_amounts_for_native_coin.erase(it); return prepare_tx_sources(fake_outputs_count, sources, selected_indicies); } @@ -5038,11 +5043,14 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vectoramount_blinding_mask; + src.real_out_asset_id_blinding_mask = td.m_zc_info_ptr->asset_id_blinding_mask; + src.asset_id = td.m_zc_info_ptr->asset_id; VARIANT_SWITCH_END(); auto interted_it = src.outputs.insert(it_to_insert, real_oe); @@ -5144,10 +5152,10 @@ bool wallet2::prepare_tx_sources_htlc(crypto::hash htlc_tx_id, const std::string assets_selection_context wallet2::get_needed_money(uint64_t fee, const std::vector& dsts) { assets_selection_context amounts_map; - amounts_map[currency::null_hash].needed_amount = fee; + amounts_map[currency::native_coin_asset_id].needed_amount = fee; for(auto& dt : dsts) { - if(dt.asset_id == currency::ffff_hash) + if(dt.asset_id == currency::ffff_pkey) continue; //this destination for emmition only THROW_IF_TRUE_WALLET_EX(0 == dt.amount, error::zero_destination); @@ -5561,7 +5569,7 @@ void wallet2::add_transfers_to_transfers_cache(const std::vector& inde add_transfer_to_transfers_cache(m_transfers[i].amount(), i, m_transfers[i].get_asset_id()); } //---------------------------------------------------------------------------------------------------- -void wallet2::add_transfer_to_transfers_cache(uint64_t amount, uint64_t index, const crypto::hash& asset_id) +void wallet2::add_transfer_to_transfers_cache(uint64_t amount, uint64_t index, const crypto::public_key& asset_id /* = currency::native_coin_asset_id */) { m_found_free_amounts[asset_id][amount].insert(index); } @@ -5760,7 +5768,7 @@ void wallet2::print_source_entry(std::stringstream& output, const currency::tx_s << ", real_output_in_tx_index: " << src.real_output_in_tx_index << ", indexes: " << ss.str(); - if (src.asset_id != currency::null_hash) + if (src.asset_id != currency::native_coin_asset_id) output << ", asset_id: " << print16(src.asset_id); } //---------------------------------------------------------------------------------------------------- @@ -5793,7 +5801,7 @@ void wallet2::prepare_tx_destinations(const assets_selection_context& needed_mon { // special case for asset minting destinations for (auto& dst : dsts) - if (dst.asset_id == currency::ffff_hash) + if (dst.asset_id == currency::ffff_pkey) final_destinations.emplace_back(dst.amount, dst.addr, dst.asset_id); // if there's not ehough destinations items (i.e. outputs), split the last one @@ -5816,7 +5824,7 @@ void wallet2::prepare_tx_destinations(uint64_t needed_money, detail::split_strategy_id_t destination_split_strategy_id, const tx_dust_policy& dust_policy, const std::vector& dsts, - std::vector& final_destinations, const crypto::hash& asset_id) + std::vector& final_destinations, const crypto::public_key& asset_id) { WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(found_money >= needed_money, "needed_money==" << needed_money << " < found_money==" << found_money); @@ -5833,7 +5841,7 @@ void wallet2::prepare_tx_destinations(uint64_t needed_money, else { // pre-HF4 - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(asset_id == currency::null_hash, "assets are not allowed prior to HF4"); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(asset_id == currency::native_coin_asset_id, "assets are not allowed prior to HF4"); currency::tx_destination_entry change_dts = AUTO_VAL_INIT(change_dts); if (needed_money < found_money) { @@ -5857,11 +5865,15 @@ void wallet2::prepare_transaction(construct_tx_param& ctp, currency::finalize_tx TIME_MEASURE_START_MS(get_needed_money_time); assets_selection_context needed_money_map = get_needed_money(ctp.fee, ctp.dsts); - //@#@ need to do refactoring over this part to support hidden amounts and asset_id + + // + // TODO @#@# need to do refactoring over this part to support hidden amounts and asset_id + // + if (ctp.flags & TX_FLAG_SIGNATURE_MODE_SEPARATE && tx_for_mode_separate.vout.size() ) { WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(get_tx_flags(tx_for_mode_separate) & TX_FLAG_SIGNATURE_MODE_SEPARATE, "tx_param.flags differs from tx.flags"); - needed_money_map[currency::null_hash].needed_amount += (currency::get_outs_money_amount(tx_for_mode_separate) - get_inputs_money_amount(tx_for_mode_separate)); + needed_money_map[currency::null_pkey].needed_amount += (currency::get_outs_money_amount(tx_for_mode_separate) - get_inputs_money_amount(tx_for_mode_separate)); } TIME_MEASURE_FINISH_MS(get_needed_money_time); @@ -5870,28 +5882,28 @@ void wallet2::prepare_transaction(construct_tx_param& ctp, currency::finalize_tx TIME_MEASURE_START_MS(prepare_tx_sources_time); if (ctp.perform_packing) { - prepare_tx_sources_for_packing(WALLET_DEFAULT_POS_MINT_PACKING_SIZE, 0, ftp.sources, ftp.selected_transfers, needed_money_map[currency::null_hash].found_amount); + prepare_tx_sources_for_packing(WALLET_DEFAULT_POS_MINT_PACKING_SIZE, 0, ftp.sources, ftp.selected_transfers, needed_money_map[currency::null_pkey].found_amount); } else if (ctp.htlc_tx_id != currency::null_hash) { //htlc //@#@ need to do refactoring over this part to support hidden amounts and asset_id - prepare_tx_sources_htlc(ctp.htlc_tx_id, ctp.htlc_origin, ftp.sources, needed_money_map[currency::null_hash].found_amount); + prepare_tx_sources_htlc(ctp.htlc_tx_id, ctp.htlc_origin, ftp.sources, needed_money_map[currency::null_pkey].found_amount); WLT_THROW_IF_FALSE_WITH_CODE(ctp.dsts.size() == 1, "htlc: unexpected ctp.dsts.size() =" << ctp.dsts.size(), API_RETURN_CODE_INTERNAL_ERROR); - WLT_THROW_IF_FALSE_WITH_CODE(needed_money_map[currency::null_hash].found_amount > ctp.fee, + WLT_THROW_IF_FALSE_WITH_CODE(needed_money_map[currency::null_pkey].found_amount > ctp.fee, "htlc: found money less then fee", API_RETURN_CODE_INTERNAL_ERROR); //fill amount - ctp.dsts.begin()->amount = needed_money_map[currency::null_hash].found_amount - ctp.fee; + ctp.dsts.begin()->amount = needed_money_map[currency::null_pkey].found_amount - ctp.fee; } else if (ctp.multisig_id != currency::null_hash) { //multisig //@#@ need to do refactoring over this part to support hidden amounts and asset_id - prepare_tx_sources(ctp.multisig_id, ftp.sources, needed_money_map[currency::null_hash].found_amount); + prepare_tx_sources(ctp.multisig_id, ftp.sources, needed_money_map[currency::null_pkey].found_amount); } else { @@ -6289,7 +6301,7 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public { if (td.m_global_output_index == daemon_oe.global_amount_index) continue; - src.outputs.emplace_back(daemon_oe.global_amount_index, daemon_oe.stealth_address, daemon_oe.concealing_point, daemon_oe.amount_commitment); + src.outputs.emplace_back(daemon_oe.global_amount_index, daemon_oe.stealth_address, daemon_oe.concealing_point, daemon_oe.amount_commitment, daemon_oe.blinded_asset_id); if (src.outputs.size() >= fake_outs_count) break; } @@ -6323,9 +6335,11 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public VARIANT_SWITCH_END(); } VARIANT_CASE_CONST(tx_out_zarcanum, o); - interted_it = src.outputs.emplace(it_to_insert, out_reference, o.stealth_address, o.concealing_point, o.amount_commitment); - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_opt_blinding_mask, "m_opt_blinding_mask is null, transfer index: " << tr_index << ", amount: " << print_money_brief(td.amount())); - src.real_out_amount_blinding_mask = *td.m_opt_blinding_mask; + interted_it = src.outputs.emplace(it_to_insert, out_reference, o.stealth_address, o.concealing_point, o.amount_commitment, o.blinded_asset_id); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.is_zc(), "transfer #" << tr_index << ", amount: " << print_money_brief(td.amount()) << " is not a ZC"); + src.real_out_amount_blinding_mask = td.m_zc_info_ptr->amount_blinding_mask; + src.real_out_asset_id_blinding_mask = td.m_zc_info_ptr->asset_id_blinding_mask; + src.asset_id = td.m_zc_info_ptr->asset_id; VARIANT_SWITCH_END(); src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_ptx_wallet_info->m_tx); src.real_output = interted_it - src.outputs.begin(); @@ -6338,7 +6352,7 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public // try to construct a transaction assets_selection_context needed_money_map; - needed_money_map[currency::null_hash] = {}; + needed_money_map[currency::native_coin_asset_id] = {}; std::vector dsts({ tx_destination_entry(amount_swept - fee, destination_addr) }); prepare_tx_destinations(needed_money_map, get_current_split_strategy(), tools::tx_dust_policy(), dsts, ftp.prepared_destinations); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index b00bbe1b..e5ae7290 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -303,7 +303,7 @@ namespace tools uint64_t found_amount = 0; //std::vector selected_indicies; }; - typedef std::unordered_map assets_selection_context; + typedef std::unordered_map assets_selection_context; class wallet2: public tools::tor::t_transport_state_notifier { @@ -339,25 +339,43 @@ namespace tools struct transfer_details_base { + struct ZC_out_info // TODO: @#@# consider using wallet_out_info instead + { + ZC_out_info() = default; + ZC_out_info(const crypto::scalar_t& amount_blinding_mask, const crypto::scalar_t& asset_id_blinding_mask, const crypto::public_key& asset_id) + : amount_blinding_mask(amount_blinding_mask), asset_id_blinding_mask(asset_id_blinding_mask), asset_id(asset_id) + {} + crypto::scalar_t amount_blinding_mask = 0; + crypto::scalar_t asset_id_blinding_mask = 0; + crypto::public_key asset_id = currency::null_pkey; // not blinded, not multiplied by 1/8 TODO: @#@# consider changing to point_t, also consider using wallet wallet_out_info + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(amount_blinding_mask) + KV_SERIALIZE(asset_id_blinding_mask) + KV_SERIALIZE_POD_AS_HEX_STRING(asset_id) + END_KV_SERIALIZE_MAP() + }; + std::shared_ptr m_ptx_wallet_info; uint64_t m_internal_output_index = 0; uint64_t m_spent_height = 0; uint32_t m_flags = 0; uint64_t m_amount = 0; - boost::shared_ptr m_opt_blinding_mask; - boost::shared_ptr m_asset_id; + boost::shared_ptr m_zc_info_ptr; + uint64_t amount() const { return m_amount; } + // @#@ will throw if type is not tx_out_bare, TODO: change according to new model, // need to replace all get_tx_out_bare_from_out_v() to proper code - uint64_t amount() const { return m_amount; } - const currency::tx_out_bare& output() const { return currency::get_tx_out_bare_from_out_v(m_ptx_wallet_info->m_tx.vout[m_internal_output_index]); } - uint8_t mix_attr() const { return output().target.type() == typeid(currency::txout_to_key) ? boost::get(output().target).mix_attr : UINT8_MAX; } + //const currency::tx_out_bare& output() const { return currency::get_tx_out_bare_from_out_v(m_ptx_wallet_info->m_tx.vout[m_internal_output_index]); } + + const currency::tx_out_v& output() const { return m_ptx_wallet_info->m_tx.vout[m_internal_output_index]; } + uint8_t mix_attr() const { uint8_t result = UINT8_MAX; get_mix_attr_from_tx_out_v(output(), result); return result; } crypto::hash tx_hash() const { return get_transaction_hash(m_ptx_wallet_info->m_tx); } bool is_spent() const { return m_flags & WALLET_TRANSFER_DETAIL_FLAG_SPENT; } bool is_spendable() const { return (m_flags & (WALLET_TRANSFER_DETAIL_FLAG_SPENT | WALLET_TRANSFER_DETAIL_FLAG_BLOCKED | WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION | WALLET_TRANSFER_DETAIL_FLAG_COLD_SIG_RESERVATION)) == 0; } bool is_reserved_for_escrow() const { return ( (m_flags & WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION) != 0 ); } - bool is_zc() const { return m_opt_blinding_mask.get(); } - const crypto::hash& get_asset_id() const { if (m_asset_id.get()) { return *m_asset_id; } else { return currency::null_hash; } } + bool is_zc() const { return m_zc_info_ptr.get(); } + const crypto::public_key& get_asset_id() const { if (m_zc_info_ptr.get()) { return m_zc_info_ptr->asset_id; } else { return currency::native_coin_asset_id; } } BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE_CUSTOM(m_ptx_wallet_info, const transaction_wallet_info&, tools::wallet2::transform_ptr_to_value, tools::wallet2::transform_value_to_ptr) @@ -365,8 +383,8 @@ namespace tools KV_SERIALIZE(m_spent_height) KV_SERIALIZE(m_flags) KV_SERIALIZE(m_amount) - KV_SERIALIZE_N(m_opt_blinding_mask, "blinding_mask") - KV_SERIALIZE(m_asset_id) + //KV_SERIALIZE_N(m_opt_blinding_mask, "blinding_mask") + KV_SERIALIZE_N(m_zc_info_ptr, "zc_out_info") KV_SERIALIZE_EPHEMERAL_N(uint64_t, tools::wallet2::transfer_details_base_to_amount, "amount") KV_SERIALIZE_EPHEMERAL_N(std::string, tools::wallet2::transfer_details_base_to_tx_hash, "tx_id") END_KV_SERIALIZE_MAP() @@ -446,7 +464,7 @@ namespace tools typedef std::unordered_map multisig_transfer_container; typedef std::unordered_map escrow_contracts_container; typedef std::map > free_amounts_cache_type; - typedef std::unordered_map free_assets_amounts_cache_type; + typedef std::unordered_map free_assets_amounts_cache_type; typedef std::unordered_map, uint64_t> amount_gindex_to_transfer_id_container; // maps [amount; gindex] -> tid @@ -557,24 +575,24 @@ namespace tools void request_alias_update(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward); bool check_available_sources(std::list& amounts); - void publish_new_asset(const currency::asset_descriptor_base& asset_info, const std::vector& destinations, currency::transaction& result_tx, crypto::hash& asset_id); + void publish_new_asset(const currency::asset_descriptor_base& asset_info, const std::vector& destinations, currency::transaction& result_tx, crypto::public_key& new_asset_id); bool set_core_proxy(const std::shared_ptr& proxy); void set_pos_mint_packing_size(uint64_t new_size); void set_minimum_height(uint64_t h); std::shared_ptr get_core_proxy(); uint64_t balance() const; - uint64_t balance(uint64_t& unloked, uint64_t& awaiting_in, uint64_t& awaiting_out, uint64_t& mined) const; - bool balance(std::unordered_map& balances, uint64_t& mined) const; + uint64_t balance(uint64_t& unloked, uint64_t& awaiting_in, uint64_t& awaiting_out, uint64_t& mined, const crypto::public_key& asset_id = currency::native_coin_asset_id) const; + bool balance(std::unordered_map& balances, uint64_t& mined) const; bool balance(std::list& balances, uint64_t& mined) const; uint64_t balance(uint64_t& unloked) const; uint64_t unlocked_balance() const; - void transfer(uint64_t amount, const currency::account_public_address& acc, const crypto::hash& asset_id = currency::null_hash); - void transfer(uint64_t amount, size_t fake_outs_count, const currency::account_public_address& acc, uint64_t fee = TX_DEFAULT_FEE, const crypto::hash& asset_id = currency::null_hash); - void transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx, const crypto::hash& asset_id = currency::null_hash); + void transfer(uint64_t amount, const currency::account_public_address& acc, const crypto::public_key& asset_id = currency::native_coin_asset_id); + void transfer(uint64_t amount, size_t fake_outs_count, const currency::account_public_address& acc, uint64_t fee = TX_DEFAULT_FEE, const crypto::public_key& asset_id = currency::native_coin_asset_id); + void transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx, const crypto::public_key& asset_id = currency::native_coin_asset_id); void transfer(const std::vector& dsts, size_t fake_outputs_count, @@ -899,10 +917,10 @@ namespace tools uint64_t get_default_fee() {return TX_DEFAULT_FEE;} void export_transaction_history(std::ostream& ss, const std::string& format, bool include_pos_transactions = true); - bool add_custom_asset_id(const crypto::hash& asset_id, currency::asset_descriptor_base& asset_descriptor); - bool delete_custom_asset_id(const crypto::hash& asset_id); + bool add_custom_asset_id(const crypto::public_key& asset_id, currency::asset_descriptor_base& asset_descriptor); + bool delete_custom_asset_id(const crypto::public_key& asset_id); bool load_whitelisted_tokens_if_not_loaded() const; - bool load_whitelisted_tokens()const; + bool load_whitelisted_tokens() const; /* create_htlc_proposal: if htlc_hash == null_hash, then this wallet is originator of the atomic process, and @@ -939,7 +957,7 @@ private: bool prepare_free_transfers_cache(uint64_t fake_outputs_count); bool select_transfers(assets_selection_context& needed_money_map, size_t fake_outputs_count, uint64_t dust, std::vector& selected_indicies); void add_transfers_to_transfers_cache(const std::vector& indexs); - void add_transfer_to_transfers_cache(uint64_t amount, uint64_t index, const crypto::hash& asset_id = currency::null_hash); + void add_transfer_to_transfers_cache(uint64_t amount, uint64_t index, const crypto::public_key& asset_id = currency::native_coin_asset_id); bool prepare_file_names(const std::wstring& file_path); void process_unconfirmed(const currency::transaction& tx, std::vector& recipients, std::vector& recipients_aliases); void add_sent_unconfirmed_tx(const currency::transaction& tx, @@ -991,7 +1009,7 @@ private: detail::split_strategy_id_t destination_split_strategy_id, const tx_dust_policy& dust_policy, const std::vector& dsts, - std::vector& final_detinations, const crypto::hash& assed_id); + std::vector& final_detinations, const crypto::public_key& asset_id); bool handle_contract(wallet_public::wallet_transfer_info& wti, const bc_services::contract_private_details& cntr, const std::vector& decrypted_attach); bool handle_release_contract(wallet_public::wallet_transfer_info& wti, const std::string& release_instruction); bool handle_cancel_proposal(wallet_public::wallet_transfer_info& wti, const bc_services::escrow_cancel_templates_body& ectb, const std::vector& decrypted_attach); @@ -1099,9 +1117,9 @@ private: std::unordered_map m_unconfirmed_txs; std::unordered_set m_unconfirmed_multisig_transfers; std::unordered_map m_tx_keys; - std::unordered_map m_own_asset_descriptors; - std::unordered_map m_custom_assets; //assets that manually added by user - mutable std::unordered_map m_whitelisted_assets; //assets that whitelisted + std::unordered_map m_own_asset_descriptors; + std::unordered_map m_custom_assets; //assets that manually added by user + mutable std::unordered_map m_whitelisted_assets; //assets that whitelisted std::multimap m_htlcs; //map [expired_if_more_then] -> height of expiration @@ -1151,6 +1169,14 @@ namespace boost a & x.m_tx; } + template + inline void serialize(Archive& a, tools::wallet2::transfer_details_base::ZC_out_info& x, const boost::serialization::version_type ver) + { + a & x.amount_blinding_mask; + a & x.asset_id_blinding_mask; + a & x.asset_id; + } + template inline void serialize(Archive &a, tools::wallet2::transfer_details_base &x, const boost::serialization::version_type ver) { @@ -1160,12 +1186,11 @@ namespace boost a & x.m_spent_height; if (ver < 2) { - x.m_amount = currency::get_tx_out_bare_from_out_v(x.m_ptx_wallet_info->m_tx.vout[x.m_internal_output_index]).amount; + x.m_amount = get_amount_from_variant(x.output()); return; } a & x.m_amount; - a & x.m_opt_blinding_mask; - a & x.m_asset_id; + a & x.m_zc_info_ptr; } diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index 973c5e95..69c961b8 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -349,11 +349,12 @@ namespace tools //---------------------------------------------------------------------------------------------------- struct not_enough_money : public transfer_error { - not_enough_money(std::string&& loc, uint64_t availbable, uint64_t tx_amount, uint64_t fee, const crypto::hash& assset_id) + not_enough_money(std::string&& loc, uint64_t availbable, uint64_t tx_amount, uint64_t fee, const crypto::public_key& asset_id) : transfer_error(std::move(loc), "NOT_ENOUGH_MONEY") , m_available(availbable) , m_tx_amount(tx_amount) , m_fee(fee) + , m_asset_id(asset_id) { } @@ -368,6 +369,8 @@ namespace tools ", available = " << currency::print_money(m_available) << ", tx_amount = " << currency::print_money(m_tx_amount) << ", fee = " << currency::print_money(m_fee); + if (m_asset_id != currency::native_coin_asset_id) + ss << ", asset_id = " << m_asset_id; return ss.str(); } @@ -375,6 +378,7 @@ namespace tools uint64_t m_available; uint64_t m_tx_amount; uint64_t m_fee; + crypto::public_key m_asset_id; }; //---------------------------------------------------------------------------------------------------- struct not_enough_outs_to_mix : public transfer_error diff --git a/src/wallet/wallet_public_structs_defs.h b/src/wallet/wallet_public_structs_defs.h index 22da411d..06d08f33 100644 --- a/src/wallet/wallet_public_structs_defs.h +++ b/src/wallet/wallet_public_structs_defs.h @@ -114,7 +114,7 @@ namespace wallet_public std::vector contract; uint16_t extra_flags; uint64_t transfer_internal_index; - crypto::hash asset_id; + crypto::public_key asset_id; // not blinded, not premultiplied by 1/8 //not included in kv serialization map @@ -144,7 +144,7 @@ namespace wallet_public KV_SERIALIZE(contract) KV_SERIALIZE(service_entries) KV_SERIALIZE(transfer_internal_index) - KV_SERIALIZE(asset_id) + KV_SERIALIZE_POD_AS_HEX_STRING(asset_id) END_KV_SERIALIZE_MAP() }; From f978be8b907ea3cbe36b6d917d6b595183241271 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 8 Feb 2023 18:54:25 +0100 Subject: [PATCH 041/112] range proofs: Zano now uses U and G generators for aggregable range proof amount commitments --- src/crypto/range_proofs.h | 3 ++- src/currency_core/blockchain_storage.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/crypto/range_proofs.h b/src/crypto/range_proofs.h index 4e25ed79..1b77cfde 100644 --- a/src/crypto/range_proofs.h +++ b/src/crypto/range_proofs.h @@ -131,7 +131,7 @@ namespace crypto }; // struct bpp_crypto_trait_zano template - const point_t& bpp_crypto_trait_zano::bpp_G = c_point_H; + const point_t& bpp_crypto_trait_zano::bpp_G = c_point_U; template const point_t& bpp_crypto_trait_zano::bpp_H = c_point_G; @@ -139,6 +139,7 @@ namespace crypto template const point_t& bpp_crypto_trait_zano::bpp_H2 = c_point_X; + // efficient multiexponentiation (naive stub implementation atm, TODO) template diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 4ef4b1e9..1e565526 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -4961,7 +4961,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, //TIME_MEASURE_START_PD(tx_input_check_clsag_gg); - bool r = crypto::verify_CLSAG_GG(tx_hash_for_signature, ring, sig.pseudo_out_amount_commitment, zc_in.k_image, sig.clsags_gg); + bool r = crypto::verify_CLSAG_GG(tx_hash_for_signature, ring, sig.pseudo_out_amount_commitment, zc_in.k_image, sig.); CHECK_AND_ASSERT_MES(r, false, "verify_CLSAG_GG failed"); //TIME_MEASURE_FINISH_PD(tx_input_check_clsag_gg); From f3583c287386ca953fa9272f8dd8668a619c2b8e Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 8 Feb 2023 18:55:25 +0100 Subject: [PATCH 042/112] coretests: zaranum_in_alt_chain test improvements (forgotten) --- tests/core_tests/zarcanum_test.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/tests/core_tests/zarcanum_test.cpp b/tests/core_tests/zarcanum_test.cpp index 1d04d39a..f1d88db8 100644 --- a/tests/core_tests/zarcanum_test.cpp +++ b/tests/core_tests/zarcanum_test.cpp @@ -643,8 +643,10 @@ bool zarcanum_in_alt_chain::generate(std::vector& events) cons REWIND_BLOCKS_N_WITH_TIME(events, blk_4r, blk_4, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); // Bob: move all to miner - MAKE_TX(events, tx_2, bob_acc, miner_acc, bob_amount - TESTS_DEFAULT_FEE, blk_4r); - MAKE_NEXT_BLOCK_TX1(events, blk_5, blk_4r, miner_acc, tx_2); + MAKE_TX(events, tx_2a, bob_acc, miner_acc, bob_amount - TESTS_DEFAULT_FEE, blk_4r); + // Miner: a little to Alice + MAKE_TX(events, tx_2b, miner_acc, alice_acc, COIN, blk_4r); + MAKE_NEXT_BLOCK_TX_LIST(events, blk_5, blk_4r, miner_acc, std::list({ tx_2a, tx_2b })); // now in the main chain Bob has zero coins // check it @@ -655,7 +657,7 @@ bool zarcanum_in_alt_chain::generate(std::vector& events) cons // TODO: check PoS mining against already spent key image std::list bob_stake_sources({ bob_acc }); - MAKE_NEXT_POS_BLOCK(events, blk_5a, blk_4r, bob_acc, bob_stake_sources); + MAKE_NEXT_POS_BLOCK(events, blk_5a, blk_4r, bob_acc, bob_stake_sources); // NOTE: tx_2a and blk_5a spend the same Bob's output MAKE_NEXT_BLOCK(events, blk_6a, blk_5a, miner_acc); DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(get_block_height(blk_6a), get_block_hash(blk_6a))); @@ -664,7 +666,10 @@ bool zarcanum_in_alt_chain::generate(std::vector& events) cons DO_CALLBACK(events, "c1"); - //MAKE_NEXT_POS_BLOCK(events, blk_7a, blk_5a, miner_acc, miner_stake_sources); + REWIND_BLOCKS_N_WITH_TIME(events, blk_5r, blk_5, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + + MAKE_NEXT_POS_BLOCK(events, blk_6, blk_5r, alice_acc, alice_stake_sources); + MAKE_NEXT_BLOCK(events, blk_7, blk_6, miner_acc); return true; } @@ -677,7 +682,8 @@ bool zarcanum_in_alt_chain::c1(currency::core& c, size_t ev_index, const std::ve std::shared_ptr bob_wlt = init_playtime_test_wallet(events, c, BOB_ACC_IDX); bob_wlt->refresh(); - CHECK_AND_FORCE_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool"); + // tx_2a, tx_2b + CHECK_AND_FORCE_ASSERT_MES(c.get_pool_transactions_count() == 2, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count()); uint64_t stub = 0; uint64_t alice_balance_before = alice_wlt->balance(stub); @@ -688,15 +694,16 @@ bool zarcanum_in_alt_chain::c1(currency::core& c, size_t ev_index, const std::ve size_t nmix = 38; bob_wlt->transfer(transfer_amount, nmix, m_accounts[ALICE_ACC_IDX].get_public_address(), transfer_fee); - CHECK_AND_FORCE_ASSERT_MES(c.get_pool_transactions_count() == 2, false, "Incorrect txs count in the pool"); + CHECK_AND_FORCE_ASSERT_MES(c.get_pool_transactions_count() == 3, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count()); r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c); CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed"); - CHECK_AND_FORCE_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool"); + // tx_2a can't be added as it's ki is spent + CHECK_AND_FORCE_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count()); alice_wlt->refresh(); - CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", alice_balance_before + transfer_amount ), false, ""); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", alice_balance_before + transfer_amount + COIN), false, ""); // COIN is from tx_2b bob_wlt->refresh(); CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt, "Bob", bob_balance_before - transfer_amount- transfer_fee), false, ""); From 7652a117cda32d08c3ad9ab502d1ec0fa2539faf Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 9 Feb 2023 23:35:33 +0100 Subject: [PATCH 043/112] confidential assets: core & wallet refactoring, various fixes, WIP --- src/crypto/zarcanum.h | 4 +- src/currency_core/blockchain_storage.cpp | 28 +++++----- src/currency_core/currency_format_utils.h | 1 + .../currency_format_utils_transactions.h | 2 +- src/simplewallet/simplewallet.cpp | 32 ++++++------ src/wallet/view_iface.h | 2 +- src/wallet/wallet2.cpp | 20 +++++-- src/wallet/wallet2.h | 1 + src/wallet/wallet_public_structs_defs.h | 1 + src/wallet/wallet_rpc_server.cpp | 12 ++--- tests/functional_tests/crypto_tests.cpp | 52 ++++++++++--------- 11 files changed, 87 insertions(+), 68 deletions(-) diff --git a/src/crypto/zarcanum.h b/src/crypto/zarcanum.h index 25056142..bfb20a53 100644 --- a/src/crypto/zarcanum.h +++ b/src/crypto/zarcanum.h @@ -66,7 +66,7 @@ namespace crypto 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_secrets, + inline bool generate_vector_UG_aggregation_proof(const hash& m, const scalar_vec_t& u_secrets, const scalar_vec_t& g_secrets, const std::vector& amount_commitments, const std::vector& amount_commitments_for_rp_aggregation, const std::vector& blinded_asset_ids, @@ -89,7 +89,7 @@ namespace crypto } - bool verify_vector_UG_aggregation_proof(const hash& m, const std::vector amount_commitments, const std::vector blinded_asset_ids, + inline bool verify_vector_UG_aggregation_proof(const hash& m, const std::vector amount_commitments, const std::vector blinded_asset_ids, const vector_UG_aggregation_proof& sig, uint8_t* p_err = nullptr) { return false; diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 1e565526..6dff8edd 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -3547,7 +3547,7 @@ bool blockchain_storage::unprocess_blockchain_tx_extra(const transaction& tx) crypto::public_key asset_id = currency::null_pkey; if (ei.m_asset_operation.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER) { - calculate_asset_id(ei.m_asset_operation.descriptor, nullptr, &asset_id); + calculate_asset_id(ei.m_asset_operation.descriptor.owner, nullptr, &asset_id); } else { @@ -3808,7 +3808,7 @@ bool blockchain_storage::put_asset_info(const transaction & tx, asset_descriptor if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER) { crypto::public_key asset_id{}; - calculate_asset_id(ado.descriptor, nullptr, &asset_id); + calculate_asset_id(ado.descriptor.owner, nullptr, &asset_id); auto asset_history_ptr = m_db_assets.find(asset_id); CHECK_AND_ASSERT_MES(!asset_history_ptr, false, "Asset id already existing"); assets_container::t_value_type local_asset_history = AUTO_VAL_INIT(local_asset_history); @@ -4948,10 +4948,10 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, // TODO: consider additional checks here // build a ring of references - vector ring; + vector ring; ring.reserve(scan_contex.zc_outs.size()); for(auto& zc_out : scan_contex.zc_outs) - ring.emplace_back(zc_out.stealth_address, zc_out.amount_commitment); + ring.emplace_back(zc_out.stealth_address, zc_out.amount_commitment, zc_out.blinded_asset_id); // calculate corresponding tx prefix hash crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, in_index, tx_prefix_hash); @@ -4961,8 +4961,8 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, //TIME_MEASURE_START_PD(tx_input_check_clsag_gg); - bool r = crypto::verify_CLSAG_GG(tx_hash_for_signature, ring, sig.pseudo_out_amount_commitment, zc_in.k_image, sig.); - CHECK_AND_ASSERT_MES(r, false, "verify_CLSAG_GG failed"); + bool r = crypto::verify_CLSAG_GGX(tx_hash_for_signature, ring, sig.pseudo_out_amount_commitment, sig.pseudo_out_blinded_asset_id, zc_in.k_image, sig.clsags_ggx); + CHECK_AND_ASSERT_MES(r, false, "verify_CLSAG_GGX failed"); //TIME_MEASURE_FINISH_PD(tx_input_check_clsag_gg); @@ -5711,7 +5711,7 @@ bool blockchain_storage::collect_rangeproofs_data_from_tx(std::vector(a); agregated_proofs.emplace_back(zcrp); - for (uint8_t i = 0; i != zcrp.outputs_count; i++) - { - CHECK_AND_ASSERT_MES(tx.vout[i + current_output_start].type() == typeid(tx_out_zarcanum), false, "Unexpected type of out in collect_rangeproofs_data_from_tx()"); - const tx_out_zarcanum& zc_out = boost::get(tx.vout[i + current_output_start]); - agregated_proofs.back().amount_commitments.emplace_back(zc_out.amount_commitment); - } - current_output_start += zcrp.outputs_count; + + // convert amount commitments for aggregation from public_key to point_t form + // TODO: consider refactoring this ugly code + for (uint8_t i = 0; i != zcrp.aggregation_proof.amount_commitments_for_rp_aggregation.size(); i++) + agregated_proofs.back().amount_commitments.emplace_back(zcrp.aggregation_proof.amount_commitments_for_rp_aggregation[i]); + + current_output_start += zcrp.aggregation_proof.amount_commitments_for_rp_aggregation.size(); proofs_count++; } } diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index 8e71ee5f..66fc0719 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -221,6 +221,7 @@ namespace currency }; + // 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& amount_commitments) diff --git a/src/currency_core/currency_format_utils_transactions.h b/src/currency_core/currency_format_utils_transactions.h index ed1a4c4f..2e041d3b 100644 --- a/src/currency_core/currency_format_utils_transactions.h +++ b/src/currency_core/currency_format_utils_transactions.h @@ -102,7 +102,7 @@ namespace currency 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; + crypto::public_key asset_id = currency::native_coin_asset_id; // not blinded, not premultiplied tx_destination_entry() = default; diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index b93bafbb..eea0bad4 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -226,8 +226,8 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("tor_enable", boost::bind(&simple_wallet::tor_enable, this, ph::_1), "Enable relaying transactions over TOR network(enabled by default)"); m_cmd_binder.set_handler("tor_disable", boost::bind(&simple_wallet::tor_disable, this, ph::_1), "Enable relaying transactions over TOR network(enabled by default)"); m_cmd_binder.set_handler("deploy_new_asset", boost::bind(&simple_wallet::deploy_new_asset, this, ph::_1), "Deploys new asset in the network, with current wallet as a maintainer"); - m_cmd_binder.set_handler("add_custom_asset_id", boost::bind(&simple_wallet::add_custom_asset_id, this, _1), "Approve asset id to be recognized in the wallet and returned in balances"); - m_cmd_binder.set_handler("remove_custom_asset_id", boost::bind(&simple_wallet::remove_custom_asset_id, this, _1), "Cancel previously made approval for asset id"); + m_cmd_binder.set_handler("add_custom_asset_id", boost::bind(&simple_wallet::add_custom_asset_id, this, ph::_1), "Approve asset id to be recognized in the wallet and returned in balances"); + m_cmd_binder.set_handler("remove_custom_asset_id", boost::bind(&simple_wallet::remove_custom_asset_id, this, ph::_1), "Cancel previously made approval for asset id"); } //---------------------------------------------------------------------------------------------------- @@ -1238,7 +1238,7 @@ bool simple_wallet::validate_wrap_status(uint64_t amount) } } //---------------------------------------------------------------------------------------------------- -bool preprocess_asset_id(std::string& address_arg, crypto::hash& asset_id) +bool preprocess_asset_id(std::string& address_arg, crypto::public_key& asset_id) { auto p = address_arg.find(':'); if (p == std::string::npos) @@ -1801,18 +1801,18 @@ bool simple_wallet::deploy_new_asset(const std::vector &args) tx_destination_entry td = AUTO_VAL_INIT(td); td.addr.push_back(m_wallet->get_account().get_public_address()); td.amount = adb.current_supply; - td.asset_id = currency::ffff_hash; + td.asset_id = currency::ffff_pkey; std::vector destinations; destinations.push_back(td); currency::transaction result_tx = AUTO_VAL_INIT(result_tx); - crypto::hash result_asset_id = currency::null_hash; + crypto::public_key result_asset_id = currency::null_pkey; m_wallet->publish_new_asset(adb, destinations, result_tx, result_asset_id); success_msg_writer(true) << "New asset deployed: " << ENDL - << "Asset ID: "<< result_asset_id << ENDL - << "Title: " << adb.full_name << ENDL - << "Ticker: " << adb.ticker << ENDL - << "Emitted: " << print_fixed_decimal_point(adb.current_supply, adb.decimal_point) << ENDL + << "Asset ID: " << result_asset_id << ENDL + << "Title: " << adb.full_name << ENDL + << "Ticker: " << adb.ticker << ENDL + << "Emitted: " << print_fixed_decimal_point(adb.current_supply, adb.decimal_point) << ENDL << "Max emission: " << print_fixed_decimal_point(adb.total_max_supply, adb.decimal_point) << ENDL ; @@ -1825,7 +1825,7 @@ bool simple_wallet::add_custom_asset_id(const std::vector &args) { fail_msg_writer() << "invalid arguments count: " << args.size() << ", expected 1"; } - crypto::hash asset_id = currency::null_hash; + crypto::public_key asset_id = currency::null_pkey; if (!epee::string_tools::parse_tpod_from_hex_string(args[0], asset_id)) { fail_msg_writer() << "expected valid asset_id"; @@ -1840,11 +1840,11 @@ bool simple_wallet::add_custom_asset_id(const std::vector &args) } else { - success_msg_writer() << "Added custom asset:" << ENDL - << " Id: " << asset_id << ENDL - << " Title: " << asset_descriptor.full_name << ENDL - << " Ticker: " << asset_descriptor.ticker << ENDL - << " Ticker: " << print_fixed_decimal_point(asset_descriptor.current_supply, asset_descriptor.decimal_point) << ENDL + success_msg_writer() << "The following custom asset was successfully added to the wallet:" << ENDL + << " id: " << asset_id << ENDL + << " title: " << asset_descriptor.full_name << ENDL + << " ticker: " << asset_descriptor.ticker << ENDL + << " supply: " << print_fixed_decimal_point(asset_descriptor.current_supply, asset_descriptor.decimal_point) << ENDL ; } return true; @@ -1856,7 +1856,7 @@ bool simple_wallet::remove_custom_asset_id(const std::vector &args) { fail_msg_writer() << "invalid arguments count: " << args.size() << ", expected 1"; } - crypto::hash asset_id = currency::null_hash; + crypto::public_key asset_id = currency::null_pkey; if (!epee::string_tools::parse_tpod_from_hex_string(args[0], asset_id)) { fail_msg_writer() << "expected valid asset_id"; diff --git a/src/wallet/view_iface.h b/src/wallet/view_iface.h index f4c295ab..9c4a1ef9 100644 --- a/src/wallet/view_iface.h +++ b/src/wallet/view_iface.h @@ -35,7 +35,7 @@ namespace view { std::string address; std::string amount; - crypto::hash asset_id; + crypto::public_key asset_id; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(address) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 5d998c43..6bffdc4a 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1432,9 +1432,23 @@ void wallet2::rise_on_transfer2(const wallet_public::wallet_transfer_info& wti) if (!m_do_rise_transfer) return; std::list balances; - uint64_t mined = 0; - this->balance(balances, mined); - m_wcallback->on_transfer2(wti, balances, mined); + uint64_t mined_balance = 0; + this->balance(balances, mined_balance); + m_wcallback->on_transfer2(wti, balances, mined_balance); + + // TODO @#@# bad design, CZ we need to redesign balance() functions regarding getting mined and unlocked balances for the native coin + uint64_t unlocked_balance = 0, native_balance = 0; + for (auto& el : balances) + { + if (el.asset_info.asset_id == currency::native_coin_asset_id) + { + native_balance = el.total; + unlocked_balance = el.unlocked; + break; + } + } + // second call for legacy callback handlers + m_wcallback->on_transfer2(wti, native_balance, unlocked_balance, mined_balance); } //---------------------------------------------------------------------------------------------------- void wallet2::handle_money_spent2(const currency::block& b, diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index e5ae7290..c73eaad4 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -119,6 +119,7 @@ namespace tools virtual ~i_wallet2_callback() = default; virtual void on_new_block(uint64_t /*height*/, const currency::block& /*block*/) {} + virtual void on_transfer2(const wallet_public::wallet_transfer_info& wti, uint64_t balance, uint64_t unlocked_balance, uint64_t total_mined) {} // this one is left for compatibility, one day we need to get rid of it virtual void on_transfer2(const wallet_public::wallet_transfer_info& wti, const std::list& balances, uint64_t total_mined) {} virtual void on_pos_block_found(const currency::block& /*block*/) {} virtual void on_sync_progress(const uint64_t& /*percents*/) {} diff --git a/src/wallet/wallet_public_structs_defs.h b/src/wallet/wallet_public_structs_defs.h index 06d08f33..05a31f9c 100644 --- a/src/wallet/wallet_public_structs_defs.h +++ b/src/wallet/wallet_public_structs_defs.h @@ -250,6 +250,7 @@ namespace wallet_public BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(balance) KV_SERIALIZE(unlocked_balance) + KV_SERIALIZE(balances) END_KV_SERIALIZE_MAP() }; }; diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index fb804956..a685c3d8 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -186,16 +186,16 @@ namespace tools { try { - // res.balance = m_wallet.balance(); - // res.unlocked_balance = m_wallet.unlocked_balance(); - uint64_t mined = 0; - m_wallet.balance(res.balances, mined); - for (auto it = res.balances.begin(); it != res.balances.end(); it++) + uint64_t stub_mined = 0; // unused + bool r = m_wallet.balance(res.balances, stub_mined); + CHECK_AND_ASSERT_THROW_MES(r, "m_wallet.balance failed"); + for (auto it = res.balances.begin(); it != res.balances.end(); ++it) { - if (it->asset_info.asset_id == currency::null_hash) + if (it->asset_info.asset_id == currency::native_coin_asset_id) { res.balance = it->total; res.unlocked_balance = it->unlocked; + break; } } } diff --git a/tests/functional_tests/crypto_tests.cpp b/tests/functional_tests/crypto_tests.cpp index fe1f0358..74ca3425 100644 --- a/tests/functional_tests/crypto_tests.cpp +++ b/tests/functional_tests/crypto_tests.cpp @@ -514,6 +514,8 @@ TEST(crypto, basics) LOG_PRINT_L0("Zano G = " << c_point_G << " = { " << c_point_G.to_hex_comma_separated_bytes_str() << " }"); LOG_PRINT_L0("Zano H = " << c_point_H << " = { " << c_point_H.to_hex_comma_separated_uint64_str() << " }"); LOG_PRINT_L0("Zano H2 = " << c_point_H2 << " = { " << c_point_H2.to_hex_comma_separated_uint64_str() << " }"); + + return true; } @@ -628,32 +630,32 @@ TEST(crypto, pos) boost::multiprecision::uint512_t Lv = boost::multiprecision::uint512_t(c_L_w) * amount; - constexpr uint64_t COIN = 1000000000000; + constexpr uint64_t c_coin = 1000000000000; const uint64_t amounts[] = { - COIN / 100, - COIN / 50, - COIN / 20, - COIN / 10, - COIN / 5, - COIN / 2, - COIN * 1, - COIN * 2, - COIN * 5, - COIN * 10, - COIN * 20, - COIN * 50, - COIN * 100, - COIN * 200, - COIN * 500, - COIN * 1000, - COIN * 2000, - COIN * 5000, - COIN * 10000, - COIN * 20000, - COIN * 50000, - COIN * 100000, - COIN * 200000, - COIN * 500000 + c_coin / 100, + c_coin / 50, + c_coin / 20, + c_coin / 10, + c_coin / 5, + c_coin / 2, + c_coin * 1, + c_coin * 2, + c_coin * 5, + c_coin * 10, + c_coin * 20, + c_coin * 50, + c_coin * 100, + c_coin * 200, + c_coin * 500, + c_coin * 1000, + c_coin * 2000, + c_coin * 5000, + c_coin * 10000, + c_coin * 20000, + c_coin * 50000, + c_coin * 100000, + c_coin * 200000, + c_coin * 500000 }; uint64_t kernel = 0; From a813484a4f0524b082a0dabf136f40b739405ff2 Mon Sep 17 00:00:00 2001 From: sowle Date: Mon, 13 Feb 2023 21:42:31 +0100 Subject: [PATCH 044/112] confidential assets: global refactoring WIP (now everything is in compilable state, including tests) --- src/crypto/clsag.cpp | 2 +- src/currency_core/currency_format_utils.cpp | 13 +++--- src/currency_core/currency_format_utils.h | 2 +- src/wallet/wallets_manager.cpp | 4 +- src/wallet/wallets_manager.h | 4 +- tests/core_tests/chaingen.cpp | 44 ++++++++++++--------- tests/core_tests/multiassets_test.cpp | 14 +++---- tests/performance_tests/is_out_to_acc.h | 5 ++- tests/unit_tests/basic_struct_packing.cpp | 5 ++- 9 files changed, 55 insertions(+), 38 deletions(-) diff --git a/src/crypto/clsag.cpp b/src/crypto/clsag.cpp index c4e1198f..352f4457 100644 --- a/src/crypto/clsag.cpp +++ b/src/crypto/clsag.cpp @@ -182,7 +182,7 @@ namespace crypto } bool verify_CLSAG_GGX(const hash& m, const std::vector& ring, const public_key& pseudo_out_amount_commitment, - const public_key& pseudo_out_asset_id, const key_image& ki, const CLSAG_GGX_signature& sig) + const public_key& pseudo_out_blinded_asset_id, const key_image& ki, const CLSAG_GGX_signature& sig) { return false; } diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index e990ac59..1d65917c 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -2578,7 +2578,7 @@ namespace currency return true; } - 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, + 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) { crypto::scalar_t h; // = crypto::hash_helper_t::hs(reinterpret_cast(derivation), output_index); // h = Hs(8 * r * V, i) @@ -2604,11 +2604,11 @@ namespace currency asset_id_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_ASSET_BLINDING_MASK, h); // f = Hs(domain_sep, d, i) - // crypto::point_t asset_id = blinded_asset_id - asset_id_blinding_mask * crypto::c_point_X; // H = T - s * X - + crypto::point_t asset_id = blinded_asset_id - asset_id_blinding_mask * crypto::c_point_X; // H = T - s * X + decoded_asset_id = asset_id.to_public_key(); return true; - } + } //--------------------------------------------------------------- bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& money_transfered, crypto::key_derivation& derivation) @@ -2724,14 +2724,17 @@ namespace currency VARIANT_SWITCH_END(); } VARIANT_CASE_CONST(tx_out_zarcanum, zo) + { uint64_t amount = 0; + crypto::public_key asset_id{}; crypto::scalar_t amount_blinding_mask = 0, asset_id_blinding_mask = 0; - if (is_out_to_acc(acc.account_address, zo, derivation, output_index, amount, amount_blinding_mask, asset_id_blinding_mask)) + if (is_out_to_acc(acc.account_address, zo, derivation, output_index, amount, asset_id, amount_blinding_mask, asset_id_blinding_mask)) { crypto::point_t asset_id_pt = crypto::point_t(zo.blinded_asset_id) - asset_id_blinding_mask * crypto::c_point_X; outs.emplace_back(output_index, amount, amount_blinding_mask, asset_id_blinding_mask, asset_id_pt.to_public_key()); money_transfered += amount; } + } VARIANT_SWITCH_END(); output_index++; } diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index 66fc0719..49ff7c3f 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -317,7 +317,7 @@ namespace currency crypto::hash get_multisig_out_id(const transaction& tx, size_t n); 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::scalar_t& amount_blinding_mask, crypto::scalar_t& asset_id_blinding_mask); + 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& 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& outs, uint64_t& money_transfered, crypto::key_derivation& derivation, std::list& htlc_info_list); bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& money_transfered, crypto::key_derivation& derivation); diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index a773dca5..a08aa2e2 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -1698,7 +1698,7 @@ std::string wallets_manager::reset_wallet_password(uint64_t wallet_id, const std else return API_RETURN_CODE_FAIL; } -std::string wallets_manager::add_custom_asset_id(uint64_t wallet_id, const crypto::hash& asset_id, currency::asset_descriptor_base& asset_descriptor) +std::string wallets_manager::add_custom_asset_id(uint64_t wallet_id, const crypto::public_key& asset_id, currency::asset_descriptor_base& asset_descriptor) { GET_WALLET_OPT_BY_ID(wallet_id, w); if(w.w->get()->add_custom_asset_id(asset_id, asset_descriptor)) @@ -1706,7 +1706,7 @@ std::string wallets_manager::add_custom_asset_id(uint64_t wallet_id, const crypt else return API_RETURN_CODE_FAIL; } -std::string wallets_manager::delete_custom_asset_id(uint64_t wallet_id, const crypto::hash& asset_id) +std::string wallets_manager::delete_custom_asset_id(uint64_t wallet_id, const crypto::public_key& asset_id) { GET_WALLET_OPT_BY_ID(wallet_id, w); if (w.w->get()->delete_custom_asset_id(asset_id)) diff --git a/src/wallet/wallets_manager.h b/src/wallet/wallets_manager.h index b5c2922f..b550857b 100644 --- a/src/wallet/wallets_manager.h +++ b/src/wallet/wallets_manager.h @@ -162,8 +162,8 @@ public: std::string get_qt_dev_tools_option() const { return m_qt_dev_tools; } void set_use_deffered_global_outputs(bool use) { m_use_deffered_global_outputs = use; } bool set_use_tor(bool use_tor); - std::string add_custom_asset_id(uint64_t wallet_id, const crypto::hash& asset_id, currency::asset_descriptor_base& asset_descriptor); - std::string delete_custom_asset_id(uint64_t wallet_id, const crypto::hash& asset_id); + std::string add_custom_asset_id(uint64_t wallet_id, const crypto::public_key& asset_id, currency::asset_descriptor_base& asset_descriptor); + std::string delete_custom_asset_id(uint64_t wallet_id, const crypto::public_key& asset_id); private: void main_worker(const po::variables_map& vm); diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 2196792f..4412213f 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -463,7 +463,7 @@ bool test_generator::build_wallets(const blockchain_vector& blockchain, if (amount == 0 && out_v.type() == typeid(tx_out_zarcanum)) { const tx_out_zarcanum& out_zc = boost::get(out_v); - rsp_entry.outs.emplace_back(gindex, out_zc.stealth_address, out_zc.amount_commitment, out_zc.concealing_point); + rsp_entry.outs.emplace_back(gindex, out_zc.stealth_address, out_zc.amount_commitment, out_zc.concealing_point, out_zc.blinded_asset_id); } else if (amount != 0 && out_v.type() == typeid(tx_out_bare)) { @@ -1040,18 +1040,20 @@ bool test_generator::construct_pow_block_with_alias_info_in_coinbase(const accou struct output_index { const currency::tx_out_v out_v; - uint64_t amount; // actual amount (decoded, cannot be zero) - size_t tx_no; // index of transaction in block - size_t out_no; // index of out in transaction - size_t idx; // global index - bool spent; // was it spent? - bool zc_out; // is it a ZC output? - const currency::block *p_blk; - const currency::transaction *p_tx; - crypto::scalar_t blinding_mask; // zc outs only + uint64_t amount = 0; // actual amount (decoded, cannot be zero) + size_t tx_no = 0; // index of transaction in block + size_t out_no = 0; // index of out in transaction + size_t idx = 0; // global index + bool spent = false; // was it spent? + bool zc_out = false; // is it a ZC output? + const currency::block *p_blk = 0; + const currency::transaction *p_tx = 0; + crypto::scalar_t amount_blinding_mask = 0; // zc outs only + crypto::scalar_t asset_id_blinding_mask = 0; // zc outs only + crypto::public_key asset_id = currency::native_coin_asset_id; output_index(const currency::tx_out_v &_out_v, uint64_t _a, size_t tno, size_t ono, const currency::block *_pb, const currency::transaction *_pt) - : out_v(_out_v), amount(_a), tx_no(tno), out_no(ono), idx(0), spent(false), zc_out(false), p_blk(_pb), p_tx(_pt), blinding_mask(0) + : out_v(_out_v), amount(_a), tx_no(tno), out_no(ono), p_blk(_pb), p_tx(_pt) {} output_index(const output_index &other) = default; @@ -1062,10 +1064,11 @@ struct output_index ss << "output_index{" << " tx_no=" << tx_no << " out_no=" << out_no - << " amount=" << amount + << " amount=" << currency::print_money_brief(amount) << " idx=" << idx << " spent=" << spent << " zc_out=" << zc_out + << " asset=" << (asset_id == currency::native_coin_asset_id ? std::string("native") : print16(asset_id)) << "}"; return ss.str(); } @@ -1144,11 +1147,14 @@ bool init_output_indices(map_output_idx_t& outs, map_output_t& outs_mine, const outs_vec.emplace_back(std::move(oi)); uint64_t decoded_amount = 0; - crypto::scalar_t decoded_blinding_mask{}; - if (is_out_to_acc(acc_keys.account_address, out, derivation, j, decoded_amount, decoded_blinding_mask)) + crypto::public_key decoded_asset_id{}; + crypto::scalar_t decoded_amount_blinding_mask{}, decoded_asset_id_blinding_mask{}; + if (is_out_to_acc(acc_keys.account_address, out, derivation, j, decoded_amount, decoded_asset_id, decoded_amount_blinding_mask, decoded_asset_id_blinding_mask)) { - outs_vec.back().amount = decoded_amount; - outs_vec.back().blinding_mask = decoded_blinding_mask; + outs_vec.back().amount = decoded_amount; + outs_vec.back().amount_blinding_mask = decoded_amount_blinding_mask; + outs_vec.back().asset_id = decoded_asset_id; + outs_vec.back().asset_id_blinding_mask = decoded_asset_id_blinding_mask; outs_mine[0].push_back(out_global_idx); } VARIANT_SWITCH_END() @@ -1282,7 +1288,7 @@ bool fill_output_entries(const std::vector& out_indices, size_t re output_entries.emplace_back(out_ref_v, otk.key); VARIANT_SWITCH_END() VARIANT_CASE_CONST(tx_out_zarcanum, ozc) - output_entries.emplace_back(out_ref_v, ozc.stealth_address, ozc.concealing_point, ozc.amount_commitment); + output_entries.emplace_back(out_ref_v, ozc.stealth_address, ozc.concealing_point, ozc.amount_commitment, ozc.blinded_asset_id); VARIANT_SWITCH_END() } } @@ -1392,8 +1398,10 @@ bool fill_tx_sources(std::vector& sources, const std: currency::tx_source_entry ts = AUTO_VAL_INIT(ts); + ts.asset_id = oi.asset_id; ts.amount = oi.amount; - ts.real_out_amount_blinding_mask = oi.blinding_mask; + ts.real_out_asset_id_blinding_mask = oi.asset_id_blinding_mask; + ts.real_out_amount_blinding_mask = oi.amount_blinding_mask; ts.real_output_in_tx_index = oi.out_no; ts.real_out_tx_key = get_tx_pub_key_from_extra(*oi.p_tx); // source tx public key if (!fill_output_entries(outs[o.first], sender_out, nmix, check_for_unlocktime, use_ref_by_id, next_block_height, head_block_ts, ts.real_output, ts.outputs)) diff --git a/tests/core_tests/multiassets_test.cpp b/tests/core_tests/multiassets_test.cpp index 8bc70f08..a1d4e7f9 100644 --- a/tests/core_tests/multiassets_test.cpp +++ b/tests/core_tests/multiassets_test.cpp @@ -73,17 +73,17 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v std::vector destinations(2); destinations[0].addr.push_back(miner_wlt->get_account().get_public_address()); destinations[0].amount = AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC; - destinations[0].asset_id = currency::ffff_hash; + destinations[0].asset_id = currency::ffff_pkey; destinations[1].addr.push_back(alice_wlt->get_account().get_public_address()); destinations[1].amount = AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC; - destinations[1].asset_id = currency::ffff_hash; + destinations[1].asset_id = currency::ffff_pkey; LOG_PRINT_MAGENTA("destinations[0].asset_id:" << destinations[0].asset_id, LOG_LEVEL_0); LOG_PRINT_MAGENTA("destinations[1].asset_id:" << destinations[1].asset_id, LOG_LEVEL_0); - LOG_PRINT_MAGENTA("currency::ffff_hash:" << currency::ffff_hash, LOG_LEVEL_0); + LOG_PRINT_MAGENTA("currency::ffff_pkey: " << currency::ffff_pkey, LOG_LEVEL_0); currency::transaction tx = AUTO_VAL_INIT(tx); - crypto::hash asset_id = currency::null_hash; + crypto::public_key asset_id = currency::null_pkey; miner_wlt->publish_new_asset(adb, destinations, tx, asset_id); LOG_PRINT_L0("Published new asset: " << asset_id << ", tx_id: " << currency::get_transaction_hash(tx)); @@ -95,11 +95,11 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v miner_wlt->refresh(); alice_wlt->refresh(); uint64_t mined = 0; - std::unordered_map balances; + std::unordered_map balances; miner_wlt->balance(balances, mined); auto it_asset = balances.find(asset_id); - auto it_native = balances.find(currency::null_hash); + auto it_native = balances.find(currency::native_coin_asset_id); CHECK_AND_ASSERT_MES(it_asset != balances.end() && it_native != balances.end(), false, "Failed to find needed asset in result balances"); @@ -111,7 +111,7 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v alice_wlt->balance(balances, mined); it_asset = balances.find(asset_id); - it_native = balances.find(currency::null_hash); + it_native = balances.find(currency::native_coin_asset_id); CHECK_AND_ASSERT_MES(it_asset != balances.end(), false, "Failed to find needed asset in result balances"); CHECK_AND_ASSERT_MES(it_native == balances.end(), false, "Failed to find needed asset in result balances"); diff --git a/tests/performance_tests/is_out_to_acc.h b/tests/performance_tests/is_out_to_acc.h index 60e7fd33..5a2a9e11 100644 --- a/tests/performance_tests/is_out_to_acc.h +++ b/tests/performance_tests/is_out_to_acc.h @@ -18,6 +18,9 @@ public: bool test() { const currency::txout_to_key& tx_out = boost::get(boost::get(m_tx.vout[0]).target); - return currency::is_out_to_acc(m_bob.get_keys(), tx_out, m_tx_pub_key, 0); + + crypto::key_derivation derivation; + generate_key_derivation(m_tx_pub_key, m_bob.get_keys().view_secret_key, derivation); + return currency::is_out_to_acc(m_bob.get_public_address(), tx_out, derivation, 0); } }; diff --git a/tests/unit_tests/basic_struct_packing.cpp b/tests/unit_tests/basic_struct_packing.cpp index 7d75ff8d..41b16705 100644 --- a/tests/unit_tests/basic_struct_packing.cpp +++ b/tests/unit_tests/basic_struct_packing.cpp @@ -113,6 +113,9 @@ TEST(tx_signatures_packing, 1) ASSERT_EQ(82178, get_object_blobsize(sigs)); } + // the following tests cases should be redone + // TODO @#@# + { // empty ZC_sig // v(1) + (1 + 32 + 32 + (1 + 10*32) + 32) = 99 @@ -136,7 +139,7 @@ TEST(tx_signatures_packing, 1) // 128 10-ring ZC_sigs // v(128) + 128 * (1 + 32 + 32 + (v(10) + 10*32) + 32) = 53506 (97 + (v(10) + 10*32)) ZC_sig zc = AUTO_VAL_INIT(zc); - zc.clsags_gg.r.resize(10); + //zc.clsags_gg.r.resize(10); sigs.clear(); for(size_t i = 0; i < 128; ++i) sigs.emplace_back(zc); From b733e5561abb763cbe5c3474030d29447fa5ad10 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 21 Feb 2023 01:35:03 +0100 Subject: [PATCH 045/112] ca: validate_tx_semantic() refactored, bare balance check made explicit --- src/currency_core/tx_semantic_validation.cpp | 46 +++++++++----------- src/currency_core/tx_semantic_validation.h | 6 +-- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/src/currency_core/tx_semantic_validation.cpp b/src/currency_core/tx_semantic_validation.cpp index 525aad37..78feebe8 100644 --- a/src/currency_core/tx_semantic_validation.cpp +++ b/src/currency_core/tx_semantic_validation.cpp @@ -21,27 +21,27 @@ namespace currency //----------------------------------------------------------------------------------------------- bool check_tx_inputs_keyimages_diff(const transaction& tx) { - std::unordered_set ki; - for(const auto& in : tx.vin) + std::unordered_set 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,18 +66,6 @@ namespace currency return false; } - if (!check_tx_balance(tx)) - { - LOG_PRINT_RED_L0("balance check failed for tx " << 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)) { @@ -91,6 +79,14 @@ namespace currency return false; } + // inexpensive check for pre-HF4 txs + // post-HF4 txs balance are being checked in check_tx_balance() + if (!check_tx_bare_balance(tx)) + { + LOG_PRINT_RED_L0("balance check failed for tx " << get_transaction_hash(tx)); + return false; + } + return true; } } \ No newline at end of file diff --git a/src/currency_core/tx_semantic_validation.h b/src/currency_core/tx_semantic_validation.h index 2e6f4790..03a946c7 100644 --- a/src/currency_core/tx_semantic_validation.h +++ b/src/currency_core/tx_semantic_validation.h @@ -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); } From 4ae6616a2b5f4b3886d92cb574b10c3109fedd89 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 21 Feb 2023 01:37:42 +0100 Subject: [PATCH 046/112] crypto: linear composition proof stub --- src/common/crypto_serialization.h | 17 ++++++++++++++++- src/crypto/zarcanum.h | 24 ++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/common/crypto_serialization.h b/src/common/crypto_serialization.h index 588deb69..2aef3cae 100644 --- a/src/common/crypto_serialization.h +++ b/src/common/crypto_serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2022 Zano Project +// Copyright (c) 2014-2023 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 @@ -152,6 +152,21 @@ namespace crypto 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() + }; + } // namespace crypto diff --git a/src/crypto/zarcanum.h b/src/crypto/zarcanum.h index bfb20a53..ac517395 100644 --- a/src/crypto/zarcanum.h +++ b/src/crypto/zarcanum.h @@ -56,6 +56,30 @@ namespace crypto const zarcanum_proof& sig, uint8_t* p_err = nullptr); + // 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 { generator_tag_void = 0, generator_tag_G = 1, generator_tag_H = 2, generator_tag_H2 = 3, generator_tag_X = 4, generator_tag_U = 5 }; + + template + 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 + bool verify_linear_composition_proof(const hash& m, const public_key& A, const linear_composition_proof& sig, uint8_t* p_err = nullptr) + { + return false; + } + + // TODO: improve this proof using random weightning factor struct vector_UG_aggregation_proof From f9b54f305a0d3a44470643e45eae2b4291436544 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 21 Feb 2023 01:41:33 +0100 Subject: [PATCH 047/112] ca: wallet refactoring to support confidential assets (WIP) --- src/currency_core/currency_format_utils.h | 2 + .../currency_format_utils_transactions.cpp | 2 +- .../currency_format_utils_transactions.h | 2 +- src/wallet/wallet2.cpp | 87 ++++++++++++------- src/wallet/wallet2.h | 23 +++-- src/wallet/wallet_errors.h | 2 +- 6 files changed, 79 insertions(+), 39 deletions(-) diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index 49ff7c3f..302d348f 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -218,6 +218,8 @@ namespace currency 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; } }; diff --git a/src/currency_core/currency_format_utils_transactions.cpp b/src/currency_core/currency_format_utils_transactions.cpp index c0e06a3b..6ab5de36 100644 --- a/src/currency_core/currency_format_utils_transactions.cpp +++ b/src/currency_core/currency_format_utils_transactions.cpp @@ -51,7 +51,7 @@ namespace currency 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(); } diff --git a/src/currency_core/currency_format_utils_transactions.h b/src/currency_core/currency_format_utils_transactions.h index 2e041d3b..6bed1af2 100644 --- a/src/currency_core/currency_format_utils_transactions.h +++ b/src/currency_core/currency_format_utils_transactions.h @@ -60,7 +60,7 @@ namespace currency 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_zarcanum() const { return !real_out_amount_blinding_mask.is_zero(); } + 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; } BEGIN_SERIALIZE_OBJECT() diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 6bffdc4a..05350e89 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -499,7 +499,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t uint64_t max_out_unlock_time = 0; std::vector outs; - uint64_t tx_money_got_in_outs = 0; // TODO: @#@# correctly calculate tx_money_got_in_outs for post-HF4 + uint64_t sum_of_native_outs = 0; // TODO: @#@# correctly calculate tx_money_got_in_outs for post-HF4 crypto::public_key tx_pub_key = null_pkey; bool r = parse_and_validate_tx_extra(tx, tx_pub_key); THROW_IF_TRUE_WALLET_EX(!r, error::tx_extra_parse_error, tx); @@ -507,10 +507,10 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t //check for transaction income crypto::key_derivation derivation = AUTO_VAL_INIT(derivation); std::list htlc_info_list; - r = lookup_acc_outs(m_account.get_keys(), tx, tx_pub_key, outs, tx_money_got_in_outs, derivation, htlc_info_list); + r = lookup_acc_outs(m_account.get_keys(), tx, tx_pub_key, outs, sum_of_native_outs, derivation, htlc_info_list); THROW_IF_TRUE_WALLET_EX(!r, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys()); - if(!outs.empty() /*&& tx_money_got_in_outs*/) + if (!outs.empty()) { //good news - got money! take care about it //usually we have only one transfer for user in transaction @@ -545,16 +545,17 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t { const wallet_out_info& out = outs[i_in_outs]; size_t o = out.index; - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(o < tx.vout.size(), "wrong out in transaction: internal index=" << o << ", total_outs=" << tx.vout.size()); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(o < tx.vout.size(), "wrong out in transaction: internal index: " << o << ", tx.vout.size(): " << tx.vout.size()); { const currency::tx_out_v& out_v = tx.vout[o]; + bool out_type_zc = out_is_zc(out_v); + bool out_type_to_key = out_is_to_key(out_v); + bool out_type_htlc = out_is_to_htlc(out_v); + bool out_type_multisig = out_is_multisig(out_v); - bool out_type_zc = out_is_zc(out_v); - bool out_type_to_key = out_is_to_key(out_v); - if (out_type_zc || out_type_to_key || out_is_to_htlc(out_v)) + if (out_type_zc || out_type_to_key || out_type_htlc) { - crypto::public_key out_key = out_get_pub_key(out_v, htlc_info_list); - //const currency::txout_to_key& otk = boost::get(out.target); + crypto::public_key out_key = out_get_pub_key(out_v, htlc_info_list); // htlc_info_list contains information about which one, redeem or refund key is ours for an htlc output // obtain key image for this output crypto::key_image ki = currency::null_ki; @@ -600,8 +601,11 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t WLT_LOG_YELLOW(ss.str(), LOG_LEVEL_0); if (m_wcallback) m_wcallback->on_message(i_wallet2_callback::ms_yellow, ss.str()); - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(tx_money_got_in_outs >= outs[i_in_outs].amount, "tx_money_got_in_outs: " << tx_money_got_in_outs << ", out.amount:" << outs[i_in_outs].amount); - tx_money_got_in_outs -= outs[i_in_outs].amount; + if (out.is_native_coin()) + { + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(sum_of_native_outs >= out.amount, "sum_of_native_outs: " << sum_of_native_outs << ", out.amount:" << out.amount); + sum_of_native_outs -= out.amount; + } continue; // skip the output } } @@ -611,11 +615,15 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t { std::stringstream ss; ss << "output #" << o << " from tx " << get_transaction_hash(tx) << " with amount " << print_money_brief(outs[i_in_outs].amount) - << " is targeted to this auditable wallet and has INCORRECT mix_attr = " << (uint64_t)out_get_mixin_attr(out_v) << ". Output IGNORED."; + << " is targeted to this auditable wallet and has INCORRECT mix_attr = " << (uint64_t)out_get_mixin_attr(out_v) << ". Output is IGNORED."; WLT_LOG_RED(ss.str(), LOG_LEVEL_0); if (m_wcallback) m_wcallback->on_message(i_wallet2_callback::ms_red, ss.str()); - tx_money_got_in_outs -= out.amount; + if (out.is_native_coin()) + { + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(sum_of_native_outs >= out.amount, "sum_of_native_outs: " << sum_of_native_outs << ", out.amount:" << out.amount); + sum_of_native_outs -= out.amount; + } continue; // skip the output } @@ -643,7 +651,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t if (ptc.coin_base_tx) { //last out in coinbase tx supposed to be change from coinstake - if (!(o == tx.vout.size() - 1 && !ptc.is_derived_from_coinbase)) + if (!(o == tx.vout.size() - 1 && !ptc.is_derived_from_coinbase)) // TODO: @#@# reconsider this condition { td.m_flags |= WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER; } @@ -655,7 +663,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t } size_t transfer_index = m_transfers.size() - 1; - if (out_is_to_htlc(out_v)) + if (out_type_htlc) { const currency::txout_htlc& hltc = out_get_htlc(out_v); //mark this as spent @@ -702,8 +710,8 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t if (is_watch_only() && is_auditable()) { WLT_CHECK_AND_ASSERT_MES_NO_RET(td.m_global_output_index != WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED, "td.m_global_output_index != WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED validation failed"); - auto amount_gindex_pair = std::make_pair(td.m_amount, td.m_global_output_index); - WLT_CHECK_AND_ASSERT_MES_NO_RET(m_amount_gindex_to_transfer_id.count(amount_gindex_pair) == 0, "update m_amount_gindex_to_transfer_id: amount " << td.m_amount << ", gindex " << td.m_global_output_index << " already exists"); + auto amount_gindex_pair = std::make_pair(td.amount_for_global_output_index(), td.m_global_output_index); + WLT_CHECK_AND_ASSERT_MES_NO_RET(m_amount_gindex_to_transfer_id.count(amount_gindex_pair) == 0, "update m_amount_gindex_to_transfer_id: amount_for_global_output_index: " << td.amount_for_global_output_index() << ", gindex: " << td.m_global_output_index << " already exists"); m_amount_gindex_to_transfer_id[amount_gindex_pair] = transfer_index; } @@ -712,14 +720,22 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t if (out_type_to_key || out_type_zc) { - WLT_LOG_L0("Received money, transfer #" << transfer_index << ", amount: " << print_money_brief(td.amount()) << (out_type_zc ? " (hidden)" : "") << ", with tx: " << get_transaction_hash(tx) << ", at height " << height); + if (td.is_native_coin()) + { + WLT_LOG_L0("Received native coins, transfer #" << transfer_index << ", amount: " << print_money_brief(td.amount()) << (out_type_zc ? " (hidden)" : "") << ", with tx: " << get_transaction_hash(tx) << ", at height " << height); + } + else + { + // TODO @#@# output asset's ticker/name + WLT_LOG_L0("Received asset " << print16(td.get_asset_id()) << ", transfer #" << transfer_index << ", amount: " << print_money_brief(td.amount()) << (out_type_zc ? " (hidden)" : "") << ", with tx: " << get_transaction_hash(tx) << ", at height " << height); + } } - else if (out_is_to_htlc(out_v)) + else if (out_type_htlc) { WLT_LOG_L0("Detected HTLC[" << (td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_HTLC_REDEEM ? "REDEEM" : "REFUND") << "], transfer #" << transfer_index << ", amount: " << print_money(td.amount()) << ", with tx: " << get_transaction_hash(tx) << ", at height " << height); } } - else if (out_is_multisig(out_v)) + else if (out_type_multisig) { crypto::hash multisig_id = currency::get_multisig_out_id(tx, o); WLT_CHECK_AND_ASSERT_MES_NO_RET(m_multisig_transfers.count(multisig_id) == 0, "multisig_id = " << multisig_id << " already in multisig container"); @@ -729,15 +745,22 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t tdb.m_amount = outs[i_in_outs].amount; WLT_LOG_L0("Received multisig, multisig out id: " << multisig_id << ", amount: " << tdb.amount() << ", with tx: " << get_transaction_hash(tx)); } + else + { + WLT_LOG_YELLOW("Unexpected output type: " << out_v.type().name() << ", out index: " << o << " in tx " << get_transaction_hash(tx), LOG_LEVEL_0); + } } } } std::string payment_id; - if (tx_money_got_in_outs && get_payment_id_from_tx(tx.attachment, payment_id)) + if (sum_of_native_outs != 0 && get_payment_id_from_tx(tx.attachment, payment_id)) { - uint64_t received = (ptc.tx_money_spent_in_ins < tx_money_got_in_outs) ? tx_money_got_in_outs - ptc.tx_money_spent_in_ins : 0; + // TODO @#@# this code takes care only of native coins + // we need to add assets support + + uint64_t received = (ptc.sum_of_own_native_inputs < sum_of_native_outs) ? sum_of_native_outs - ptc.sum_of_own_native_inputs : 0; if (0 < received && payment_id.size()) { payment_details payment; @@ -750,7 +773,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t } } - if (ptc.tx_money_spent_in_ins) + if (ptc.sum_of_own_native_inputs) { //check if there are asset_registration that belong to this wallet asset_descriptor_operation ado = AUTO_VAL_INIT(ado); @@ -798,25 +821,27 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t } } - if (ptc.tx_money_spent_in_ins) + if (ptc.sum_of_own_native_inputs) {//this actually is transfer transaction, notify about spend - if (ptc.tx_money_spent_in_ins > tx_money_got_in_outs) + if (ptc.sum_of_own_native_inputs > sum_of_native_outs) {//usual transfer - handle_money_spent2(b, tx, ptc.tx_money_spent_in_ins - (tx_money_got_in_outs+get_tx_fee(tx)), ptc.mtd, recipients, remote_aliases); + handle_money_spent2(b, tx, ptc.sum_of_own_native_inputs - (sum_of_native_outs + get_tx_fee(tx)), ptc.mtd, recipients, remote_aliases); } else {//strange transfer, seems that in one transaction have transfers from different wallets. if (!is_coinbase(tx)) { - WLT_LOG_RED("Unusual transaction " << currency::get_transaction_hash(tx) << ", tx_money_spent_in_ins: " << ptc.tx_money_spent_in_ins << ", tx_money_got_in_outs: " << tx_money_got_in_outs, LOG_LEVEL_0); + WLT_LOG_RED("Unusual transaction " << currency::get_transaction_hash(tx) << ", sum_of_native_inputs: " << ptc.sum_of_own_native_inputs << ", sum_of_native_outs: " << sum_of_native_outs, LOG_LEVEL_0); } - handle_money_received2(b, tx, (tx_money_got_in_outs - (ptc.tx_money_spent_in_ins - get_tx_fee(tx))), ptc.mtd); + handle_money_received2(b, tx, (sum_of_native_outs - (ptc.sum_of_own_native_inputs - get_tx_fee(tx))), ptc.mtd); } } else { - if(tx_money_got_in_outs) - handle_money_received2(b, tx, tx_money_got_in_outs, ptc.mtd); + if (sum_of_native_outs != 0) + { + handle_money_received2(b, tx, sum_of_native_outs, ptc.mtd); + } else if (currency::is_derivation_used_to_encrypt(tx, derivation)) { //transaction doesn't transfer actually money, bud bring some information @@ -5777,7 +5802,7 @@ void wallet2::print_source_entry(std::stringstream& output, const currency::tx_s for(auto& el : src.outputs) ss << el.out_reference << " "; - output << "amount: " << print_money_brief(src.amount) << (src.is_zarcanum() ? " (hidden)" : "") + output << "amount: " << print_money_brief(src.amount) << (src.is_zc() ? " (hidden)" : "") << ", real_output: " << src.real_output << ", real_output_in_tx_index: " << src.real_output_in_tx_index << ", indexes: " << ss.str(); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index c73eaad4..d54a0ca2 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -364,7 +364,8 @@ namespace tools boost::shared_ptr m_zc_info_ptr; uint64_t amount() const { return m_amount; } - + uint64_t amount_for_global_output_index() const { return is_zc() ? 0 : m_amount; } // amount value for global outputs index, it's zero for outputs with hidden amounts + // @#@ will throw if type is not tx_out_bare, TODO: change according to new model, // need to replace all get_tx_out_bare_from_out_v() to proper code //const currency::tx_out_bare& output() const { return currency::get_tx_out_bare_from_out_v(m_ptx_wallet_info->m_tx.vout[m_internal_output_index]); } @@ -377,6 +378,7 @@ namespace tools bool is_reserved_for_escrow() const { return ( (m_flags & WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION) != 0 ); } bool is_zc() const { return m_zc_info_ptr.get(); } const crypto::public_key& get_asset_id() const { if (m_zc_info_ptr.get()) { return m_zc_info_ptr->asset_id; } else { return currency::native_coin_asset_id; } } + bool is_native_coin() const { return m_zc_info_ptr.get() ? (m_zc_info_ptr->asset_id == currency::native_coin_asset_id) : true; } BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE_CUSTOM(m_ptx_wallet_info, const transaction_wallet_info&, tools::wallet2::transform_ptr_to_value, tools::wallet2::transform_value_to_ptr) @@ -504,7 +506,7 @@ namespace tools struct process_transaction_context { - uint64_t tx_money_spent_in_ins = 0; + uint64_t sum_of_own_native_inputs = 0; // old-fashioned bare inputs or ZC inputs referring to native coin asset_id // check all outputs for spending (compare key images) money_transfer2_details mtd; bool is_pos_coinbase = false; @@ -1330,7 +1332,8 @@ namespace tools if (tr_index != UINT64_MAX) { transfer_details& td = m_transfers[tr_index]; - ptc.tx_money_spent_in_ins += td.amount(); + if (td.is_native_coin()) + ptc.sum_of_own_native_inputs += td.m_amount; uint32_t flags_before = td.m_flags; td.m_flags |= WALLET_TRANSFER_DETAIL_FLAG_SPENT; td.m_spent_height = ptc.height; @@ -1338,8 +1341,18 @@ namespace tools ptc.is_derived_from_coinbase = true; else ptc.is_derived_from_coinbase = false; - WLT_LOG_L0("Spent key out, transfer #" << tr_index << ", amount: " << currency::print_money_brief(td.amount()) << ", with tx: " << get_transaction_hash(tx) << ", at height " << ptc.height << - "; flags: " << flags_before << " -> " << td.m_flags); + + if (td.is_native_coin()) + { + WLT_LOG_L0("Spent native coins, transfer #" << tr_index << ", amount: " << currency::print_money_brief(td.amount()) << (td.is_zc() ? " (hidden), with tx: " : ", with tx: ") << get_transaction_hash(tx) << ", at height " << ptc.height << + "; flags: " << flags_before << " -> " << td.m_flags); + } + else + { + WLT_LOG_L0("Spent asset " << print16(td.get_asset_id()) << " , transfer #" << tr_index << ", amount: " << currency::print_money_brief(td.amount()) << ", with tx: " << get_transaction_hash(tx) << ", at height " << ptc.height << + "; flags: " << flags_before << " -> " << td.m_flags); + } + ptc.mtd.spent_indices.push_back(ptc.i); remove_transfer_from_expiration_list(tr_index); } diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index 69c961b8..3d118c92 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -444,7 +444,7 @@ namespace tools const currency::tx_source_entry& src = m_sources[i]; ss << "\n " << i << ": "; ss << " amount: " << std::setw(21) << currency::print_money(src.amount); - ss << (src.is_zarcanum() ? " ZC " : " old "); + ss << (src.is_zc() ? " ZC " : " old "); ss << " asset_id: " << src.asset_id; for (size_t j = 0; j < src.outputs.size(); ++j) { From f3eb63d25c1a314e5142ddd831bb5ef7adb97557 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 21 Feb 2023 01:51:55 +0100 Subject: [PATCH 048/112] ca: global refactoring: tx balance validation, asset operation validation, transaction creation. Also, main tx structure improved with @cryptozoidberg to reflect needs in versatile prunable proofs storage! --- src/currency_core/blockchain_storage.cpp | 86 ++--- src/currency_core/blockchain_storage.h | 6 +- src/currency_core/crypto_config.h | 3 +- src/currency_core/currency_basic.h | 92 ++--- src/currency_core/currency_format_utils.cpp | 351 +++++++++++--------- src/currency_core/currency_format_utils.h | 10 +- 6 files changed, 292 insertions(+), 256 deletions(-) diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 6dff8edd..21208afe 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -1359,7 +1359,8 @@ bool blockchain_storage::validate_miner_transaction(const block& b, return false; } - if (!check_tx_balance(b.miner_tx, base_reward + fee)) + crypto::hash tx_id_for_balance_check = b.miner_tx.version > TRANSACTION_VERSION_PRE_HF4 ? get_transaction_hash(b.miner_tx) : null_hash; + if (!check_tx_balance(b.miner_tx, tx_id_for_balance_check, base_reward + fee)) { LOG_ERROR("coinbase transaction balance check failed. Block reward is " << print_money_brief(base_reward + fee) << "(" << print_money(base_reward) << "+" << print_money(fee) << ", blocks_size_median = " << blocks_size_median @@ -3551,8 +3552,7 @@ bool blockchain_storage::unprocess_blockchain_tx_extra(const transaction& tx) } else { - CHECK_AND_ASSERT_MES(ei.m_asset_operation.asset_id.size() == 1, false, "Unexpected asset_id in operation"); - asset_id = ei.m_asset_operation.asset_id.back(); + CHECK_AND_NO_ASSERT_MES(false, false, "asset operation not implemented"); } r = pop_asset_info(asset_id); CHECK_AND_ASSERT_MES(r, false, "failed to pop_alias_info"); @@ -3802,15 +3802,16 @@ bool blockchain_storage::pop_asset_info(const crypto::public_key& asset_id) return true; } //------------------------------------------------------------------ -bool blockchain_storage::put_asset_info(const transaction & tx, asset_descriptor_operation & ado) +bool blockchain_storage::put_asset_info(const transaction& tx, const crypto::hash& tx_id, const asset_descriptor_operation& ado) { CRITICAL_REGION_LOCAL(m_read_lock); if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER) { crypto::public_key asset_id{}; - calculate_asset_id(ado.descriptor.owner, nullptr, &asset_id); + CHECK_AND_ASSERT_MES(validate_asset_operation(tx, tx_id, ado, asset_id), false, "asset operation validation failed!"); + auto asset_history_ptr = m_db_assets.find(asset_id); - CHECK_AND_ASSERT_MES(!asset_history_ptr, false, "Asset id already existing"); + CHECK_AND_ASSERT_MES(!asset_history_ptr, false, "asset with id " << asset_id << " has already been registered"); assets_container::t_value_type local_asset_history = AUTO_VAL_INIT(local_asset_history); local_asset_history.push_back(ado); m_db_assets.set(asset_id, local_asset_history); @@ -3821,7 +3822,7 @@ bool blockchain_storage::put_asset_info(const transaction & tx, asset_descriptor else { //TODO: implement other operations - CHECK_AND_ASSERT_THROW(false, "not implemented yet"); + CHECK_AND_ASSERT_THROW(false, "asset operation not implemented yet"); } return true; @@ -3902,7 +3903,7 @@ bool blockchain_storage::prevalidate_alias_info(const transaction& tx, const ext return true; } //------------------------------------------------------------------ -bool blockchain_storage::process_blockchain_tx_extra(const transaction& tx) +bool blockchain_storage::process_blockchain_tx_extra(const transaction& tx, const crypto::hash& tx_id) { //check transaction extra tx_extra_info ei = AUTO_VAL_INIT(ei); @@ -3918,7 +3919,7 @@ bool blockchain_storage::process_blockchain_tx_extra(const transaction& tx) } if (ei.m_asset_operation.operation_type != ASSET_DESCRIPTOR_OPERATION_UNDEFINED) { - r = put_asset_info(tx, ei.m_asset_operation); + r = put_asset_info(tx, tx_id, ei.m_asset_operation); CHECK_AND_ASSERT_MES(r, false, "failed to put_asset_info"); } @@ -4096,7 +4097,7 @@ bool blockchain_storage::add_transaction_from_block(const transaction& tx, const CHECK_AND_ASSERT_MES(validate_tx_for_hardfork_specific_terms(tx, tx_id, bl_height), false, "tx " << tx_id << ": hardfork-specific validation failed"); TIME_MEASURE_START_PD(tx_process_extra); - bool r = process_blockchain_tx_extra(tx); + bool r = process_blockchain_tx_extra(tx, tx_id); CHECK_AND_ASSERT_MES(r, false, "failed to process_blockchain_tx_extra"); TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_process_extra); @@ -5351,6 +5352,7 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti return false; } + // TODO @#@# consider: 1) tx.proofs, 2) new proof data structures if (var_is_after_hardfork_4_zone) { @@ -5714,7 +5716,7 @@ bool blockchain_storage::collect_rangeproofs_data_from_tx(std::vector tx_outs_commitments; if (!m_is_in_checkpoint_zone) { - if (!collect_rangeproofs_data_from_tx(range_proofs_agregated, tx/*, tx_outs_commitments*/)) - { - LOG_PRINT_L0("Block with id: " << id << " has at least one transaction with wrong proofs, tx_id: " << tx_id << ", collect_rangeproofs_data_from_tx failed"); - purge_block_data_from_blockchain(bl, tx_processed_count); - //add_block_as_invalid(bl, id); - bvc.m_verification_failed = true; - return false; - } + auto cleanup = [&](){ purge_block_data_from_blockchain(bl, tx_processed_count); bvc.m_verification_failed = true; }; + + CHECK_AND_ASSERT_MES_CUSTOM(collect_rangeproofs_data_from_tx(range_proofs_agregated, tx/*, tx_outs_commitments*/), false, cleanup(), + "block " << id << ", tx " << tx_id << ": collect_rangeproofs_data_from_tx failed"); + + CHECK_AND_ASSERT_MES_CUSTOM(check_tx_balance(tx, tx_id), false, cleanup(), + "block " << id << ", tx " << tx_id << ": check_tx_balance failed"); } TIME_MEASURE_START_PD(tx_add_one_tx_time); @@ -5970,8 +5972,20 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt return false; } + boost::multiprecision::uint128_t already_generated_coins = m_db_blocks.size() ? m_db_blocks.back()->already_generated_coins:0; + uint64_t base_reward = get_base_block_reward(is_pos_bl, already_generated_coins, height); + if (!m_is_in_checkpoint_zone) { + if (!validate_miner_transaction(bl, cumulative_block_size, fee_summary, base_reward, already_generated_coins)) // TODO @#@# base_reward will be calculated once again, consider refactoring + { + LOG_PRINT_L0("Block with id: " << id + << " have wrong miner transaction"); + purge_block_data_from_blockchain(bl, tx_processed_count); + bvc.m_verification_failed = true; + return false; + } + if (!collect_rangeproofs_data_from_tx(range_proofs_agregated, bl.miner_tx)) { LOG_PRINT_L0("Block with id: " << id @@ -5980,28 +5994,16 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt bvc.m_verification_failed = true; return false; } - } - uint64_t base_reward = 0; - boost::multiprecision::uint128_t already_generated_coins = m_db_blocks.size() ? m_db_blocks.back()->already_generated_coins:0; - if (!validate_miner_transaction(bl, cumulative_block_size, fee_summary, base_reward, already_generated_coins)) - { - LOG_PRINT_L0("Block with id: " << id - << " have wrong miner transaction"); - purge_block_data_from_blockchain(bl, tx_processed_count); - bvc.m_verification_failed = true; - return false; - } - - - //validate range proofs - if (!verify_multiple_zc_outs_range_proofs(range_proofs_agregated)) - { - LOG_PRINT_L0("Block with id: " << id - << " have failed to verify multiple rangeproofs"); - purge_block_data_from_blockchain(bl, tx_processed_count); - bvc.m_verification_failed = true; - return false; + //validate range proofs + if (!verify_multiple_zc_outs_range_proofs(range_proofs_agregated)) + { + LOG_PRINT_L0("Block with id: " << id + << " have failed to verify multiple rangeproofs"); + purge_block_data_from_blockchain(bl, tx_processed_count); + bvc.m_verification_failed = true; + return false; + } } diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index fc68d95a..cc89303f 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -492,7 +492,7 @@ namespace currency typedef tools::db::cached_key_value_accessor solo_options_container; typedef tools::db::basic_key_value_accessor per_block_gindex_increments_container; // height => [(amount, gindex_increment), ...] - typedef tools::db::cached_key_value_accessor, true, false> assets_container; + typedef tools::db::cached_key_value_accessor, true, false> assets_container; // TODO @#@# consider storing tx_id as well for reference -- sowle //----------------------------------------- @@ -648,14 +648,14 @@ namespace currency uint64_t get_adjusted_time()const; bool complete_timestamps_vector(uint64_t start_height, std::vector& 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 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, asset_descriptor_operation & ado); + 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(); diff --git a/src/currency_core/crypto_config.h b/src/currency_core/crypto_config.h index f97a9bad..23251fdd 100644 --- a/src/currency_core/crypto_config.h +++ b/src/currency_core/crypto_config.h @@ -1,4 +1,4 @@ -// Copyright (c) 2022 Zano Project +// 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. // @@ -26,4 +26,5 @@ #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______________" diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h index e15b7506..392ed389 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -765,7 +765,8 @@ namespace currency std::string ticker; std::string full_name; std::string meta_info; - crypto::public_key owner = currency::null_pkey; + crypto::public_key owner = currency::null_pkey; // consider premultipling by 1/8 + bool hidden_supply = false; BEGIN_VERSIONED_SERIALIZE() FIELD(total_max_supply) @@ -775,6 +776,7 @@ namespace currency FIELD(full_name) FIELD(meta_info) FIELD(owner) + FIELD(hidden_supply) END_SERIALIZE() @@ -828,23 +830,36 @@ namespace currency struct asset_descriptor_operation { uint8_t operation_type = ASSET_DESCRIPTOR_OPERATION_UNDEFINED; - std::vector proof; asset_descriptor_base descriptor; - std::vector asset_id; //questionable regarding form of optional fields // premultiplied by 1/8 - + boost::optional opt_amount_commitment; // premultiplied by 1/8 BEGIN_VERSIONED_SERIALIZE() FIELD(operation_type) - FIELD(proof) FIELD(descriptor) - FIELD(asset_id) + //FIELD(opt_amount_commitment) END_SERIALIZE() - BEGIN_BOOST_SERIALIZATION() BOOST_SERIALIZE(operation_type) - BOOST_SERIALIZE(proof) BOOST_SERIALIZE(descriptor) + //BOOST_SERIALIZE(opt_amount_commitment) + END_BOOST_SERIALIZATION() + }; + + struct asset_operation_proof + { + // linear composition proof for the fact amount_commitment = lin(asset_id, G) + boost::optional opt_amount_commitment_composition_proof; // for hidden supply + boost::optional opt_amount_commitment_g_proof; // for non-hidden supply, proofs that amount_commitment - supply * asset_id = lin(G) + + BEGIN_VERSIONED_SERIALIZE() + //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) END_BOOST_SERIALIZATION() }; @@ -915,10 +930,10 @@ namespace currency END_SERIALIZE() }; - typedef boost::mpl::vector26< + 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, zarcanum_tx_data_v1, zc_asset_surjection_proof, zc_outs_range_proof, zc_balance_proof, asset_descriptor_operation + tx_payer, tx_receiver, extra_alias_entry, zarcanum_tx_data_v1, asset_descriptor_operation > all_payload_types; typedef boost::make_variant_over::type payload_items_v; @@ -969,7 +984,7 @@ namespace currency typedef boost::variant signature_v; - + typedef boost::variant proof_v; //include backward compatibility defintions @@ -978,11 +993,9 @@ namespace currency class transaction_prefix { public: - // tx version information - uint64_t version{}; - //extra - std::vector extra; + uint64_t version = 0; std::vector vin; + std::vector extra; std::vector vout; BEGIN_SERIALIZE() @@ -991,12 +1004,9 @@ namespace currency 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(){} }; /* @@ -1012,55 +1022,23 @@ namespace currency class transaction: public transaction_prefix { public: - std::vector signatures; std::vector attachment; - - transaction(); + std::vector signatures; + std::vector proofs; BEGIN_SERIALIZE_OBJECT() FIELDS(*static_cast(this)) CHAIN_TRANSITION_VER(TRANSACTION_VERSION_INITAL, transaction_v1) CHAIN_TRANSITION_VER(TRANSACTION_VERSION_PRE_HF4, transaction_v1) - FIELD(signatures) 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(); - } - */ - - - /************************************************************************/ /* */ @@ -1122,8 +1100,6 @@ namespace currency */ //------------------------------------------------------------------------------------------------------------------- - - #pragma pack(push, 1) struct stake_modifier_type { @@ -1133,7 +1109,6 @@ namespace currency struct stake_kernel { - stake_modifier_type stake_modifier; uint64_t block_timestamp; //this block timestamp crypto::key_image kimage; @@ -1246,6 +1221,7 @@ 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"); diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 1d65917c..12cfd793 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -103,15 +103,21 @@ namespace currency crypto::scalar_t local_asset_id_blinding_masks_sum = 0; crypto::scalar_t amount_blinding_masks_sum = 0; crypto::scalar_t local_amount_blinding_masks_sum = 0; + + // 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{}; }; //-------------------------------------------------------------------------------- - bool generate_asset_surjection_proof(zc_asset_surjection_proof& result) + bool generate_asset_surjection_proof(const crypto::hash& context_hash, zc_asset_surjection_proof& result) { // TODO: membership proof here return false; } //-------------------------------------------------------------------------------- - bool generate_zc_outs_range_proof(size_t out_index_start, size_t outs_count, const outputs_generation_context& outs_gen_context, + bool generate_zc_outs_range_proof(const crypto::hash& context_hash, size_t out_index_start, size_t outs_count, const outputs_generation_context& outs_gen_context, const std::vector& vouts, zc_outs_range_proof& result) { CHECK_AND_ASSERT_MES(outs_gen_context.check_sizes(outs_count), false, ""); @@ -130,9 +136,8 @@ namespace currency } // aggregation proof - // TODO: @#@# use appropriate hash for context binding uint8_t err = 0; - bool r = crypto::generate_vector_UG_aggregation_proof(null_hash, outs_gen_context.amounts, g_secrets, + bool r = crypto::generate_vector_UG_aggregation_proof(context_hash, outs_gen_context.amounts, g_secrets, outs_gen_context.amount_commitments, amount_commitments_for_rp_aggregation, outs_gen_context.blinded_asset_ids, result.aggregation_proof, &err); @@ -162,7 +167,7 @@ namespace currency } //------------------------------------------------------------------ // for txs with no zc inputs (and thus no zc signatures) but with zc outputs - bool generate_tx_balance_proof(transaction &tx, const outputs_generation_context& outs_gen_context, uint64_t block_reward_for_miner_tx = 0) + bool generate_tx_balance_proof(transaction &tx, const crypto::hash& tx_id, const outputs_generation_context& outs_gen_context, uint64_t block_reward_for_miner_tx = 0) { CHECK_AND_ASSERT_MES(tx.version > TRANSACTION_VERSION_PRE_HF4, false, "unsupported tx.version: " << tx.version); CHECK_AND_ASSERT_MES(count_type_in_variant_container(tx.signatures) == 0, false, "ZC_sig is unexpected"); @@ -200,15 +205,14 @@ namespace currency // (fee - sum(bare inputs' amounts)) * H - sum(pseudo outs commitments for ZC inputs) + sum(outputs' commitments) = residual * G // tx doesn't have any zc inputs --> add Schnorr proof for commitment to zero - CHECK_AND_ASSERT_MES(count_type_in_variant_container(tx.attachment) == 0, false, ""); + CHECK_AND_ASSERT_MES(count_type_in_variant_container(tx.proofs) == 0, false, ""); zc_balance_proof balance_proof = AUTO_VAL_INIT(balance_proof); crypto::point_t commitment_to_zero = outs_commitments_sum + (crypto::scalar_t(fee) - crypto::scalar_t(bare_inputs_sum)) * crypto::c_point_H; //crypto::scalar_t witness = outputs_blinding_masks_sum; - // TODO: consider adding more data to message - crypto::generate_signature(null_hash, commitment_to_zero.to_public_key(), outs_gen_context.amount_blinding_masks_sum.as_secret_key(), balance_proof.s); - tx.attachment.push_back(balance_proof); + crypto::generate_signature(tx_id, commitment_to_zero.to_public_key(), outs_gen_context.amount_blinding_masks_sum.as_secret_key(), balance_proof.s); + tx.proofs.emplace_back(std::move(balance_proof)); return true; } @@ -364,21 +368,6 @@ namespace currency ++output_index; } - if (tx.version > TRANSACTION_VERSION_PRE_HF4) - { - //add range proofs - currency::zc_outs_range_proof range_proofs = AUTO_VAL_INIT(range_proofs); - bool r = generate_zc_outs_range_proof(0, destinations.size(), outs_gen_context, tx.vout, range_proofs); - CHECK_AND_ASSERT_MES(r, false, "Failed to generate zc_outs_range_proof()"); - tx.attachment.push_back(range_proofs); - - if (!pos) - { - r = generate_tx_balance_proof(tx, outs_gen_context, block_reward); - CHECK_AND_ASSERT_MES(r, false, "generate_tx_balance_proof failed"); - } - } - if (tx.attachment.size()) add_attachments_info_to_extra(tx.extra, tx.attachment); @@ -388,13 +377,87 @@ namespace currency set_tx_unlock_time(tx, height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW); } + // + // The tx prefix should be sealed by now, and the tx hash should be defined. + // Any changes made below should only affect the signatures/proofs and should not impact the prefix hash calculation. + // + + if (tx.version > TRANSACTION_VERSION_PRE_HF4) + { + crypto::hash tx_id = get_transaction_hash(tx); + + //add range proofs + currency::zc_outs_range_proof range_proofs = AUTO_VAL_INIT(range_proofs); + bool r = generate_zc_outs_range_proof(tx_id, 0, destinations.size(), outs_gen_context, tx.vout, range_proofs); + CHECK_AND_ASSERT_MES(r, false, "Failed to generate zc_outs_range_proof()"); + tx.proofs.emplace_back(std::move(range_proofs)); + + if (!pos) + { + r = generate_tx_balance_proof(tx, tx_id, outs_gen_context, block_reward); + CHECK_AND_ASSERT_MES(r, false, "generate_tx_balance_proof failed"); + } + } + if (blinding_masks_sum_ptr) *blinding_masks_sum_ptr = outs_gen_context.amount_blinding_masks_sum; // TODO @#@# return true; } //------------------------------------------------------------------ - bool check_tx_balance(const transaction& tx, uint64_t additional_inputs_amount_and_fees_for_mining_tx /* = 0 */) + bool check_tx_bare_balance(const transaction& tx, uint64_t additional_inputs_amount_and_fees_for_mining_tx /* = 0 */) + { + // legacy checks for old fashioned tx with non-hidden amounts + CHECK_AND_ASSERT_MES(tx.version <= TRANSACTION_VERSION_PRE_HF4, false, "check_tx_bare_balance can't check post-HF4 txs"); + uint64_t bare_outputs_sum = get_outs_money_amount(tx); + uint64_t bare_inputs_sum = get_inputs_money_amount(tx); + + if (additional_inputs_amount_and_fees_for_mining_tx == 0) + { + // normal tx + CHECK_AND_ASSERT_MES(bare_inputs_sum >= bare_outputs_sum, false, "tx balance error: sum of inputs (" << print_money_brief(bare_inputs_sum) + << ") is less than or equal to sum of outputs(" << print_money_brief(bare_outputs_sum) << ")"); + } + else + { + // miner tx + CHECK_AND_ASSERT_MES(bare_inputs_sum + additional_inputs_amount_and_fees_for_mining_tx == bare_outputs_sum, false, + "tx balance error: sum of inputs (" << print_money_brief(bare_inputs_sum) << + ") + additional inputs and fees (" << print_money_brief(additional_inputs_amount_and_fees_for_mining_tx) << + ") is less than or equal to sum of outputs(" << print_money_brief(bare_outputs_sum) << ")"); + } + return true; + } + //----------------------------------------------------------------------------------------------- + bool validate_asset_operation(const transaction& tx, const crypto::hash& tx_id, const asset_descriptor_operation& ado, crypto::public_key& asset_id) + { + crypto::point_t asset_id_pt = crypto::c_point_0; + calculate_asset_id(ado.descriptor.owner, &asset_id_pt, &asset_id); + + CHECK_AND_ASSERT_MES(count_type_in_variant_container(tx.proofs) == 1, false, "asset_operation_proof not present or present more than once"); + const asset_operation_proof& aop = get_type_in_variant_container_by_ref(tx.proofs); + + if (ado.descriptor.hidden_supply) + { + CHECK_AND_ASSERT_MES(aop.opt_amount_commitment_composition_proof.has_value(), false, "opt_amount_commitment_composition_proof is absent"); + // TODO @#@# if asset is hidden -- theck composition proof + return false; + } + else + { + // make sure that amount commitment corresponds to opt_amount_commitment_g_proof + CHECK_AND_ASSERT_MES(ado.opt_amount_commitment.has_value(), false, "opt_amount_commitment is absent"); + CHECK_AND_ASSERT_MES(aop.opt_amount_commitment_g_proof.has_value(), false, "opt_amount_commitment_g_proof is absent"); + crypto::point_t A = crypto::point_t(ado.opt_amount_commitment.get()).modify_mul8() - ado.descriptor.current_supply * asset_id_pt; + + bool r = crypto::check_signature(tx_id, A.to_public_key(), aop.opt_amount_commitment_g_proof.get()); + CHECK_AND_ASSERT_MES(r, false, "opt_amount_commitment_g_proof check failed"); + } + + return true; + } + //------------------------------------------------------------------ + bool check_tx_balance(const transaction& tx, const crypto::hash& tx_id, uint64_t additional_inputs_amount_and_fees_for_mining_tx /* = 0 */) { if (tx.version > TRANSACTION_VERSION_PRE_HF4) { @@ -434,8 +497,9 @@ namespace currency asset_descriptor_operation ado = AUTO_VAL_INIT(ado); if (get_type_in_variant_container(tx.extra, ado) && ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER) // @#@ TODO: Support other asset operations { - CHECK_AND_ASSERT_MES(ado.asset_id.size() == 1, false, "invalid size of ado.asset_id: " << ado.asset_id.size()); - sum_of_pseudo_out_amount_commitments += crypto::scalar_t(ado.descriptor.current_supply) * crypto::point_t(ado.asset_id.back()).modify_mul8(); + // opt_amount_commitment supposed to be validated earlier in validate_asset_operation() + CHECK_AND_ASSERT_MES(ado.opt_amount_commitment.has_value(), false, "opt_amount_commitment is not set"); + sum_of_pseudo_out_amount_commitments += crypto::point_t(ado.opt_amount_commitment.get()); // *1/8 } size_t zc_sigs_count = 0; for(auto& sig_v : tx.signatures) @@ -465,34 +529,16 @@ namespace currency // no zc inputs -- there should be an explicit proof structure (Schnorr proof), proving that: // (sum(bare inputs' amounts) - fee) * H + sum(pseudo outs commitments for ZC inputs) - sum(outputs' commitments) = residual_g * G zc_balance_proof balance_proof = AUTO_VAL_INIT(balance_proof); - bool r = get_type_in_variant_container(tx.attachment, balance_proof); + bool r = get_type_in_variant_container(tx.proofs, balance_proof); CHECK_AND_ASSERT_MES(r, false, "no zc inputs are present, but at the same time there's no zc_balance_proof in attachment"); - r = crypto::check_signature(null_hash, commitment_to_zero.to_public_key(), balance_proof.s); + r = crypto::check_signature(tx_id, commitment_to_zero.to_public_key(), balance_proof.s); CHECK_AND_ASSERT_MES(r, false, "zc_balance_proof is invalid"); } + return true; } - else - { - // old fashioned tx with non-hidden amounts - uint64_t bare_outputs_sum = get_outs_money_amount(tx); - uint64_t bare_inputs_sum = get_inputs_money_amount(tx); - - if (additional_inputs_amount_and_fees_for_mining_tx == 0) - { - // normal tx - CHECK_AND_ASSERT_MES(bare_inputs_sum >= bare_outputs_sum, false, "tx balance error: sum of inputs (" << print_money_brief(bare_inputs_sum) - << ") is less than or equal to sum of outputs(" << print_money_brief(bare_outputs_sum) << ")"); - } - else - { - // miner tx - CHECK_AND_ASSERT_MES(bare_inputs_sum + additional_inputs_amount_and_fees_for_mining_tx == bare_outputs_sum, false, - "tx balance error: sum of inputs (" << print_money_brief(bare_inputs_sum) << - ") + additional inputs and fees (" << print_money_brief(additional_inputs_amount_and_fees_for_mining_tx) << - ") is less than or equal to sum of outputs(" << print_money_brief(bare_outputs_sum) << ")"); - } - } - return true; + + // pre-HF4 txs + return check_tx_bare_balance(tx, additional_inputs_amount_and_fees_for_mining_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) @@ -780,7 +826,7 @@ namespace currency template bool operator()(const t_extra_typename& k) const { - //do notheing for rest + //do nothing for rest return true; } }; @@ -1666,7 +1712,7 @@ namespace currency const account_keys& sender_account_keys, const uint64_t tx_flags, outputs_generation_context& outs_gen_context, transaction& tx, bool last_output) { bool watch_only_mode = sender_account_keys.spend_secret_key == null_skey; - CHECK_AND_ASSERT_MES(se.is_zarcanum(), false, "sources contains a non-zarcanum input"); + CHECK_AND_ASSERT_MES(se.is_zc(), false, "sources contains a non-zc input"); CHECK_AND_ASSERT_MES(input_index < tx.vin.size(), false, "input_index (" << input_index << ") is out-of-bounds, vin.size = " << tx.vin.size()); CHECK_AND_ASSERT_MES(tx.vin[input_index].type() == typeid(txin_zc_input), false, "Unexpected type of input #" << input_index); @@ -1825,7 +1871,7 @@ namespace currency bool r = false; transaction& tx = result.tx; - crypto::secret_key& one_time_secret_key = result.one_time_key; + crypto::secret_key& one_time_tx_secret_key = result.one_time_key; result.ftp = ftp; CHECK_AND_ASSERT_MES(destinations.size() <= CURRENCY_TX_MAX_ALLOWED_OUTS, false, "Too many outs (" << destinations.size() << ")! Tx can't be constructed."); @@ -1856,7 +1902,7 @@ namespace currency txkey = keypair::generate(); add_tx_pub_key_to_extra(tx, txkey.pub); - one_time_secret_key = txkey.sec; + one_time_tx_secret_key = txkey.sec; //add flags etc_tx_flags16_t e = AUTO_VAL_INIT(e); @@ -1870,7 +1916,7 @@ namespace currency else { txkey.pub = get_tx_pub_key_from_extra(tx); - txkey.sec = one_time_secret_key; + txkey.sec = one_time_tx_secret_key; CHECK_AND_ASSERT_MES(txkey.pub != null_pkey && txkey.sec != null_skey, false, "In append mode both public and secret keys must be provided"); //separately encrypt attachments without putting extra @@ -1893,28 +1939,7 @@ namespace currency uint64_t native_coins_input_sum = 0; - - crypto::public_key asset_id_for_asset_operation = currency::null_pkey; - asset_descriptor_operation* pado = nullptr; - if (tx.version > TRANSACTION_VERSION_PRE_HF4) - { - pado = get_type_in_variant_container(tx.extra); - if (pado) - { - CHECK_AND_ASSERT_MES(pado->operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER, false, "unsupported asset operation"); - crypto::secret_key stub = AUTO_VAL_INIT(stub); - bool r = derive_key_pair_from_key_pair(sender_account_keys.account_address.spend_public_key, one_time_secret_key, stub, pado->descriptor.owner, CRYPTO_HDS_ASSET_CONTROL_KEY); - CHECK_AND_ASSERT_MES(r, false, "Failed to derive_public_key_from_tx_and_account_pub_key()"); - //also assign this asset id to destinations - calculate_asset_id(pado->descriptor.owner, nullptr, &asset_id_for_asset_operation); - } - } - - std::vector in_contexts; - - //we'll aggregate Zarcanum outs into one txin_zarcanum_inputs - //txin_zarcanum_inputs ins_zc = AUTO_VAL_INIT(ins_zc); std::vector inputs_mapping; size_t current_index = 0; inputs_mapping.resize(sources.size()); @@ -1928,6 +1953,7 @@ namespace currency in_contexts.push_back(input_generation_context_data{}); input_generation_context_data& in_context = in_contexts.back(); + // sort src_entr.outputs entries by global out index, put it to in_context.outputs, convert to relative gindices, and put new real out index into in_context.real_out_index in_context.outputs = prepare_outputs_entries_for_key_offsets(src_entr.outputs, src_entr.real_output, in_context.real_out_index); if(src_entr.is_multisig()) @@ -1999,7 +2025,7 @@ namespace currency //TODO: Might need some refactoring since this scheme is not the clearest one(did it this way for now to keep less changes to not broke anything) //potentially this approach might help to support htlc and multisig without making to complicated code - if (src_entr.is_zarcanum()) + if (src_entr.is_zc()) { has_zc_inputs = true; txin_zc_input zc_in = AUTO_VAL_INIT(zc_in); @@ -2021,36 +2047,58 @@ namespace currency native_coins_input_sum += src_entr.amount; } - uint64_t amount_of_emitted_asset = 0; + + // + // OUTs + // std::vector shuffled_dsts(destinations); - if (asset_id_for_asset_operation != currency::null_pkey) - { - //must be asset publication - for (auto& item : shuffled_dsts) - { - if (item.asset_id == currency::ffff_pkey) - { - item.asset_id = asset_id_for_asset_operation; - amount_of_emitted_asset += item.amount; - } - } - CHECK_AND_ASSERT_MES(pado, false, "pado is null ??"); - pado->descriptor.current_supply = amount_of_emitted_asset; // TODO: consider setting current_supply beforehand, not setting it hear in ad-hoc manner -- sowle - } + size_t outputs_to_be_constructed = shuffled_dsts.size(); + outputs_generation_context outs_gen_context(outputs_to_be_constructed); // auxiliary data for each output + // ASSET oprations handling + if (tx.version > TRANSACTION_VERSION_PRE_HF4) + { + asset_descriptor_operation* pado = nullptr; + pado = get_type_in_variant_container(tx.extra); + if (pado) + { + // only operation register is supported atm + CHECK_AND_ASSERT_MES(pado->operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER, false, "unsupported asset operation: " << (int)pado->operation_type); + crypto::secret_key asset_control_key{}; + bool r = derive_key_pair_from_key_pair(sender_account_keys.account_address.spend_public_key, one_time_tx_secret_key, asset_control_key, pado->descriptor.owner, CRYPTO_HDS_ASSET_CONTROL_KEY); + CHECK_AND_ASSERT_MES(r, false, "derive_key_pair_from_key_pair failed"); + + calculate_asset_id(pado->descriptor.owner, &outs_gen_context.ao_asset_id_pt, &outs_gen_context.ao_asset_id); + + // calculate amount blinding mask + outs_gen_context.ao_amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_ASSET_CONTROL_ABM, asset_control_key); + + // set correct asset_id to the corresponding destination entries + uint64_t amount_of_emitted_asset = 0; + for (auto& item : shuffled_dsts) + { + if (item.asset_id == currency::ffff_pkey) + { + item.asset_id = outs_gen_context.ao_asset_id; // set calculated asset_id to the asset's outputs, if this asset is being emitted within this tx + amount_of_emitted_asset += item.amount; + } + } + pado->descriptor.current_supply = amount_of_emitted_asset; // TODO: consider setting current_supply beforehand, not setting it hear in ad-hoc manner -- sowle + + outs_gen_context.ao_amount_commitment = amount_of_emitted_asset * outs_gen_context.ao_asset_id_pt + outs_gen_context.ao_amount_blinding_mask * crypto::c_point_G; + pado->opt_amount_commitment = (crypto::c_scalar_1div8 * outs_gen_context.ao_amount_commitment).to_public_key(); + } + } // "Shuffle" outs if (shuffle) std::sort(shuffled_dsts.begin(), shuffled_dsts.end(), [](const tx_destination_entry& de1, const tx_destination_entry& de2) { return de1.amount < de2.amount; }); - // TODO: consider "Shuffle" inputs // construct outputs uint64_t native_coins_output_sum = 0; size_t output_index = tx.vout.size(); // in case of append mode we need to start output indexing from the last one + 1 - size_t outputs_to_be_constructed = shuffled_dsts.size(); - outputs_generation_context outs_gen_context(outputs_to_be_constructed); // auxiliary data for each output uint64_t range_proof_start_index = output_index; std::set deriv_cache; for(size_t j = 0; j < outputs_to_be_constructed; ++j, ++output_index) @@ -2068,16 +2116,6 @@ namespace currency native_coins_output_sum += dst_entr.amount; } - //check money - //if (!(flags&TX_FLAG_SIGNATURE_MODE_SEPARATE)) - //{ - // if (summary_outs_money > summary_inputs_money) - // { - // LOG_ERROR("Transaction inputs money (" << print_money_brief(summary_inputs_money) << ") is less than outputs money (" << print_money_brief(summary_outs_money) << ")"); - // return false; - // } - //} - //process offers and put there offers derived keys uint64_t att_count = 0; for (auto& o : tx.attachment) @@ -2089,7 +2127,7 @@ namespace currency { CHECK_AND_ASSERT_MES(tsa.security.size() == 1, false, "Wrong tsa.security.size() = " << tsa.security.size()); - r = derive_public_key_from_target_address(sender_account_keys.account_address, one_time_secret_key, att_count, tsa.security.back()); + r = derive_public_key_from_target_address(sender_account_keys.account_address, one_time_tx_secret_key, att_count, tsa.security.back()); CHECK_AND_ASSERT_MES(r, false, "Failed to derive_public_key_from_target_address"); } att_count++; @@ -2106,33 +2144,14 @@ namespace currency //2 sort the inputs in given range std::sort(tx.vin.begin() + input_starter_index, tx.vin.end(), less_txin_v); - } - - if (tx.version > TRANSACTION_VERSION_PRE_HF4) - { - // asset surjeciton proof - currency::zc_asset_surjection_proof asp{}; - bool r = generate_asset_surjection_proof(asp); - CHECK_AND_ASSERT_MES(r, false, "generete_asset_surjection_proof failed"); - tx.attachment.push_back(asp); - - // add range proofs - currency::zc_outs_range_proof range_proofs = AUTO_VAL_INIT(range_proofs); - r = generate_zc_outs_range_proof(range_proof_start_index, outputs_to_be_constructed, outs_gen_context, tx.vout, range_proofs); - CHECK_AND_ASSERT_MES(r, false, "Failed to generate zc_outs_range_proof()"); - tx.attachment.push_back(range_proofs); // add explicit fee info r = add_tx_fee_amount_to_extra(tx, native_coins_input_sum - native_coins_output_sum); CHECK_AND_ASSERT_MES(r, false, "add_tx_fee_amount_to_extra failed"); - - if (!has_zc_inputs) - { - r = generate_tx_balance_proof(tx, outs_gen_context); - CHECK_AND_ASSERT_MES(r, false, "generate_tx_balance_proof failed"); - } } + // attachments container should be sealed by now + if (flags & TX_FLAG_SIGNATURE_MODE_SEPARATE) { // for separately signed tx each input has to contain information about corresponding outputs, extra entries and attachments @@ -2154,13 +2173,37 @@ namespace currency if (tx.attachment.size()) add_attachments_info_to_extra(tx.extra, tx.attachment); } + + // - // generate ring signatures + // generate proofs and signatures + // (any changes made below should only affect the signatures/proofs and should not impact the prefix hash calculation) // - crypto::hash tx_prefix_hash; - get_transaction_prefix_hash(tx, tx_prefix_hash); - //size_t input_index = input_starter_index; - //size_t in_context_index = 0; + crypto::hash tx_prefix_hash = get_transaction_prefix_hash(tx); + + // proofs (transaction-wise, not pre-input) + if (tx.version > TRANSACTION_VERSION_PRE_HF4) + { + // asset surjeciton proof + currency::zc_asset_surjection_proof asp{}; + bool r = generate_asset_surjection_proof(tx_prefix_hash, asp); + CHECK_AND_ASSERT_MES(r, false, "generete_asset_surjection_proof failed"); + tx.proofs.emplace_back(std::move(asp)); + + // add range proofs + currency::zc_outs_range_proof range_proofs = AUTO_VAL_INIT(range_proofs); + r = generate_zc_outs_range_proof(tx_prefix_hash, range_proof_start_index, outputs_to_be_constructed, outs_gen_context, tx.vout, range_proofs); + CHECK_AND_ASSERT_MES(r, false, "Failed to generate zc_outs_range_proof()"); + tx.proofs.emplace_back(std::move(range_proofs)); + + if (!has_zc_inputs) + { + r = generate_tx_balance_proof(tx, tx_prefix_hash, outs_gen_context); + CHECK_AND_ASSERT_MES(r, false, "generate_tx_balance_proof failed"); + } + } + + // ring signatures (per-input proofs) r = false; for (size_t i_ = 0; i_ != sources.size(); i_++) { @@ -2171,7 +2214,7 @@ namespace currency CHECK_AND_ASSERT_MES(tx_hash_for_signature != null_hash, false, "prepare_prefix_hash_for_sign failed"); std::stringstream ss_ring_s; - if (source_entry.is_zarcanum()) + if (source_entry.is_zc()) { // ZC // blinding_masks_sum is supposed to be sum(mask of all tx output) - sum(masks of all pseudo out commitments) @@ -2466,12 +2509,16 @@ namespace currency VARIANT_SWITCH_END(); } VARIANT_CASE_CONST(tx_out_zarcanum, o) - if (!check_key(o.amount_commitment)) + { + if (!check_key(o.stealth_address)) return false; if (!check_key(o.concealing_point)) return false; - if (!check_key(o.stealth_address)) + if (!check_key(o.amount_commitment)) return false; + if (!check_key(o.blinded_asset_id)) + return false; + } VARIANT_SWITCH_END(); } return true; @@ -2559,6 +2606,7 @@ namespace currency return res; } //--------------------------------------------------------------- + // out_key.key =?= Hs(derivation || output_index) * G + addr.spend_public_key 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) { crypto::public_key pk; @@ -2611,12 +2659,12 @@ namespace currency } //--------------------------------------------------------------- - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& money_transfered, crypto::key_derivation& derivation) + bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& sum_of_native_outs, crypto::key_derivation& derivation) { crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx); if (null_pkey == tx_pub_key) return false; - return lookup_acc_outs(acc, tx, get_tx_pub_key_from_extra(tx), outs, money_transfered, derivation); + return lookup_acc_outs(acc, tx, get_tx_pub_key_from_extra(tx), outs, sum_of_native_outs, derivation); } //--------------------------------------------------------------- bool check_tx_derivation_hint(const transaction& tx, const crypto::key_derivation& derivation) @@ -2665,22 +2713,22 @@ namespace currency return true; } //--------------------------------------------------------------- - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector& 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& outs, uint64_t& sum_of_native_outs, crypto::key_derivation& derivation) { std::list htlc_info_list; - return lookup_acc_outs(acc, tx, tx_pub_key, outs, money_transfered, derivation, htlc_info_list); + return lookup_acc_outs(acc, tx, tx_pub_key, outs, sum_of_native_outs, derivation, htlc_info_list); } //--------------------------------------------------------------- - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector& outs, uint64_t& money_transfered, crypto::key_derivation& derivation, std::list& htlc_info_list) + bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector& outs, uint64_t& sum_of_native_outs, crypto::key_derivation& derivation, std::list& htlc_info_list) { - money_transfered = 0; + sum_of_native_outs = 0; bool r = generate_key_derivation(tx_pub_key, acc.view_secret_key, derivation); CHECK_AND_ASSERT_MES(r, false, "unable to generate derivation from tx_pub = " << tx_pub_key << " * view_sec, invalid tx_pub?"); if (is_coinbase(tx) && get_block_height(tx) == 0 && tx_pub_key == ggenesis_tx_pub_key) { //genesis coinbase - return lookup_acc_outs_genesis(acc, tx, tx_pub_key, outs, money_transfered, derivation); + return lookup_acc_outs_genesis(acc, tx, tx_pub_key, outs, sum_of_native_outs, derivation); } if (!check_tx_derivation_hint(tx, derivation)) @@ -2697,13 +2745,13 @@ namespace currency if (is_out_to_acc(acc.account_address, t, derivation, output_index)) { outs.emplace_back(output_index, o.amount); - money_transfered += o.amount; + sum_of_native_outs += o.amount; } VARIANT_CASE_CONST(txout_multisig, t) if (is_out_to_acc(acc.account_address, t, derivation, output_index)) { outs.emplace_back(output_index, o.amount); // TODO: @#@# consider this - //don't cout this money + //don't cout this money in sum_of_native_outs } VARIANT_CASE_CONST(txout_htlc, htlc) htlc_info hi = AUTO_VAL_INIT(hi); @@ -2717,6 +2765,11 @@ namespace currency hi.hltc_our_out_is_before_expiration = false; htlc_info_list.push_back(hi); } + else + { + LOG_ERROR("lookup_acc_outs: handling txout_htlc went wrong, output_index: " << output_index); + return false; + } outs.emplace_back(output_index, o.amount); VARIANT_CASE_OTHER() LOG_ERROR("Wrong type at lookup_acc_outs, unexpected type is: " << o.target.type().name()); @@ -2730,9 +2783,11 @@ namespace currency crypto::scalar_t amount_blinding_mask = 0, asset_id_blinding_mask = 0; if (is_out_to_acc(acc.account_address, zo, derivation, output_index, amount, asset_id, amount_blinding_mask, asset_id_blinding_mask)) { - crypto::point_t asset_id_pt = crypto::point_t(zo.blinded_asset_id) - asset_id_blinding_mask * crypto::c_point_X; - outs.emplace_back(output_index, amount, amount_blinding_mask, asset_id_blinding_mask, asset_id_pt.to_public_key()); - money_transfered += amount; + crypto::point_t asset_id_pt = crypto::point_t(zo.blinded_asset_id).modify_mul8() - asset_id_blinding_mask * crypto::c_point_X; + crypto::public_key asset_id = asset_id_pt.to_public_key(); + outs.emplace_back(output_index, amount, amount_blinding_mask, asset_id_blinding_mask, asset_id); + if (asset_id == currency::native_coin_asset_id) + sum_of_native_outs += amount; } } VARIANT_SWITCH_END(); diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index 302d348f..164c4288 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -238,7 +238,9 @@ namespace currency }; bool verify_multiple_zc_outs_range_proofs(const std::vector& range_proofs); - bool check_tx_balance(const transaction& tx, uint64_t additional_inputs_amount_and_fees_for_mining_tx = 0); + 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(const transaction& tx, const crypto::hash& tx_id, const asset_descriptor_operation& ado, crypto::public_key& asset_id); //--------------------------------------------------------------- bool construct_miner_tx(size_t height, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins, size_t current_block_size, @@ -320,9 +322,9 @@ namespace currency 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& 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& outs, uint64_t& money_transfered, crypto::key_derivation& derivation, std::list& htlc_info_list); - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& 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& outs, uint64_t& sum_of_native_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& outs, uint64_t& sum_of_native_outs, crypto::key_derivation& derivation, std::list& htlc_info_list); + bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& sum_of_native_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); From b5ad2ffcdc6244e7b5532f46be3a7185212f77e3 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Tue, 21 Feb 2023 17:18:21 +0100 Subject: [PATCH 049/112] implemented boost::optional serialization --- src/currency_core/currency_basic.h | 13 ++++--- src/gui/qt-daemon/layout | 2 +- src/serialization/boost_types.h | 60 ++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 src/serialization/boost_types.h diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h index 392ed389..2ea50948 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -30,6 +30,7 @@ #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 @@ -836,13 +837,13 @@ namespace currency BEGIN_VERSIONED_SERIALIZE() FIELD(operation_type) FIELD(descriptor) - //FIELD(opt_amount_commitment) + FIELD(opt_amount_commitment) END_SERIALIZE() BEGIN_BOOST_SERIALIZATION() BOOST_SERIALIZE(operation_type) BOOST_SERIALIZE(descriptor) - //BOOST_SERIALIZE(opt_amount_commitment) + BOOST_SERIALIZE(opt_amount_commitment) END_BOOST_SERIALIZATION() }; @@ -853,13 +854,13 @@ namespace currency boost::optional opt_amount_commitment_g_proof; // for non-hidden supply, proofs that amount_commitment - supply * asset_id = lin(G) BEGIN_VERSIONED_SERIALIZE() - //FIELD(opt_amount_commitment_composition_proof) - //FIELD(opt_amount_commitment_g_proof) + 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_SERIALIZE(opt_amount_commitment_composition_proof) + BOOST_SERIALIZE(opt_amount_commitment_g_proof) END_BOOST_SERIALIZATION() }; diff --git a/src/gui/qt-daemon/layout b/src/gui/qt-daemon/layout index f8d6ed1b..b45d5a82 160000 --- a/src/gui/qt-daemon/layout +++ b/src/gui/qt-daemon/layout @@ -1 +1 @@ -Subproject commit f8d6ed1bbe38d48d7e762154ea9ccbdb33d88424 +Subproject commit b45d5a82285a8804c859e9d3548fae693716cd6a diff --git a/src/serialization/boost_types.h b/src/serialization/boost_types.h new file mode 100644 index 00000000..154705b8 --- /dev/null +++ b/src/serialization/boost_types.h @@ -0,0 +1,60 @@ +// Copyright (c) 2014-2017 The 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 + + +template