diff --git a/README.md b/README.md index 6af4daa1..189c88cf 100644 --- a/README.md +++ b/README.md @@ -1,61 +1,79 @@ [![Coverity Scan](https://scan.coverity.com/projects/18767/badge.svg)](https://scan.coverity.com/projects/zanoproject) [![Discord](https://img.shields.io/discord/538361472691077130?label=discord&logo=discord)](https://discord.gg/wE3rmYY) -Building +## Cloning + +Be sure to clone the repository properly:\ +`$ git clone --recursive https://github.com/hyle-team/zano.git` + +# Building -------- -### Cloning - -Be sure to properly clone the repository: - -`$ git clone --recursive https://github.com/hyle-team/zano.git` ### Dependencies | component / version | minimum
(not recommended but may work) | recommended | most recent of what we have ever tested | |--|--|--|--| -| gcc (Linux) | 5.4.0 | 7.2.0 | 8.3.0 | +| gcc (Linux) | 5.4.0 | 7.4.0 | 8.3.0 | | llvm/clang (Linux) | UNKNOWN | 7.0.1 | 8.0.0 | -| [MSVC](https://visualstudio.microsoft.com/downloads/) (Windows) | 2015 (14.0 update 1) | 2017 (15.5.7) | 2019 | -| [XCode](https://developer.apple.com/downloads/) (macOS) | 7.3.1 | 9.2 | 9.2 | -| [CMake](https://cmake.org/download/) | 2.8.6 | 3.15.5 | 3.15.5 | -| [Boost](https://www.boost.org/users/download/) | 1.56 | 1.68 | 1.68 | -| [Qt](https://download.qt.io/archive/qt/) (only for GUI) | 5.8.0 | 5.11.2 | 5.13.2 | +| [MSVC](https://visualstudio.microsoft.com/downloads/) (Windows) | 2015 (14.0 update 1) | 2017 (15.9.0) | 2019 | +| [XCode](https://developer.apple.com/downloads/) (macOS) | 9.2 | 12.3 | 12.3 | +| [CMake](https://cmake.org/download/) | 2.8.6 | 3.15.5 | 3.20 | +| [Boost](https://www.boost.org/users/download/) | 1.56 | 1.68 | 1.76 | +| [Qt](https://download.qt.io/archive/qt/) (*only for GUI*) | 5.8.0 | 5.11.2 | 5.15.2 | + +Note:\ +[*server version*] denotes steps required for building command-line tools (daemon, simplewallet, etc.).\ +[*GUI version*] denotes steps required for building Zano executable with GUI. + +
### Linux Recommended OS version: Ubuntu 18.04 LTS. 1. Prerequisites - 1. Prerequisites for server version: - - sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git screen - - 1. Prerequisites for GUI version: - sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git screen mesa-common-dev libglu1-mesa-dev` + [*server version*] + + sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git screen + + [*GUI version*] + + sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git screen mesa-common-dev libglu1-mesa-dev 2. Download and build Boost - wget https://dl.bintray.com/boostorg/release/1.68.0/source/boost_1_68_0.tar.bz2 + wget https://boostorg.jfrog.io/artifactory/main/release/1.68.0/source/boost_1_68_0.tar.bz2 tar -xjf boost_1_68_0.tar.bz2 cd boost_1_68_0 ./bootstrap.sh --with-libraries=system,filesystem,thread,date_time,chrono,regex,serialization,atomic,program_options,locale,timer ./b2 -3. Install Qt +3. Install Qt\ +(*GUI version only, skip this step if you're building server version*) + + [*GUI version*] wget https://download.qt.io/new_archive/qt/5.11/5.11.2/qt-opensource-linux-x64-5.11.2.run chmod +x qt-opensource-linux-x64-5.11.2.run ./qt-opensource-linux-x64-5.11.2.run - Then follow the instructions in Wizard. Don't forget to tick WebEngine module! + Then follow the instructions in Wizard. Don't forget to tick the WebEngine module checkbox! + +4. Set environment variables properly\ +For instance, by adding the following lines to `~/.bashrc` + + [*server version*] + + export BOOST_ROOT=/home/user/boost_1_68_0 + + + [*GUI version*] -4. Set `BOOST_ROOT` and `QT_PREFIX_PATH` envinorment variables\ - For instance, by adding these lines to `~/.bashrc`: - export BOOST_ROOT=/home/user/boost_1_68_0 export QT_PREFIX_PATH=/home/user/Qt5.11.2/5.11.2/gcc_64 + 5. Building binaries 1. Building daemon and simplewallet: @@ -66,7 +84,9 @@ Recommended OS version: Ubuntu 18.04 LTS. cmake .. make -j1 daemon simplewallet - **NOTICE**: If you are building on machine with relatively high anount of RAM or with proper setting of virtual memory, then you can use `-j2` or `-j` option to speed up the building process. Use with caution. + **NOTICE**: If you are building on a machine with a relatively high amount of RAM or with the proper setting of virtual memory, then you can use `-j2` or `-j` option to speed up the building process. Use with caution. + + **NOTICE 2**: If you'd like to build binaries for the testnet, use `cmake -D TESTNET=TRUE ..` instead of `cmake ..` . 1. Building GUI: @@ -75,6 +95,8 @@ Recommended OS version: Ubuntu 18.04 LTS. 7. Look for the binaries in `build` folder +
+ ### Windows Recommended OS version: Windows 7 x64. 1. Install required prerequisites (Boost, Qt, CMake). @@ -83,13 +105,17 @@ Recommended OS version: Windows 7 x64. 4. Go to the build folder and open generated Zano.sln in MSVC. 5. Build. -In order to correctly deploy Qt GUI application you also need to do the following: +In order to correctly deploy Qt GUI application, you also need to do the following: + 6. Copy Zano.exe to a folder (e.g. `depoy`). -7. Run `PATH_TO_QT\bin\windeployqt.exe deploy/Zano.exe`. +7. Run `PATH_TO_QT\bin\windeployqt.exe deploy\Zano.exe`. 8. Copy folder `\src\gui\qt-daemon\html` to `deploy\html`. +9. Now you can run `Zano.exe` + +
### macOS -Recommended OS version: macOS Sierra 10.12.6 x64. +Recommended OS version: macOS Sierra 10.15.4 x64. 1. Install required prerequisites. 2. Set environment variables as stated in `utils/macosx_build_config.command`. 3. `mkdir build`
`cd build`
`cmake ..`
`make` @@ -104,7 +130,7 @@ To build GUI application: e. Press “Create”, then “Done”.\ f. Make sure the certificate was added to keychain "System". If not—move it to "System".\ g. Double click the certificate you've just added, enter the trust section and under "When using this certificate" select "Always trust".\ - h. Unfold the certificate in Keychain Access window and double click underlying private key "Zano". Select "Access Control" tab, then select "Allow all applications to access this item". Click "Save Changes". + h. Unfold the certificate in Keychain Access window and double click the underlying private key "Zano". Select "Access Control" tab, then select "Allow all applications to access this item". Click "Save Changes". 2. Revise building script, comment out unwanted steps and run it: `utils/build_script_mac_osx.sh` 3. The application should be here: `/buid_mac_osx_64/release/src` diff --git a/contrib/eos_portable_archive/eos/portable_oarchive.hpp b/contrib/eos_portable_archive/eos/portable_oarchive.hpp index fce2bd26..5f390194 100644 --- a/contrib/eos_portable_archive/eos/portable_oarchive.hpp +++ b/contrib/eos_portable_archive/eos/portable_oarchive.hpp @@ -340,7 +340,7 @@ namespace eos { // we choose to use little endian because this way we just // save the first size bytes to the stream and skip the rest #if BOOST_VERSION >= 106900 - temp = endian::native_to_little(temp); + temp = endian::native_to_little(t); #else endian::store_little_endian(&temp, t); #endif diff --git a/contrib/epee/include/misc_language.h b/contrib/epee/include/misc_language.h index 1a02c7c8..276dfe02 100644 --- a/contrib/epee/include/misc_language.h +++ b/contrib/epee/include/misc_language.h @@ -65,6 +65,8 @@ namespace epee } +#define STD_TRY_CATCH_LOCATION(return_val) STD_TRY_CATCH(LOCATION_SS, return_val) + /* helper class, to make able get namespace via decltype()::*/ template class namespace_accessor: public base_class{}; diff --git a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h index 05c235d8..01f9e257 100644 --- a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h +++ b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h @@ -26,6 +26,7 @@ #pragma once +#include #include namespace epee diff --git a/contrib/epee/include/storages/portable_storage.h b/contrib/epee/include/storages/portable_storage.h index 92fbeece..4d36cc03 100644 --- a/contrib/epee/include/storages/portable_storage.h +++ b/contrib/epee/include/storages/portable_storage.h @@ -28,6 +28,7 @@ #pragma once +#include #include "misc_language.h" #include "portable_storage_base.h" #include "portable_storage_to_bin.h" diff --git a/src/common/pre_download.h b/src/common/pre_download.h index e119d505..5feec36b 100644 --- a/src/common/pre_download.h +++ b/src/common/pre_download.h @@ -50,7 +50,8 @@ namespace tools boost::system::error_code ec; uint64_t sz = boost::filesystem::file_size(db_main_file_path, ec); - if (pre_download.unpacked_size == 0 || !(ec || (pre_download.unpacked_size > sz && pre_download.unpacked_size - sz > pre_download_min_size_difference) || command_line::has_arg(vm, command_line::arg_force_predownload)) ) + bool flag_force_predownload = command_line::has_arg(vm, command_line::arg_force_predownload); + if (pre_download.unpacked_size == 0 || !(ec || (pre_download.unpacked_size > sz && pre_download.unpacked_size - sz > pre_download_min_size_difference) || flag_force_predownload) ) { LOG_PRINT_MAGENTA("Pre-downloading not needed (db file size = " << sz << ")", LOG_LEVEL_0); return true; @@ -92,15 +93,15 @@ namespace tools r = cl.download_and_unzip(cb, downloading_file_path, url, 5000 /* timout */, "GET", std::string(), 30 /* fails count */); if (!r) { - LOG_PRINT_RED("Download failed", LOG_LEVEL_0); - return false; + LOG_PRINT_RED("Downloading failed", LOG_LEVEL_0); + return !flag_force_predownload; // fatal error only if force-predownload } crypto::hash data_hash = hash_stream.calculate_hash(); if (epee::string_tools::pod_to_hex(data_hash) != pre_download.hash) { LOG_ERROR("hash missmatch in downloaded file, got: " << epee::string_tools::pod_to_hex(data_hash) << ", expected: " << pre_download.hash); - return false; + return !flag_force_predownload; // fatal error only if force-predownload } LOG_PRINT_GREEN("Download succeeded, hash " << pre_download.hash << " is correct" , LOG_LEVEL_0); diff --git a/src/connectivity_tool/conn_tool.cpp b/src/connectivity_tool/conn_tool.cpp index ce3143e9..b14125ad 100644 --- a/src/connectivity_tool/conn_tool.cpp +++ b/src/connectivity_tool/conn_tool.cpp @@ -593,6 +593,7 @@ bool handle_get_daemon_info(po::variables_map& vm) PRINT_FIELD_NAME(res.performance_data, "", tx_append_time) PRINT_FIELD_NAME(res.performance_data, "", tx_append_rl_wait) PRINT_FIELD_NAME(res.performance_data, "", tx_append_is_expired) + PRINT_FIELD_NAME(res.performance_data, "", tx_mixin_count) PRINT_FIELD_NAME(res.performance_data, "", tx_check_inputs_prefix_hash) PRINT_FIELD_NAME(res.performance_data, "", tx_check_inputs_attachment_check) PRINT_FIELD_NAME(res.performance_data, "", tx_check_inputs_loop) diff --git a/src/crypto/crypto-sugar.h b/src/crypto/crypto-sugar.h index 43e69c42..600fe914 100644 --- a/src/crypto/crypto-sugar.h +++ b/src/crypto/crypto-sugar.h @@ -315,6 +315,13 @@ namespace crypto return *this; } + // returns this = a * b + scalar_t& assign_mul(const scalar_t& a, const scalar_t& b) + { + sc_mul(m_s, a.m_s, b.m_s); + return *this; + } + /* I think it has bad symantic (operator-like), consider rename/reimplement -- sowle */ @@ -426,6 +433,17 @@ namespace crypto }; // struct scalar_t + // + // Global constants + // + + extern const scalar_t c_scalar_1; + extern const scalar_t c_scalar_L; + extern const scalar_t c_scalar_Lm1; + extern const scalar_t c_scalar_P; + extern const scalar_t c_scalar_Pm1; + extern const scalar_t c_scalar_256m1; + extern const scalar_t c_scalar_1div8; // // @@ -479,6 +497,7 @@ namespace crypto zero(); } + // as we're using additive notation, zero means identity group element here and after void zero() { ge_p3_0(&m_p3); @@ -490,6 +509,11 @@ namespace crypto return fe_isnonzero(m_p3.X) * fe_cmp(m_p3.Y, m_p3.Z) == 0; } + bool is_in_main_subgroup() const + { + return (c_scalar_L * *this).is_zero(); + } + bool from_public_key(const crypto::public_key& pk) { return ge_frombytes_vartime(&m_p3, reinterpret_cast(&pk)) == 0; @@ -710,19 +734,151 @@ namespace crypto }; // struct point_g_t + // + // vector of scalars + // + struct scalar_vec_t : public std::vector + { + typedef std::vector super_t; + + scalar_vec_t() {} + scalar_vec_t(size_t n) : super_t(n) {} + scalar_vec_t(std::initializer_list init_list) : super_t(init_list) {} + + bool is_reduced() const + { + for (auto& el : *this) + if (!el.is_reduced()) + return false; + return true; + } + + // add a scalar rhs to each element + scalar_vec_t operator+(const scalar_t& rhs) const + { + scalar_vec_t result(size()); + for (size_t i = 0, n = size(); i < n; ++i) + result[i] = at(i) + rhs; + return result; + } + + // subtract a scalar rhs to each element + scalar_vec_t operator-(const scalar_t& rhs) const + { + scalar_vec_t result(size()); + for (size_t i = 0, n = size(); i < n; ++i) + result[i] = at(i) - rhs; + return result; + } + + // multiply each element of the vector by a scalar + scalar_vec_t operator*(const scalar_t& rhs) const + { + scalar_vec_t result(size()); + for (size_t i = 0, n = size(); i < n; ++i) + result[i] = at(i) * rhs; + return result; + } + + // component-wise multiplication (a.k.a the Hadamard product) (only if their sizes match) + scalar_vec_t operator*(const scalar_vec_t& rhs) const + { + scalar_vec_t result; + const size_t n = size(); + if (n != rhs.size()) + return result; + + result.resize(size()); + for (size_t i = 0; i < n; ++i) + result[i] = at(i) * rhs[i]; + return result; + } + + // add each element of two vectors, but only if their sizes match + scalar_vec_t operator+(const scalar_vec_t& rhs) const + { + scalar_vec_t result; + const size_t n = size(); + if (n != rhs.size()) + return result; + + result.resize(size()); + for (size_t i = 0; i < n; ++i) + result[i] = at(i) + rhs[i]; + return result; + } + + // zeroes all elements + void zero() + { + size_t size_bytes = sizeof(scalar_t) * size(); + memset(data(), 0, size_bytes); + } + + // invert all elements in-place efficiently: 4*N muptiplications + 1 inversion + void invert() + { + // muls muls_rev + // 0: 1 2 3 .. n-1 + // 1: 0 2 3 .. n-1 + // 2: 0 1 3 .. n-1 + // + // n-1: 0 1 2 3 .. n-2 + + const size_t size = this->size(); + + if (size < 2) + { + if (size == 1) + at(0) = at(0).reciprocal(); + return; + } + + scalar_vec_t muls(size), muls_rev(size); + muls[0] = 1; + for (size_t i = 0; i < size - 1; ++i) + muls[i + 1] = at(i) * muls[i]; + + muls_rev[size - 1] = 1; + for (size_t i = size - 1; i != 0; --i) + muls_rev[i - 1] = at(i) * muls_rev[i]; + + scalar_t inv = (muls[size - 1] * at(size - 1)).reciprocal(); + + for (size_t i = 0; i < size; ++i) + at(i) = muls[i] * inv * muls_rev[i]; + } + + scalar_t calc_hs() const; + + }; // scalar_vec_t + + + // treats vector of scalars as an M x N matrix just for convenience + template + struct scalar_mat_t : public scalar_vec_t + { + typedef scalar_vec_t super_t; + static_assert(N > 0, "invalid N value"); + + scalar_mat_t() {} + scalar_mat_t(size_t n) : super_t(n) {} + scalar_mat_t(std::initializer_list init_list) : super_t(init_list) {} + + // matrix accessor M rows x N cols + scalar_t& operator()(size_t row, size_t col) + { + return at(row * N + col); + } + }; // scalar_mat_t + + + // // Global constants // extern const point_g_t c_point_G; - - extern const scalar_t c_scalar_1; - extern const scalar_t c_scalar_L; - extern const scalar_t c_scalar_Lm1; - extern const scalar_t c_scalar_P; - extern const scalar_t c_scalar_Pm1; - extern const scalar_t c_scalar_256m1; - extern const scalar_t c_scalar_1div8; extern const point_t c_point_H; extern const point_t c_point_0; @@ -901,4 +1057,11 @@ namespace crypto }; // hash_helper_t struct + inline scalar_t scalar_vec_t::calc_hs() const + { + // hs won't touch memory if size is 0, so it's safe + return hash_helper_t::hs(data(), sizeof(scalar_t) * size()); + } + + } // namespace crypto diff --git a/src/crypto/range_proofs.cpp b/src/crypto/range_proofs.cpp new file mode 100644 index 00000000..b6750a09 --- /dev/null +++ b/src/crypto/range_proofs.cpp @@ -0,0 +1,12 @@ +// Copyright (c) 2021 Zano Project (https://zano.org/) +// Copyright (c) 2021 sowle (val@zano.org, crypto.sowle@gmail.com) +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "range_proofs.h" + +namespace crypto +{ + const point_t& bpp_crypto_trait_zano::bpp_H = c_point_H; + + +} diff --git a/src/crypto/range_proofs.h b/src/crypto/range_proofs.h new file mode 100644 index 00000000..b3d04d68 --- /dev/null +++ b/src/crypto/range_proofs.h @@ -0,0 +1,823 @@ +// Copyright (c) 2021 Zano Project (https://zano.org/) +// Copyright (c) 2021 sowle (val@zano.org, crypto.sowle@gmail.com) +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#pragma once + +// +// This file contains the implementation of range proof protocol. +// Namely, Bulletproofs+ https://eprint.iacr.org/2020/735.pdf +// + +#include "epee/include/misc_log_ex.h" +#include "crypto-sugar.h" + +namespace crypto +{ + + // returns x + x^2 + x^3 + ... + x^(2^f) + // == x * (x + 1) * (x^2 + 1) * (x^4 + 1) * ...(x^(f+1) + 1) + inline scalar_t sum_of_powers(scalar_t x, size_t f) + { + scalar_t result = x; + for (size_t i = 0; i < f; ++i) + { + result.assign_muladd(result, x, result); + x *= x; + } + return result; + } + + constexpr size_t c_bpp_log2_n = 6; + constexpr size_t c_bpp_n = 64; // 2^64 is the upper bound for the witness's range + constexpr size_t c_bpp_values_max = 16; // maximum number of elements in BP+ proof, i.e. max allowed BP+ outputs + constexpr size_t c_bpp_mn_max = c_bpp_n * c_bpp_values_max; + + // returns smallest k, s.t. v <= 2**k + inline size_t calc_exp_power_of_2_upper_bound(size_t v) + { + constexpr size_t max_v = (SIZE_MAX >> 1) + 1; + //if (v > max_v) + // return 0; + + size_t pow = 1, result = 0; + while (v > pow) + { + pow <<= 1; + ++result; + } + return result; + } + + // returns least significant bit uing de Bruijn sequence + // http://graphics.stanford.edu/~seander/bithacks.html + inline uint8_t calc_lsb_32(uint32_t v) + { + static const uint8_t multiply_de_bruijn_bit_position[32] = + { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + return multiply_de_bruijn_bit_position[((uint32_t)((v & -(int32_t)v) * 0x077CB531U)) >> 27]; + } + + + //////////////////////////////////////// + // crypto trait for Zano + //////////////////////////////////////// + struct bpp_crypto_trait_zano + { + static void calc_pedersen_commitment(const scalar_t& value, const scalar_t& mask, point_t& commitment) + { + commitment = value * c_point_G + mask * c_point_H; + } + + static const scalar_t& get_initial_transcript() + { + static scalar_t value = hash_helper_t::hs("Zano BP+ initial transcript"); + return value; + } + + // assumes hsc is cleared + static void update_transcript(hash_helper_t::hs_t& hsc, scalar_t& e, const std::vector& points) + { + hsc.add_scalar(e); + hsc.add_points_array(points); + e = hsc.calc_hash(); + } + + static const point_t& get_generator(bool select_H, size_t index) + { + if (index >= c_bpp_mn_max) + return c_point_0; // out of bound + + static std::vector generators(2 * c_bpp_mn_max); + static bool calculated = false; + if (!calculated) + { + scalar_t hash_buf[2] = { hash_helper_t::hs("Zano BP+ generator"), 0 }; + for (size_t i = 0; i < 2 * c_bpp_mn_max; ++i) + { + hash_buf[1].m_u64[0] = i; + ge_bytes_hash_to_ec(&generators[i].m_p3, &hash_buf, sizeof hash_buf); + } + calculated = true; + } + + return generators[2 * index + (select_H ? 1 : 0)]; + } + + static const point_t& bpp_H; + }; + + + struct bpp_signature + { + std::vector L; // size = log_2(m * n) + std::vector R; + public_key A0; + public_key A; + public_key B; + scalar_t r; + scalar_t s; + scalar_t delta; + }; + +#define DBG_VAL_PRINT(x) std::cout << #x ": " << x << ENDL +#define DBG_PRINT(x) std::cout << x << ENDL + + template + bool bpp_gen(const std::vector& values, const scalar_vec_t& masks, bpp_signature& sig, std::vector& commitments, uint8_t* p_err = nullptr) + { +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("bpp_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() > 0 && values.size() <= c_bpp_values_max && values.size() == masks.size(), 1); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(masks.is_reduced(), 3); + + const size_t c_bpp_log2_m = calc_exp_power_of_2_upper_bound(values.size()); + const size_t c_bpp_m = 1ull << c_bpp_log2_m; + const size_t c_bpp_mn = c_bpp_m * c_bpp_n; + const size_t c_bpp_log2_mn = c_bpp_log2_m + c_bpp_log2_n; + + // pre-multiply all output points by c_scalar_1div8 + // in order to enforce these points to be in the prime-order subgroup (after mul by 8 in bpp_verify()) + + // calc commitments vector as commitments[i] = 1/8 * values[i] * G + 1/8 * masks[i] * H + commitments.resize(values.size()); + for (size_t i = 0; i < values.size(); ++i) + CT::calc_pedersen_commitment(scalar_t(values[i]) * c_scalar_1div8, masks[i] * c_scalar_1div8, commitments[i]); + + + // s.a. BP+ paper, page 15, eq. 11 + // decompose v into aL and aR: + // v = aL o (1, 2, 2^2, ..., 2^n-1), o - component-wise product aka Hadamard product + // aR = aL - (1, 1, ... 1) + // aR o aL = 0 + + // aLs = (aL_0, aL_1, ..., aL_m-1) -- `bit` matrix of c_bpp_m x c_bpp_n, each element is a scalar + + scalar_mat_t aLs(c_bpp_mn), aRs(c_bpp_mn); + aLs.zero(); + aRs.zero(); + // m >= values.size, first set up [0..values.size-1], then -- [values.size..m-1] (padding area) + for (size_t i = 0; i < values.size(); ++i) + { + uint64_t v = values[i]; + for (size_t j = 0; j < c_bpp_n; ++j) + { + if (v & 1) + aLs(i, j) = c_scalar_1; // aL = 1, aR = 0 + else + aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 + v >>= 1; + } + } + + for (size_t i = values.size(); i < c_bpp_m; ++i) + for (size_t j = 0; j < c_bpp_n; ++j) + aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 + + + // using e as Fiat-Shamir transcript + scalar_t e = CT::get_initial_transcript(); + DBG_PRINT("initial transcript: " << e); + + hash_helper_t::hs_t hsc; + CT::update_transcript(hsc, e, commitments); + + // BP+ paper, page 15: The prover begins with sending A = g^aL h^aR h^alpha (group element) + // so we calculate A0 = alpha * H + SUM(aL_i * G_i) + SUM(aR_i * H_i) + + scalar_t alpha = scalar_t::random(); + point_t A0 = alpha * CT::bpp_H; + + for (size_t i = 0; i < c_bpp_mn; ++i) + A0 += aLs[i] * CT::get_generator(false, i) + aRs[i] * CT::get_generator(true, i); + + // part of 1/8 defense scheme + A0 *= c_scalar_1div8; + A0.to_public_key(sig.A0); + + DBG_VAL_PRINT(alpha); + DBG_VAL_PRINT(A0); + + // calculate scalar challenges y and z + hsc.add_scalar(e); + hsc.add_pub_key(sig.A0); + scalar_t y = hsc.calc_hash(); + scalar_t z = hash_helper_t::hs(y); + e = z; // transcript for further steps + DBG_VAL_PRINT(y); + DBG_VAL_PRINT(z); + + // Computing vector d for aggregated version of the protocol (BP+ paper, page 17) + // (note: elements is stored column-by-column in memory) + // d = | 1 * z^(2*1), 1 * z^(2*2), 1 * z^(2*3), ..., 1 * z^(2*m) | + // | 2 * z^(2*1), 2 * z^(2*2), 2 * z^(2*3), ..., 2 * z^(2*m) | + // | 4 * z^(2*1), 4 * z^(2*2), 4 * z^(2*3), ..., 4 * z^(2*m) | + // | ....................................................................................... | + // | 2^(n-1) * z^(2*1), 2^(n-1) * z^(2*2), 2^(n-1) * z^(2*3), ..., 2^(n-1) * z^(2*m)) | + // Note: sum(d_i) = (2^n - 1) * ((z^2)^1 + (z^2)^2 + ... (z^2)^m)) = (2^n-1) * sum_of_powers(x^2, log(m)) + + scalar_t z_sq = z * z; + scalar_mat_t d(c_bpp_mn); + d(0, 0) = z_sq; + // first row + for (size_t i = 1; i < c_bpp_m; ++i) + d(i, 0) = d(i - 1, 0) * z_sq; + // all rows + for (size_t j = 1; j < c_bpp_n; ++j) + for (size_t i = 0; i < c_bpp_m; ++i) + d(i, j) = d(i, j - 1) + d(i, j - 1); + + DBG_PRINT("Hs(d): " << d.calc_hs()); + + // calculate extended Vandermonde vector y = (1, y, y^2, ..., y^(mn+1)) (BP+ paper, page 18, Fig. 3) + // (calculate two more elements (1 and y^(mn+1)) for convenience) + scalar_vec_t y_powers(c_bpp_mn + 2); + y_powers[0] = 1; + for (size_t i = 1; i <= c_bpp_mn + 1; ++i) + y_powers[i] = y_powers[i - 1] * y; + + const scalar_t& y_mn_p1 = y_powers[c_bpp_mn + 1]; + + DBG_PRINT("Hs(y_powers): " << y_powers.calc_hs()); + + // aL_hat = aL - 1*z + scalar_vec_t aLs_hat = aLs - z; + // aL_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3) + scalar_vec_t aRs_hat = aRs + z; + for (size_t i = 0; i < c_bpp_mn; ++i) + aRs_hat[i] += d[i] * y_powers[c_bpp_mn - i]; + + DBG_PRINT("Hs(aLs_hat): " << aLs_hat.calc_hs()); + DBG_PRINT("Hs(aRs_hat): " << aRs_hat.calc_hs()); + + // calculate alpha_hat + // alpha_hat = alpha + SUM(z^(2j) * gamma_j * y^(mn+1)) for j = 1..m + // i.e. \hat{\alpha} = \alpha + y^{m n+1} \sum_{j = 1}^{m} z^{2j} \gamma_j + scalar_t alpha_hat = 0; + for (size_t i = 0; i < masks.size(); ++i) + alpha_hat += d(i, 0) * masks[i]; + alpha_hat = alpha + y_mn_p1 * alpha_hat; + + DBG_VAL_PRINT(alpha_hat); + + // calculate y^-1, y^-2, ... + const scalar_t y_inverse = y.reciprocal(); + scalar_vec_t y_inverse_powers(c_bpp_mn / 2 + 1); // the greatest power we need is c_bpp_mn/2 (at the first reduction round) + y_inverse_powers[0] = 1; + for (size_t i = 1, size = y_inverse_powers.size(); i < size; ++i) + y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inverse; + + // prepare generator's vector + std::vector g(c_bpp_mn), h(c_bpp_mn); + for (size_t i = 0; i < c_bpp_mn; ++i) + { + g[i] = CT::get_generator(false, i); + h[i] = CT::get_generator(true, i); + } + + // WIP zk-argument called with zk-WIP(g, h, G, H, A_hat, aL_hat, aR_hat, alpha_hat) + + scalar_vec_t& a = aLs_hat; + scalar_vec_t& b = aRs_hat; + + sig.L.resize(c_bpp_log2_mn); + sig.R.resize(c_bpp_log2_mn); + + // zk-WIP reduction rounds (s.a. the preprint page 13 Fig. 1) + for (size_t n = c_bpp_mn / 2, ni = 0; n >= 1; n /= 2, ++ni) + { + DBG_PRINT(ENDL << "#" << ni); + + // zk-WIP(g, h, G, H, P, a, b, alpha) + + scalar_t dL = scalar_t::random(); + DBG_VAL_PRINT(dL); + scalar_t dR = scalar_t::random(); + DBG_VAL_PRINT(dR); + + // a = (a1, a2), b = (b1, b2) -- vectors of scalars + // cL = -- scalar + scalar_t cL = 0; + for (size_t i = 0; i < n; ++i) + cL += a[i] * y_powers[i + 1] * b[n + i]; + + DBG_VAL_PRINT(cL); + + // cR = * y^n -- scalar + scalar_t cR = 0; + for (size_t i = 0; i < n; ++i) + cR += a[n + i] * y_powers[i + 1] * b[i]; + cR *= y_powers[n]; + + DBG_VAL_PRINT(cR); + + // L = y^-n * a1 * g2 + b2 * h1 + cL * G + dL * H -- point + point_t sum = c_point_0; + for (size_t i = 0; i < n; ++i) + sum += a[i] * g[n + i]; + point_t L; + CT::calc_pedersen_commitment(cL, dL, L); + for (size_t i = 0; i < n; ++i) + L += b[n + i] * h[i]; + L += y_inverse_powers[n] * sum; + L *= c_scalar_1div8; + DBG_VAL_PRINT(L); + + // R = y^n * a2 * g1 + b1 * h2 + cR * G + dR * H -- point + sum.zero(); + for (size_t i = 0; i < n; ++i) + sum += a[n + i] * g[i]; + point_t R; + CT::calc_pedersen_commitment(cR, dR, R); + for (size_t i = 0; i < n; ++i) + R += b[i] * h[n + i]; + R += y_powers[n] * sum; + R *= c_scalar_1div8; + DBG_VAL_PRINT(R); + + // put L, R to the sig + L.to_public_key(sig.L[ni]); + R.to_public_key(sig.R[ni]); + + // update the transcript + hsc.add_scalar(e); + hsc.add_pub_key(sig.L[ni]); + hsc.add_pub_key(sig.R[ni]); + e = hsc.calc_hash(); + DBG_VAL_PRINT(e); + + // recalculate arguments for the next round + scalar_t e_squared = e * e; + scalar_t e_inverse = e.reciprocal(); + scalar_t e_inverse_squared = e_inverse * e_inverse; + scalar_t e_y_inv_n = e * y_inverse_powers[n]; + scalar_t e_inv_y_n = e_inverse * y_powers[n]; + + // g_hat = e^-1 * g1 + (e * y^-n) * g2 -- vector of points + for (size_t i = 0; i < n; ++i) + g[i] = e_inverse * g[i] + e_y_inv_n * g[n + i]; + + // h_hat = e * h1 + e^-1 * h2 -- vector of points + for (size_t i = 0; i < n; ++i) + h[i] = e * h[i] + e_inverse * h[n + i]; + + // P_hat = e^2 * L + P + e^-2 * R -- point + + // a_hat = e * a1 + e^-1 * y^n * a2 -- vector of scalars + for (size_t i = 0; i < n; ++i) + a[i] = e * a[i] + e_inv_y_n * a[n + i]; + + // b_hat = e^-1 * b1 + e * b2 -- vector of scalars + for (size_t i = 0; i < n; ++i) + b[i] = e_inverse * b[i] + e * b[n + i]; + + // alpha_hat = e^2 * dL + alpha + e^-2 * dR -- scalar + alpha_hat += e_squared * dL + e_inverse_squared * dR; + + // run next iteraton zk-WIP(g_hat, h_hat, G, H, P_hat, a_hat, b_hat, alpha_hat) + } + DBG_PRINT(""); + + // zk-WIP last round + scalar_t r = scalar_t::random(); + scalar_t s = scalar_t::random(); + scalar_t delta = scalar_t::random(); + scalar_t eta = scalar_t::random(); + DBG_VAL_PRINT(r); + DBG_VAL_PRINT(s); + DBG_VAL_PRINT(delta); + DBG_VAL_PRINT(eta); + + // A = r * g + s * h + (r y b + s y a) * G + delta * H -- point + point_t A = c_point_0; + CT::calc_pedersen_commitment(y * (r * b[0] + s * a[0]), delta, A); + A += r * g[0] + s * h[0]; + A *= c_scalar_1div8; + A.to_public_key(sig.A); + DBG_VAL_PRINT(A); + + // B = (r * y * s) * G + eta * H + point_t B = c_point_0; + CT::calc_pedersen_commitment(r * y * s, eta, B); + B *= c_scalar_1div8; + B.to_public_key(sig.B); + DBG_VAL_PRINT(B); + + // update the transcript + hsc.add_scalar(e); + hsc.add_pub_key(sig.A); + hsc.add_pub_key(sig.B); + e = hsc.calc_hash(); + DBG_VAL_PRINT(e); + + // finalize the signature + sig.r = r + e * a[0]; + sig.s = s + e * b[0]; + sig.delta = eta + e * delta + e * e * alpha_hat; + DBG_VAL_PRINT(sig.r); + DBG_VAL_PRINT(sig.s); + DBG_VAL_PRINT(sig.delta); + + return true; +#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + } // bpp_gen() + + + // efficient multiexponentiation (naive stub implementation atm, TODO) + template + bool multiexp_and_check_being_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand) + { + CHECK_AND_ASSERT_MES(g_scalars.size() < c_bpp_mn_max, false, "g_scalars oversized"); + CHECK_AND_ASSERT_MES(h_scalars.size() < c_bpp_mn_max, false, "h_scalars oversized"); + + point_t result = summand; + + for (size_t i = 0; i < g_scalars.size(); ++i) + result += g_scalars[i] * CT::get_generator(false, i); + + for (size_t i = 0; i < h_scalars.size(); ++i) + result += h_scalars[i] * CT::get_generator(true, i); + + if (!result.is_zero()) + { + LOG_PRINT_L0("multiexp result is non zero: " << result); + return false; + } + return true; + } + + + struct bpp_sig_commit_ref_t + { + bpp_sig_commit_ref_t(const bpp_signature& sig, const std::vector& commitments) + : sig(sig) + , commitments(commitments) + {} + const bpp_signature& sig; + const std::vector& commitments; + }; + + + template + bool bpp_verify(const std::vector& sigs, uint8_t* p_err = nullptr) + { +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("bpp_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + DBG_PRINT(ENDL << " . . . . bpp_verify() . . . . "); + + const size_t kn = sigs.size(); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(kn > 0, 1); + + struct intermediate_element_t + { + scalar_t y; + scalar_t z; + scalar_t z_sq; + scalar_vec_t e; + scalar_vec_t e_sq; + scalar_t e_final; + scalar_t e_final_sq; + size_t inv_e_offset; // offset in batch_for_inverse + size_t inv_y_offset; // offset in batch_for_inverse + size_t c_bpp_log2_m; + size_t c_bpp_m; + size_t c_bpp_mn; + point_t A; + point_t A0; + point_t B; + std::vector L; + std::vector R; + }; + std::vector interms(kn); + + size_t c_bpp_log2_m_max = 0; + for (size_t k = 0; k < kn; ++k) + { + const bpp_sig_commit_ref_t& bsc = sigs[k]; + const bpp_signature& sig = bsc.sig; + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(bsc.commitments.size() > 0, 2); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() > 0 && sig.L.size() == sig.R.size(), 3); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.r.is_reduced() && sig.s.is_reduced() && sig.delta.is_reduced(), 4); + + intermediate_element_t& interm = interms[k]; + interm.c_bpp_log2_m = calc_exp_power_of_2_upper_bound(bsc.commitments.size()); + if (c_bpp_log2_m_max < interm.c_bpp_log2_m) + c_bpp_log2_m_max = interm.c_bpp_log2_m; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() == interm.c_bpp_log2_m + c_bpp_log2_n, 5); + + interm.c_bpp_m = 1ull << interm.c_bpp_log2_m; + interm.c_bpp_mn = interm.c_bpp_m * c_bpp_n; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A0.from_public_key(sig.A0), 6); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A.from_public_key(sig.A), 7); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.B.from_public_key(sig.B), 8); + interm.L.resize(sig.L.size()); + interm.R.resize(sig.R.size()); + for (size_t i = 0; i < interm.L.size(); ++i) + { + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.L[i].from_public_key(sig.L[i]), 9); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.R[i].from_public_key(sig.R[i]), 10); + } + } + const size_t c_bpp_m_max = 1ull << c_bpp_log2_m_max; + const size_t c_bpp_mn_max = c_bpp_m_max * c_bpp_n; + const size_t c_bpp_LR_size_max = c_bpp_log2_m_max + c_bpp_log2_n; + + + // + // prepare stuff + // + /* + std::vector g(c_bpp_mn_max), h(c_bpp_mn_max); + for (size_t i = 0; i < c_bpp_mn_max; ++i) + { + g[i] = CT::get_generator(false, i); + h[i] = CT::get_generator(true, i); + } + */ + + scalar_vec_t batch_for_inverse; + batch_for_inverse.reserve(kn + kn * c_bpp_LR_size_max); + + + for (size_t k = 0; k < kn; ++k) + { + DBG_PRINT(ENDL << "SIG #" << k); + const bpp_sig_commit_ref_t& bsc = sigs[k]; + const bpp_signature& sig = bsc.sig; + intermediate_element_t& interm = interms[k]; + + // restore y and z + // using e as Fiat-Shamir transcript + scalar_t e = CT::get_initial_transcript(); + DBG_PRINT("initial transcript: " << e); + hash_helper_t::hs_t hsc; + CT::update_transcript(hsc, e, bsc.commitments); + // calculate scalar challenges y and z + hsc.add_scalar(e); + hsc.add_pub_key(sig.A0); + hsc.assign_calc_hash(interm.y); + interm.z = hash_helper_t::hs(interm.y); + interm.z_sq = interm.z * interm.z; + DBG_VAL_PRINT(interm.y); + DBG_VAL_PRINT(interm.z); + e = interm.z; // transcript for further steps + + interm.inv_y_offset = batch_for_inverse.size(); + batch_for_inverse.push_back(interm.y); + interm.inv_e_offset = batch_for_inverse.size(); + + interm.e.resize(sig.L.size()); + interm.e_sq.resize(sig.L.size()); + + for (size_t i = 0; i < sig.L.size(); ++i) + { + hsc.add_scalar(e); + hsc.add_pub_key(sig.L[i]); + hsc.add_pub_key(sig.R[i]); + hsc.assign_calc_hash(e); + interm.e[i] = e; + interm.e_sq[i] = e * e; + DBG_PRINT("e[" << i << "]: " << e); + batch_for_inverse.push_back(e); + } + + hsc.add_scalar(e); + hsc.add_pub_key(sig.A); + hsc.add_pub_key(sig.B); + hsc.assign_calc_hash(interm.e_final); + interm.e_final_sq = interm.e_final * interm.e_final; + DBG_VAL_PRINT(interm.e_final); + } + + batch_for_inverse.invert(); + + // Notation: + // 1_vec ^ n = (1, 1, 1, ..., 1) + // 2_vec ^ n = (2^0, 2^1, 2^2, ..., 2^(n-1)) + // -1_vec ^ n = ((-1)^0, (-1)^1, (-1)^2, ... (-1)^(n-1)) = (1, -1, 1, -1, ...) + // y<^n = (y^n, y^(n-1), ..., y^1) + // y>^n = (y^1, y^2, ..., y^n) + + // from page 13, Fig 1: + // Verifier outputs Accept IFF the following equality holds (single proof): + // P^e^2 * A^e * B == g ^ (r' e) * h ^ (s' e) * G ^ (r' y s') * H ^ delta' + // (where g and h are calculated in each round) + // The same equation in additive notation: + // e^2 * P + e * A + B == (r' * e) * g + (s' * e) * h + (r' y s') * G + delta' * H + // <=> + // (r' * e) * g + (s' * e) * h + (r' y s') * G + delta' * H - e^2 * P - e * A - B == 0 (*) + // where A, B, r', s', delta' is taken from the signature + // and P_{k+1} = e^2 * L_k + P_k + e^-2 * R_k for all rounds + // + // from page 18, Fig 3: + // P and V computes: + // A_hat = A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + + // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + + // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G + // (calculated once) + // + // As suggested in Section 6.1 "Practical Optimizations": + // 1) g and h exponentianions can be optimized in order not to be calculated at each round as the following (page 20): + // + // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta' * H - + // - e^2 * A_hat + // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) + // - e * A - B = 0 (**) + // + // where: + // g, h - vector of fixed generators + // s_vec_i = y^(1-i) * PROD{j=1..log(n)}(e_j ^ b(i,j)) + // s'_vec_i = PROD{j=1..log(n)}(e_j ^ -b(i,j)) + // b(i, j) = { 2 * ((1<<(j-1)) & (i-1)) - 1) (counting both from 1) (page 20) + // b(i, j) = { 2 * ((1< + + // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta' * H - + // - e^2 * (A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + + // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + + // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G + // ) + // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) + // - e * A - B = 0 + + // => + + // (for single signature) + // + // (r' * e * s_vec - e^2 * (- 1_vec^(mn) * z)) * g | these are + // + (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) * h | fixed generators + // + (r' y s' - e^2 * ((z - z^2)*SUM(y^>mn) - z*y^(mn+1)*SUM(d)) * G | across all + // + delta' * H | the signatures + // + // - e^2 * A0 + // - e^2 * y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j)) + // - e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) + // - e * A - B = 0 (***) + // + // All (***) will be muptiplied by random weightning factor and then summed up. + + // Calculate cummulative sclalar multiplicand for fixed generators across all the sigs. + scalar_vec_t g_scalars; + g_scalars.resize(c_bpp_mn_max, 0); + scalar_vec_t h_scalars; + h_scalars.resize(c_bpp_mn_max, 0); + scalar_t G_scalar = 0; + scalar_t H_scalar = 0; + point_t summand = c_point_0; + + for (size_t k = 0; k < kn; ++k) + { + DBG_PRINT(ENDL << "SIG #" << k); + const bpp_sig_commit_ref_t& bsc = sigs[k]; + const bpp_signature& sig = bsc.sig; + intermediate_element_t& interm = interms[k]; + + // random weightning factor for speed-optimized batch verification (preprint page 20) + const scalar_t rwf = scalar_t::random(); + DBG_PRINT("rwf: " << rwf); + + // prepare d vector (see also d structure description in proof function) + scalar_mat_t d(interm.c_bpp_mn); + d(0, 0) = interm.z_sq; + // first row + for (size_t i = 1; i < interm.c_bpp_m; ++i) + d(i, 0) = d(i - 1, 0) * interm.z_sq; + // all rows + for (size_t j = 1; j < c_bpp_n; ++j) + for (size_t i = 0; i < interm.c_bpp_m; ++i) + d(i, j) = d(i, j - 1) + d(i, j - 1); + // sum(d) (see also note in proof function for this) + static const scalar_t c_scalar_2_power_n_minus_1 = { 0xffffffffffffffff, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }; + const scalar_t sum_d = c_scalar_2_power_n_minus_1 * sum_of_powers(interm.z_sq, interm.c_bpp_log2_m); + + DBG_PRINT("Hs(d): " << d.calc_hs()); + DBG_PRINT("sum(d): " << sum_d); + + const scalar_t& y_inv = batch_for_inverse[interm.inv_y_offset]; + auto get_e_inv = [&](size_t i) { return batch_for_inverse[interm.inv_e_offset + i]; }; // i belongs to [0; L.size()-1] + + // prepare s_vec (unlike the paper here we moved y-component out of s_vec for convenience, so s_vec'[x] = s_vec[~x & (MN-1)]) + // complexity (sc_mul's): MN+2*log2(MN)-2 + // the idea is the following: + // s_vec[00000b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^-1 * (e_1)^-1 * (e_0)^-1 + // s_vec[00101b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^+1 * (e_1)^-1 * (e_0)^+1 + const size_t log2_mn = sig.L.size(); // at the beginning we made sure that sig.L.size() == c_bpp_log2_m + c_bpp_log2_n + scalar_vec_t s_vec(interm.c_bpp_mn); + s_vec[0] = get_e_inv(0); + for (size_t i = 1; i < log2_mn; ++i) + s_vec[0] *= get_e_inv(i); // s_vec[0] = (e_0)^-1 * (e_1)^-1 * .. (e_{log2_mn-1})^-1 + DBG_PRINT("[0] " << s_vec[0]); + for (size_t i = 1; i < interm.c_bpp_mn; ++i) + { + size_t base_el_index = i & (i - 1); // base element index: 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10... base element differs in one bit (0) from the current one (1) + size_t bit_index = log2_mn - calc_lsb_32((uint32_t)i) - 1; // the bit index where current element has the difference with the base + s_vec[i] = s_vec[base_el_index] * interm.e_sq[bit_index]; // (e_j)^-1 * (e_j)^2 = (e_j)^+1 + DBG_PRINT("[" << i << "] " << " " << base_el_index << ", " << bit_index << " : " << s_vec[i]); + } + + // prepare y_inv vector + scalar_vec_t y_inverse_powers(interm.c_bpp_mn); + y_inverse_powers[0] = 1; + for (size_t i = 1; i < interm.c_bpp_mn; ++i) + y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inv; + + // y^(mn+1) + scalar_t y_power_mnp1 = interm.y; + for (size_t i = 0; i < log2_mn; ++i) + y_power_mnp1 *= y_power_mnp1; + y_power_mnp1 *= interm.y; + DBG_VAL_PRINT(y_power_mnp1); + + // now calculate all multiplicands for common generators + + // g vector multiplicands: + // rwf * (r' * e * (1, y^-1, y^-2, ...) o s_vec + e^2 * z) = + // rwf * r' * e * ((1, y^-1, ...) o s_vec) + rwf * e^2 * z * (1, 1, ...) + scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; + scalar_t rwf_r_e = rwf * interm.e_final * sig.r; + for (size_t i = 0; i < interm.c_bpp_mn; ++i) + g_scalars[i] += rwf_r_e * y_inverse_powers[i] * s_vec[i] + rwf_e_sq_z; + + DBG_PRINT("Hs(g_scalars): " << g_scalars.calc_hs()); + + // h vector multiplicands: + // rwf * (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) + // rwf * s' * e * s'_vec - rwf * e^2 * z * (1, 1...) - rwf * e^2 * (d o y<^(mn)) + //scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; + scalar_t rwf_s_e = rwf * sig.s * interm.e_final; + scalar_t rwf_e_sq_y = rwf * interm.e_final_sq * interm.y; + for (size_t i = interm.c_bpp_mn - 1; i != SIZE_MAX; --i) + { + h_scalars[i] += rwf_s_e * s_vec[interm.c_bpp_mn - 1 - i] - rwf_e_sq_z - rwf_e_sq_y * d[i]; + rwf_e_sq_y *= interm.y; + } + + DBG_PRINT("Hs(h_scalars): " << h_scalars.calc_hs()); + + // G point multiplicands: + // rwf * (r' y s' - e ^ 2 * ((z - z ^ 2)*SUM(y^>mn) - z * y^(mn+1) * SUM(d)) = + // = rwf * r' y s' - rwf * e^2 * (z - z ^ 2)*SUM(y^>mn) + rwf * e^2 * z * y^(mn+1) * SUM(d) + G_scalar += rwf * sig.r * interm.y * sig.s + rwf_e_sq_y * sum_d * interm.z; + G_scalar -= rwf * interm.e_final_sq * (interm.z - interm.z_sq) * sum_of_powers(interm.y, log2_mn); + DBG_PRINT("sum_y: " << sum_of_powers(interm.y, log2_mn)); + DBG_PRINT("G_scalar: " << G_scalar); + + // H point multiplicands: + // rwf * delta + H_scalar += rwf * sig.delta; + DBG_PRINT("H_scalar: " << H_scalar); + + // uncommon generators' multiplicands + point_t summand_8 = c_point_0; // this summand to be multiplied by 8 before adding to the main summand + // - rwf * e^2 * A0 + summand_8 -= rwf * interm.e_final_sq * interm.A0; + DBG_PRINT("A0_scalar: " << c_scalar_Lm1 * interm.e_final_sq * rwf); + + // - rwf * e^2 * y^(mn+1) * (SUM{j=1..m} (z^2)^j * V_j)) + scalar_t e_sq_y_mn1_z_sq_power = rwf * interm.e_final_sq * y_power_mnp1; + for (size_t j = 0; j < bsc.commitments.size(); ++j) + { + e_sq_y_mn1_z_sq_power *= interm.z_sq; + summand_8 -= e_sq_y_mn1_z_sq_power * bsc.commitments[j]; + DBG_PRINT("V_scalar[" << j << "]: " << c_scalar_Lm1 * e_sq_y_mn1_z_sq_power); + } + + // - rwf * e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) + scalar_t rwf_e_sq = rwf * interm.e_final_sq; + for (size_t j = 0; j < log2_mn; ++j) + { + summand_8 -= rwf_e_sq * (interm.e_sq[j] * interm.L[j] + get_e_inv(j) * get_e_inv(j) * interm.R[j]); + DBG_PRINT("L_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * interm.e_sq[j]); + DBG_PRINT("R_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * get_e_inv(j) * get_e_inv(j)); + } + + // - rwf * e * A - rwf * B = 0 + summand_8 -= rwf * interm.e_final * interm.A + rwf * interm.B; + DBG_PRINT("A_scalar: " << c_scalar_Lm1 * rwf * interm.e_final); + DBG_PRINT("B_scalar: " << c_scalar_Lm1 * rwf); + + summand_8.modify_mul8(); + summand += summand_8; + } + + point_t GH_exponents = c_point_0; + CT::calc_pedersen_commitment(G_scalar, H_scalar, GH_exponents); + bool result = multiexp_and_check_being_zero(g_scalars, h_scalars, summand + GH_exponents); + if (result) + DBG_PRINT(ENDL << " . . . . bpp_verify() -- SUCCEEDED!!!" << ENDL); + return result; +#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + } + +} // namespace crypto diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index e60e5b6f..b2bae2b9 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -3816,12 +3816,14 @@ namespace currency const crypto::hash& m_tx_id; const crypto::hash& m_bl_id; const uint64_t m_bl_height; - add_transaction_input_visitor(blockchain_storage& bcs, blockchain_storage::key_images_container& m_db_spent_keys, const crypto::hash& tx_id, const crypto::hash& bl_id, const uint64_t bl_height) : + uint64_t &m_mixins_count; + add_transaction_input_visitor(blockchain_storage& bcs, blockchain_storage::key_images_container& m_db_spent_keys, const crypto::hash& tx_id, const crypto::hash& bl_id, const uint64_t bl_height, uint64_t& mixins_count) : m_bcs(bcs), m_db_spent_keys(m_db_spent_keys), m_tx_id(tx_id), m_bl_id(bl_id), - m_bl_height(bl_height) + m_bl_height(bl_height), + m_mixins_count(mixins_count) {} bool operator()(const txin_to_key& in) const { @@ -3846,7 +3848,8 @@ namespace currency return false; } } - + if (m_mixins_count < in.key_offsets.size()) + m_mixins_count = in.key_offsets.size(); return true; } bool operator()(const txin_htlc& in) const @@ -3896,11 +3899,11 @@ bool blockchain_storage::add_transaction_from_block(const transaction& tx, const process_blockchain_tx_attachments(tx, bl_height, bl_id, timestamp); TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_process_attachment); - + uint64_t mixins_count = 0; TIME_MEASURE_START_PD(tx_process_inputs); for(const txin_v& in : tx.vin) { - if(!boost::apply_visitor(add_transaction_input_visitor(*this, m_db_spent_keys, tx_id, bl_id, bl_height), in)) + if(!boost::apply_visitor(add_transaction_input_visitor(*this, m_db_spent_keys, tx_id, bl_id, bl_height, mixins_count), in)) { LOG_ERROR("critical internal error: add_transaction_input_visitor failed. but key_images should be already checked"); purge_transaction_keyimages_from_blockchain(tx, false); @@ -3913,6 +3916,13 @@ bool blockchain_storage::add_transaction_from_block(const transaction& tx, const } } TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_process_inputs); + if (need_to_profile && mixins_count > 0) + { + m_performance_data.tx_mixin_count.push(mixins_count); +#ifdef _DEBUG + LOG_PRINT_L0("[TX_MIXINS]: " << mixins_count); +#endif + } //check if there is already transaction with this hash TIME_MEASURE_START_PD(tx_check_exist); diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index 5c3b995f..7cb02c41 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -73,33 +73,35 @@ namespace currency epee::math_helper::average target_calculating_calc; //tx processing zone - epee::math_helper::average tx_check_inputs_time; - epee::math_helper::average tx_add_one_tx_time; - epee::math_helper::average tx_process_extra; - epee::math_helper::average tx_process_attachment; - epee::math_helper::average tx_process_inputs ; - epee::math_helper::average tx_push_global_index; - epee::math_helper::average tx_check_exist; - epee::math_helper::average tx_print_log; - epee::math_helper::average tx_prapare_append; + epee::math_helper::average tx_check_inputs_time; + epee::math_helper::average tx_add_one_tx_time; + epee::math_helper::average tx_process_extra; + epee::math_helper::average tx_process_attachment; + epee::math_helper::average tx_process_inputs ; + epee::math_helper::average tx_push_global_index; + epee::math_helper::average tx_check_exist; + epee::math_helper::average tx_print_log; + epee::math_helper::average tx_prapare_append; - epee::math_helper::average tx_append_time; - epee::math_helper::average tx_append_rl_wait; - epee::math_helper::average tx_append_is_expired; + epee::math_helper::average tx_append_time; + epee::math_helper::average tx_append_rl_wait; + epee::math_helper::average tx_append_is_expired; - epee::math_helper::average tx_store_db; + epee::math_helper::average tx_store_db; - epee::math_helper::average tx_check_inputs_prefix_hash; - epee::math_helper::average tx_check_inputs_attachment_check; - epee::math_helper::average tx_check_inputs_loop; - epee::math_helper::average tx_check_inputs_loop_kimage_check; - epee::math_helper::average tx_check_inputs_loop_ch_in_val_sig; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_get_item_size; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_relative_to_absolute; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop_get_subitem; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop_find_tx; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop_handle_output; + epee::math_helper::average tx_check_inputs_prefix_hash; + epee::math_helper::average tx_check_inputs_attachment_check; + epee::math_helper::average tx_check_inputs_loop; + epee::math_helper::average tx_check_inputs_loop_kimage_check; + epee::math_helper::average tx_check_inputs_loop_ch_in_val_sig; + epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_get_item_size; + epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_relative_to_absolute; + epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop; + epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop_get_subitem; + epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop_find_tx; + epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop_handle_output; + + epee::math_helper::average tx_mixin_count; //TODO: move this to suitable place or remove it all diff --git a/src/pch/stdafx.h b/src/pch/stdafx.h index 7aec3431..76afcc62 100644 --- a/src/pch/stdafx.h +++ b/src/pch/stdafx.h @@ -66,8 +66,6 @@ POP_VS_WARNINGS #include #include #include -#include -#include #include #include #include diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 6238bed6..2c287ed7 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -210,6 +210,7 @@ namespace currency res.performance_data.tx_append_time = pd.tx_append_time.get_avg(); res.performance_data.tx_append_rl_wait = pd.tx_append_rl_wait.get_avg(); res.performance_data.tx_append_is_expired = pd.tx_append_is_expired.get_avg(); + res.performance_data.tx_mixin_count = pd.tx_mixin_count.get_avg(); res.performance_data.tx_store_db = pd.tx_store_db.get_avg(); diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 2ef811ac..531cbe74 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -500,6 +500,8 @@ namespace currency uint64_t tx_print_log; uint64_t tx_prapare_append; + uint64_t tx_mixin_count; + uint64_t tx_store_db; @@ -547,6 +549,7 @@ namespace currency KV_SERIALIZE(tx_store_db) KV_SERIALIZE(tx_print_log) KV_SERIALIZE(tx_prapare_append) + KV_SERIALIZE(tx_mixin_count) KV_SERIALIZE(tx_check_inputs_prefix_hash) KV_SERIALIZE(tx_check_inputs_attachment_check) diff --git a/src/version.h.in b/src/version.h.in index 65a5944d..cfee72bd 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -5,9 +5,9 @@ #define PROJECT_MAJOR_VERSION "1" #define PROJECT_MINOR_VERSION "2" -#define PROJECT_REVISION "0" +#define PROJECT_REVISION "1" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 123 +#define PROJECT_VERSION_BUILD_NO 124 #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 "]" diff --git a/src/wallet/plain_wallet_api.cpp b/src/wallet/plain_wallet_api.cpp index b7a91e8f..4b8a8fd6 100644 --- a/src/wallet/plain_wallet_api.cpp +++ b/src/wallet/plain_wallet_api.cpp @@ -95,21 +95,21 @@ namespace plain_wallet std::string get_wallets_folder() { #ifdef WIN32 - return ""; + std::string path = get_bundle_working_dir() + "/" + WALLETS_FOLDER_NAME + "/"; #else std::string path = get_bundle_working_dir() + "/" + WALLETS_FOLDER_NAME + "/"; - return path; #endif // WIN32 + return path; } std::string get_app_config_folder() { #ifdef WIN32 - return ""; + std::string path = get_bundle_working_dir() + "/" + APP_CONFIG_FOLDER + "/"; #else std::string path = get_bundle_working_dir() + "/" + APP_CONFIG_FOLDER + "/"; - return path; #endif // WIN32 + return path; } #ifdef ANDROID_BUILD class android_logger : public log_space::ibase_log_stream diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 9c8c9c33..d0456a00 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2389,10 +2389,6 @@ bool wallet2::deinit() bool wallet2::clear() { reset_all(); - //currency::block b; - //currency::generate_genesis_block(b); - m_chain.clear(); - //m_blockchain.push_back(get_block_hash(b)); return true; } //---------------------------------------------------------------------------------------------------- @@ -2666,6 +2662,7 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password) bool need_to_resync = false; if (wbh.m_ver == 1000) { + // old WALLET_FILE_BINARY_HEADER_VERSION version means no encryption need_to_resync = !tools::portable_unserialize_obj_from_stream(*this, data_file); } else diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index f1ab885e..6723795c 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -707,7 +707,7 @@ namespace tools if (ver < 149) { - WLT_LOG_MAGENTA("Wallet file truncated due to old version", LOG_LEVEL_0); + WLT_LOG_MAGENTA("Wallet file truncated due to old version: " << ver, LOG_LEVEL_0); return; } diff --git a/src/wallet/wallet_helpers.h b/src/wallet/wallet_helpers.h index 8e37d856..9ebf9137 100644 --- a/src/wallet/wallet_helpers.h +++ b/src/wallet/wallet_helpers.h @@ -37,6 +37,8 @@ namespace tools result.require_password = false; result.hash_sum_matched = false; result.syntax_correct = acc.restore_from_tracking_seed(seed_phrase); + if (result.syntax_correct) + result.tracking = true; } else { diff --git a/src/wallet/wallet_public_structs_defs.h b/src/wallet/wallet_public_structs_defs.h index c393c1c5..afcddc49 100644 --- a/src/wallet/wallet_public_structs_defs.h +++ b/src/wallet/wallet_public_structs_defs.h @@ -188,11 +188,13 @@ namespace wallet_public bool syntax_correct; bool require_password; bool hash_sum_matched; + bool tracking; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(syntax_correct) KV_SERIALIZE(require_password) KV_SERIALIZE(hash_sum_matched) + KV_SERIALIZE(tracking) END_KV_SERIALIZE_MAP() }; diff --git a/tests/functional_tests/crypto_tests.cpp b/tests/functional_tests/crypto_tests.cpp index ba4313fd..86d00401 100644 --- a/tests/functional_tests/crypto_tests.cpp +++ b/tests/functional_tests/crypto_tests.cpp @@ -14,6 +14,7 @@ #include "currency_core/difficulty.h" #include "crypto/crypto-sugar.h" +#include "crypto/range_proofs.h" using namespace crypto; @@ -1096,6 +1097,52 @@ TEST(crypto, point_basics) return true; } +TEST(crypto, neg_identity) +{ + point_t z = c_point_0; // 0 group element (identity) + public_key z_pk = z.to_public_key(); // pub key, corresponding to 0 ge (pub key is not zero bitwise) + public_key z_neg_pk = z_pk; + ((unsigned char*)&z_neg_pk)[31] = 0x80; // set sign bit manually + std::cout << "-Identity = " << z_pk << ENDL; + point_t z_neg; + ASSERT_FALSE(z_neg.from_public_key(z_neg_pk)); // negative identity should not be loaded + + key_image z_ki; + memset(&z_ki, 0, sizeof(z_ki)); + ((unsigned char*)&z_ki)[00] = 0x01; // y = 1 + + ASSERT_TRUE(validate_key_image(z_ki)); + + key_image z_neg_ki = z_ki; + ((unsigned char*)&z_neg_ki)[31] = 0x80; // set sign bit manually + + ASSERT_FALSE(validate_key_image(z_neg_ki)); // negative identity should not be loaded + + + // also do zero-byte pub key / key image checks + + public_key zzz_pk; + memset(&zzz_pk, 0, sizeof public_key); + + ASSERT_TRUE(check_key(zzz_pk)); + + point_t zzz; + ASSERT_TRUE(zzz.from_public_key(zzz_pk)); + ASSERT_FALSE(zzz.is_in_main_subgroup()); + + key_image zzz_ki; + memset(&zzz_ki, 0, sizeof key_image); + + ASSERT_FALSE(validate_key_image(zzz_ki)); + + point_t zzz2; + ASSERT_TRUE(zzz2.from_key_image(zzz_ki)); + ASSERT_FALSE(zzz2.is_in_main_subgroup()); + ASSERT_EQ(zzz, zzz2); + + return true; +} + TEST(crypto, scalar_reciprocal) { int64_t test_nums[] = { 1, 2, 10 }; @@ -1551,6 +1598,30 @@ TEST(crypto, hex_tools) return true; } + +TEST(crypto, calc_lsb_32) +{ + auto local_calc_lsb = [](uint32_t v) { + uint8_t r = 0; + while (v != 0 && (v & 1) == 0) + { + v >>= 1; + ++r; + } + return r; + }; + + for (uint32_t x = 0; x < UINT32_MAX; ++x) + { + if (x % 10000000 == 0) + std::cout << x << ENDL; + ASSERT_EQ((int)local_calc_lsb(x), (int)calc_lsb_32(x)); + } + ASSERT_EQ((int)local_calc_lsb(UINT32_MAX), (int)calc_lsb_32(UINT32_MAX)); + + return true; +} + // // test's runner // diff --git a/tests/functional_tests/plain_wallet_tests.cpp b/tests/functional_tests/plain_wallet_tests.cpp index 457dcefc..f6efe29f 100644 --- a/tests/functional_tests/plain_wallet_tests.cpp +++ b/tests/functional_tests/plain_wallet_tests.cpp @@ -31,17 +31,29 @@ struct try_pull_result_open_response void run_plain_wallet_api_test() { LOG_PRINT_L0("Creating instance..."); - std::string s = plain_wallet::init("195.201.107.230", "11211", boost::dll::program_location().parent_path().string(), 1); - s = plain_wallet::get_export_private_info("E:\\tmp\\check_export"); - std::string key = plain_wallet::generate_random_key(10); - std::string test_data = "1234567890 test test "; - std::string res = plain_wallet::set_appconfig(test_data, key); - std::string test_data2 = plain_wallet::get_appconfig(key); - if (test_data2 != test_data) - { - LOG_ERROR("Error"); - } + //plain_wallet::set_bundle_working_dir("E:\\tmp\\check_export"); + std::string s = plain_wallet::init("195.201.107.230", "33333", boost::dll::program_location().parent_path().string(), 1); + //s = plain_wallet::get_export_private_info("E:\\tmp\\check_export"); + + + std::string res = plain_wallet::sync_call("get_seed_phrase_info", 0, "{\"seed_phrase\":\"aZxat4HAWriVQ3enkGcVsrZRdMseAJswG3CSEwTqZS246VsFQ53w26eZstYsu1jWE74Atz9ajLxFnBsVTafncWNH5SMv4zHFaTS:1780c4d5dd7e97cc4a75ea8baa7977d12ef948b9a6dddc2a9a37e5e22ac7180e:1599495055\"}"); + + + res = plain_wallet::restore("footstep knowledge fur capture honey minute carefully peaceful lovely crawl lunch government nightmare friendship myself sign possibly plan flower depression bread rainbow wrong hardly dark chest", + "test_wall2.zan", "111", ""); + + + epee::misc_utils::sleep_no_w(10000000); + + //std::string key = plain_wallet::generate_random_key(10); + //std::string test_data = "1234567890 test test "; + //std::string res = plain_wallet::set_appconfig(test_data, key); + //std::string test_data2 = plain_wallet::get_appconfig(key); + //if (test_data2 != test_data) + //{ + // LOG_ERROR("Error"); + //} return; //std::string fres = plain_wallet::get_logs_buffer(); //std::string fres2 = plain_wallet::truncate_log(); diff --git a/utils/configure_local_paths_msvs2019.cmd b/utils/configure_local_paths_msvs2019.cmd new file mode 100644 index 00000000..742774bf --- /dev/null +++ b/utils/configure_local_paths_msvs2019.cmd @@ -0,0 +1,8 @@ +@echo off +rem +rem This file contains local path settings for your own personal dev environment. +rem Rename to configure_local_paths.cmd and do not commit. +rem + +set QT_PREFIX_PATH=C:\dev\_sdk\Qt5.15.2\5.15.2 +set BOOST_ROOT=C:\dev\_sdk\boost_1_76_0 diff --git a/utils/configure_win64_msvs2019_gui_testnet.cmd b/utils/configure_win64_msvs2019_gui_testnet.cmd new file mode 100644 index 00000000..0fd0d89d --- /dev/null +++ b/utils/configure_win64_msvs2019_gui_testnet.cmd @@ -0,0 +1,7 @@ +call configure_local_paths_msvs2019.cmd + +cd .. +@mkdir build_msvc2019_64_tn +cd build_msvc2019_64_tn + +cmake -D TESTNET=TRUE -D USE_PCH=TRUE -D BUILD_TESTS=TRUE -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2019_64 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.2" -G "Visual Studio 16 2019" -A x64 -T host=x64 ".." diff --git a/utils/docker/Dockerfile b/utils/docker/Dockerfile index 9176be64..08f2ffe1 100644 --- a/utils/docker/Dockerfile +++ b/utils/docker/Dockerfile @@ -46,7 +46,7 @@ RUN curl https://github.com/Kitware/CMake/releases/download/v3.15.5/cmake-3.15.5 # Boost 1.68 -RUN curl https://dl.bintray.com/boostorg/release/1.68.0/source/boost_1_68_0.tar.bz2 -OL &&\ +RUN curl https://boostorg.jfrog.io/artifactory/main/release/1.68.0/source/boost_1_68_0.tar.bz2 -OL &&\ echo '7f6130bc3cf65f56a618888ce9d5ea704fa10b462be126ad053e80e553d6d8b7 boost_1_68_0.tar.bz2' | sha256sum -c - &&\ tar -xjf boost_1_68_0.tar.bz2 &&\ rm boost_1_68_0.tar.bz2 &&\ diff --git a/utils/munin_plugins/performance_transaction b/utils/munin_plugins/performance_transaction index 84748813..ff8f1c7d 100755 --- a/utils/munin_plugins/performance_transaction +++ b/utils/munin_plugins/performance_transaction @@ -5,7 +5,7 @@ case $1 in cat <<'EOM' graph_title performance_transactions graph_vlabel mcs -graph_category daemon +graph_category transactions tx_add_one_tx_time.label tx_add_one_tx_time tx_add_one_tx_time.draw LINE tx_append_time.label tx_append_time diff --git a/utils/munin_plugins/performance_transaction_inp b/utils/munin_plugins/performance_transaction_inp index 1feaf016..04da756e 100755 --- a/utils/munin_plugins/performance_transaction_inp +++ b/utils/munin_plugins/performance_transaction_inp @@ -5,7 +5,7 @@ case $1 in cat <<'EOM' graph_title performance_tranactions_inp graph_vlabel mcs -graph_category daemon.inp +graph_category transactions.inp tx_check_inputs_prefix_hash.label prefix_hash tx_check_inputs_prefix_hash.draw AREA tx_check_inputs_attachment_check.label attachment_check diff --git a/utils/munin_plugins/performance_transaction_inp_loop b/utils/munin_plugins/performance_transaction_inp_loop index e0b8f602..4cd5ebc8 100755 --- a/utils/munin_plugins/performance_transaction_inp_loop +++ b/utils/munin_plugins/performance_transaction_inp_loop @@ -5,7 +5,7 @@ case $1 in cat <<'EOM' graph_title performance_tranactions_inp.every_inp graph_vlabel mcs -graph_category daemon.inp +graph_category transactions.inp tx_check_inputs_loop_kimage_check.label kimage_check tx_check_inputs_loop_kimage_check.draw AREA tx_check_inputs_loop_ch_in_val_sig.label ch_in_val_sig diff --git a/utils/munin_plugins/performance_transaction_inp_loop_scan_loop b/utils/munin_plugins/performance_transaction_inp_loop_scan_loop index 9e95c2b1..537ccd18 100755 --- a/utils/munin_plugins/performance_transaction_inp_loop_scan_loop +++ b/utils/munin_plugins/performance_transaction_inp_loop_scan_loop @@ -5,7 +5,7 @@ case $1 in cat <<'EOM' graph_title performance_tranactions_inp.every_inp.every_key graph_vlabel mcs -graph_category daemon.inp +graph_category transactions.inp tx_check_inputs_loop_scan_outputkeys_loop_get_subitem.label get_subitem tx_check_inputs_loop_scan_outputkeys_loop_get_subitem.draw AREA tx_check_inputs_loop_scan_outputkeys_loop_find_tx.label find_tx diff --git a/utils/munin_plugins/tx_mixins_count b/utils/munin_plugins/tx_mixins_count new file mode 100755 index 00000000..0bee5984 --- /dev/null +++ b/utils/munin_plugins/tx_mixins_count @@ -0,0 +1,17 @@ +#!/bin/bash + +case $1 in + config) + cat <<'EOM' +graph_args --alt-autoscale +graph_title mixins +graph_vlabel mixins +graph_category transactions +mixins.label mixins + +EOM + exit 0;; +esac + +printf "mixins.value " +connectivity_tool --ip=127.0.0.1 --rpc-port=$ZANO_RPC_PORT --timeout=1000 --rpc-get-daemon-info --getinfo-flags-hex="0x0000000000010000" | grep tx_mixin_count | cut -d ' ' -f2