1
0
Fork 0
forked from lthn/blockchain

merge from develop

This commit is contained in:
cryptozoidberg 2021-06-11 21:59:50 +03:00
commit 2fb3b96c2b
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
10 changed files with 1075 additions and 46 deletions

View file

@ -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 <br>(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.18.1 |
| [Boost](https://www.boost.org/users/download/) | 1.56 | 1.68 | 1.69 |
| [Qt](https://download.qt.io/archive/qt/) (*only for GUI*) | 5.8.0 | 5.11.2 | 5.13.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.
<br />
### 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,7 @@ 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.
1. Building GUI:
@ -75,6 +93,8 @@ Recommended OS version: Ubuntu 18.04 LTS.
7. Look for the binaries in `build` folder
<br />
### Windows
Recommended OS version: Windows 7 x64.
1. Install required prerequisites (Boost, Qt, CMake).
@ -83,13 +103,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`
<br />
### 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` <br> `cd build` <br> `cmake ..` <br> `make`
@ -104,7 +128,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`

View file

@ -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<T, sizeof(T)>(&temp, t);
#endif

View file

@ -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
*/
@ -710,6 +717,146 @@ namespace crypto
}; // struct point_g_t
//
// vector of scalars
//
struct scalar_vec_t : public std::vector<scalar_t>
{
typedef std::vector<scalar_t> super_t;
scalar_vec_t() {}
scalar_vec_t(size_t n) : super_t(n) {}
scalar_vec_t(std::initializer_list<scalar_t> 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<size_t N>
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<scalar_t> 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
//
@ -901,4 +1048,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

View file

@ -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;
}

823
src/crypto/range_proofs.h Normal file
View file

@ -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<point_t>& 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<point_t> 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<public_key> L; // size = log_2(m * n)
std::vector<public_key> 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<typename CT>
bool bpp_gen(const std::vector<uint64_t>& values, const scalar_vec_t& masks, bpp_signature& sig, std::vector<point_t>& 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<c_bpp_n> 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<c_bpp_n> 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<point_t> 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 = <a1, ((y, y^2, ...) o b2)> -- 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 = <a2, ((y, y^2, ...) o b1)> * 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<typename CT>
bool multiexp_and_check_being_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand)
{
CHECK_AND_ASSERT_MES(g_scalars.size() < 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<point_t>& commitments)
: sig(sig)
, commitments(commitments)
{}
const bpp_signature& sig;
const std::vector<point_t>& commitments;
};
template<typename CT>
bool bpp_verify(const std::vector<bpp_sig_commit_ref_t>& sigs, uint8_t* p_err = nullptr)
{
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
if (!(cond)) { LOG_PRINT_RED("bpp_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \
if (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<point_t> L;
std::vector<point_t> R;
};
std::vector<intermediate_element_t> 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<point_t> 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<<j) & i) - 1) (counting both from 0)
//
// 2) we gonna aggregate all (**) for each round by multiplying them to a random weights and then sum up
// insert A_hat into (**) =>
// (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<c_bpp_n> 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<CT>(g_scalars, h_scalars, summand + GH_exponents);
if (result)
DBG_PRINT(ENDL << " . . . . bpp_verify() -- SUCCEEDED!!!" << ENDL);
return result;
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
}
} // namespace crypto

View file

@ -67,7 +67,6 @@ POP_VS_WARNINGS
#include <boost/serialization/vector.hpp>
#include <boost/serialization/version.hpp>
#include <boost/spirit/home/support/detail/endian/endian.hpp>
#include <boost/spirit/home/support/detail/math/fpclassify.hpp>
#include <boost/thread.hpp>
#include <boost/timer/timer.hpp>
#include <boost/type_traits/is_arithmetic.hpp>

View file

@ -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 == WALLET_FILE_BINARY_HEADER_VERSION_INITAL)
{
// old WALLET_FILE_BINARY_HEADER_VERSION version means no encryption
need_to_resync = !tools::portable_unserialize_obj_from_stream(*this, data_file);
WLT_LOG_L0("Detected format: WALLET_FILE_BINARY_HEADER_VERSION_INITAL(need_to_resync=" << need_to_resync << ")");
}

View file

@ -14,6 +14,7 @@
#include "currency_core/difficulty.h"
#include "crypto/crypto-sugar.h"
#include "crypto/range_proofs.h"
using namespace crypto;
@ -1551,6 +1552,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
//

View file

@ -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 &&\

View file

@ -3,12 +3,11 @@ curr_path=${BASH_SOURCE%/*}
version_file_path=../src/version.h.in
pushd $curr_path
# clear old local changes if any
git checkout -- ../src/*
git pull --ff-only
if [ $? -ne 0 ]; then
echo "Failed to pull"
popd
exit $?
fi
build_no_before=`cat $version_file_path | grep 'PROJECT_VERSION_BUILD_NO ' | awk {'print $3'}`
@ -19,15 +18,11 @@ build_no_after=`cat $version_file_path | grep 'PROJECT_VERSION_BUILD_NO ' | awk
echo "$build_no_before -> $build_no_after"
echo $(pwd -P)
git status
git commit -a -m"=== build number: $build_no_before -> $build_no_after ==="
git push
if [ $? -ne 0 ]; then
echo "Failed to push"
popd
exit $?
fi
echo "Build number was succesefully incremented."
popd