forked from lthn/blockchain
Merge branch 'develop' into cake
This commit is contained in:
commit
ecf1a7d487
87 changed files with 7093 additions and 580 deletions
|
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.1)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
PROJECT(Zano)
|
||||
|
||||
|
|
@ -194,8 +194,8 @@ else()
|
|||
endif()
|
||||
|
||||
|
||||
# If BOOST_ROOT is set, ignore system-wide Boost
|
||||
if(DEFINED ENV{BOOST_ROOT})
|
||||
# always use local Boost installation rather than the system-wide (unless ZANO_USE_SYSTEM_BOOST is defined for some reason, which is not recommended)
|
||||
if(NOT DEFINED ENV{ZANO_USE_SYSTEM_BOOST})
|
||||
set(Boost_NO_SYSTEM_PATHS ON)
|
||||
endif()
|
||||
|
||||
|
|
@ -221,6 +221,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
|||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
set(Boost_LIBRARY_DIRS "${Boost_LIBRARY_DIRS}/${CMAKE_ANDROID_ARCH_ABI}/")
|
||||
set(Boost_LIBRARIES "${Boost_LIBRARY_DIRS}libboost_system.a;${Boost_LIBRARY_DIRS}libboost_filesystem.a;${Boost_LIBRARY_DIRS}libboost_thread.a;${Boost_LIBRARY_DIRS}libboost_timer.a;${Boost_LIBRARY_DIRS}libboost_date_time.a;${Boost_LIBRARY_DIRS}libboost_chrono.a;${Boost_LIBRARY_DIRS}libboost_regex.a;${Boost_LIBRARY_DIRS}libboost_serialization.a;${Boost_LIBRARY_DIRS}libboost_atomic.a;${Boost_LIBRARY_DIRS}libboost_program_options.a")
|
||||
elseif(APPLE)
|
||||
find_package(Boost 1.71 REQUIRED COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options locale)
|
||||
else()
|
||||
find_package(Boost 1.70 REQUIRED COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options locale)
|
||||
endif()
|
||||
|
|
@ -244,7 +246,7 @@ elseif(NOT MSVC)
|
|||
endif()
|
||||
|
||||
if(BUILD_GUI)
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
endif()
|
||||
|
||||
|
|
|
|||
53
README.md
53
README.md
|
|
@ -42,18 +42,25 @@ Recommended OS versions: Ubuntu 20.04, 22.04 LTS.
|
|||
|
||||
sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git screen checkinstall zlib1g-dev mesa-common-dev libglu1-mesa-dev
|
||||
|
||||
2. Download and build Boost\
|
||||
(Assuming you have cloned Zano into the 'zano' folder. If you used a different location for Zano, edit line 4 accordingly.)
|
||||
2. Clone Zano into a local folder\
|
||||
(If for some reason you need to use alternative Zano branch, change 'master' to the required branch name.)
|
||||
|
||||
git clone --recursive https://github.com/hyle-team/zano.git -b master
|
||||
|
||||
In the following steps we assume that you cloned Zano into '~/zano' folder in your home directory.
|
||||
|
||||
3. Download and build Boost\
|
||||
(Assuming you have cloned Zano into the 'zano' folder. If you used a different location for Zano, **edit line 4** accordingly.)
|
||||
|
||||
curl -OL https://boostorg.jfrog.io/artifactory/main/release/1.70.0/source/boost_1_70_0.tar.bz2
|
||||
echo "430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778 boost_1_70_0.tar.bz2" | shasum -c && tar -xjf boost_1_70_0.tar.bz2
|
||||
rm boost_1_70_0.tar.bz2 && cd boost_1_70_0
|
||||
patch -p0 < ../zano/utils/boost_1.70_gcc_8.patch || cd ..
|
||||
./bootstrap.sh --with-libraries=system,filesystem,thread,date_time,chrono,regex,serialization,atomic,program_options,locale,timer,log
|
||||
./b2
|
||||
./b2 && cd ..
|
||||
Make sure that you see "The Boost C++ Libraries were successfully built!" message at the end.
|
||||
|
||||
3. Install Qt\
|
||||
4. Install Qt\
|
||||
(*GUI version only, skip this step if you're building server version*)
|
||||
|
||||
[*GUI version*]
|
||||
|
|
@ -64,18 +71,19 @@ Recommended OS versions: Ubuntu 20.04, 22.04 LTS.
|
|||
Then follow the instructions in Wizard. Don't forget to tick the WebEngine module checkbox!
|
||||
|
||||
|
||||
4. Install OpenSSL
|
||||
5. Install OpenSSL
|
||||
|
||||
We recommend installing OpenSSL v1.1.1w locally unless you would like to use the same version system-wide. Adjust the local path `/home/user/openssl` in the commands below according to your needs.
|
||||
We recommend installing OpenSSL v1.1.1w locally unless you would like to use the same version system-wide.\
|
||||
(Assuming that `$HOME` environment variable is set to your home directory. Otherwise, edit line 4 accordingly.)
|
||||
|
||||
curl -OL https://www.openssl.org/source/openssl-1.1.1w.tar.gz
|
||||
echo "cf3098950cb4d853ad95c0841f1f9c6d3dc102dccfcacd521d93925208b76ac8 openssl-1.1.1w.tar.gz" | shasum -c && tar xaf openssl-1.1.1w.tar.gz
|
||||
cd openssl-1.1.1w/
|
||||
./config --prefix=/home/user/openssl --openssldir=/home/user/openssl shared zlib
|
||||
make && make test && make install
|
||||
./config --prefix=$HOME/openssl --openssldir=$HOME/openssl shared zlib
|
||||
make && make test && make install && cd ..
|
||||
|
||||
|
||||
5. Set environment variables properly\
|
||||
6. [*OPTIONAL*] Set global environment variables for convenient use\
|
||||
For instance, by adding the following lines to `~/.bashrc`
|
||||
|
||||
[*server version*]
|
||||
|
|
@ -90,18 +98,27 @@ For instance, by adding the following lines to `~/.bashrc`
|
|||
export OPENSSL_ROOT_DIR=/home/user/openssl
|
||||
export QT_PREFIX_PATH=/home/user/Qt5.11.2/5.11.2/gcc_64
|
||||
|
||||
Make sure you've restarted your terminal session (by reopening the terminal window or reconnecting the server) to apply these changes.
|
||||
|
||||
6. Build the binaries
|
||||
1. Build daemon and simplewallet:
|
||||
|
||||
cd zano/ && make -j1
|
||||
or
|
||||
**NOTICE: Please edit the lines above according to your actual paths.**
|
||||
|
||||
**NOTICE 2:** Make sure you've restarted your terminal session (by reopening the terminal window or reconnecting the server) to apply these changes.
|
||||
|
||||
8. Build the binaries
|
||||
1. If you skipped step 6 and did not set the environment variables:
|
||||
|
||||
cd zano && mkdir build && cd build
|
||||
BOOST_ROOT=$HOME/boost_1_70_0 OPENSSL_ROOT_DIR=$HOME/openssl cmake ..
|
||||
make -j1 daemon simplewallet
|
||||
|
||||
2. If you set the variables in step 6:
|
||||
|
||||
cd zano && mkdir build && cd build
|
||||
cmake ..
|
||||
make -j1 daemon simplewallet
|
||||
|
||||
or simply:
|
||||
|
||||
cd zano && make -j1
|
||||
|
||||
**NOTICE**: If you are building on a machine with a relatively high amount of RAM or with the proper setting of virtual memory, then you can use `-j2` or `-j` option to speed up the building process. Use with caution.
|
||||
|
||||
**NOTICE 2**: If you'd like to build binaries for the testnet, use `cmake -D TESTNET=TRUE ..` instead of `cmake ..` .
|
||||
|
|
@ -111,12 +128,12 @@ For instance, by adding the following lines to `~/.bashrc`
|
|||
cd zano
|
||||
utils/build_script_linux.sh
|
||||
|
||||
7. Look for the binaries in `build` folder
|
||||
Look for the binaries in `build` folder
|
||||
|
||||
<br />
|
||||
|
||||
### Windows
|
||||
Recommended OS version: Windows 7 x64.
|
||||
Recommended OS version: Windows 7 x64, Windows 11 x64.
|
||||
1. Install required prerequisites (Boost, Qt, CMake, OpenSSL).
|
||||
2. Edit paths in `utils/configure_local_paths.cmd`.
|
||||
3. Run one of `utils/configure_win64_msvsNNNN_gui.cmd` according to your MSVC version.
|
||||
|
|
|
|||
|
|
@ -274,6 +274,21 @@ namespace misc_utils
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t get_avg() const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_lock);
|
||||
if (!queued_items.size())
|
||||
return 0;
|
||||
|
||||
uint64_t summ = 0;
|
||||
for (const auto& item : queued_items)
|
||||
{
|
||||
summ += *item.first;
|
||||
}
|
||||
|
||||
return summ / queued_items.size();
|
||||
}
|
||||
|
||||
template<typename key_t, typename associated_data_t>
|
||||
friend std::ostream & operator<< (std::ostream &out, median_helper<key_t, associated_data_t> const &mh);
|
||||
}; // class median_helper
|
||||
|
|
@ -292,26 +307,25 @@ namespace misc_utils
|
|||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
template<class type_vec_type>
|
||||
type_vec_type median(std::vector<type_vec_type> &v)
|
||||
template<typename container_t>
|
||||
typename container_t::value_type median(container_t &v)
|
||||
{
|
||||
//CRITICAL_REGION_LOCAL(m_lock);
|
||||
typename container_t::value_type median{};
|
||||
if(v.empty())
|
||||
return boost::value_initialized<type_vec_type>();
|
||||
return median;
|
||||
if(v.size() == 1)
|
||||
return v[0];
|
||||
|
||||
size_t n = (v.size()) / 2;
|
||||
std::sort(v.begin(), v.end());
|
||||
//nth_element(v.begin(), v.begin()+n-1, v.end());
|
||||
if(v.size()%2)
|
||||
{//1, 3, 5...
|
||||
return v[n];
|
||||
}else
|
||||
{//2, 4, 6...
|
||||
return (v[n-1] + v[n])/2;
|
||||
auto median_it = v.begin() + v.size() / 2;
|
||||
std::nth_element(v.begin(), median_it, v.end());
|
||||
median = *median_it;
|
||||
if (v.size() % 2 == 0)
|
||||
{
|
||||
auto max_it = std::max_element(v.begin(), median_it); // it's garanteed that after nth_element() the necessary element is in this interval
|
||||
median = (median + *max_it) / 2; // average of [size/2-1] and [size/2] elements
|
||||
}
|
||||
|
||||
return median;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2023 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
|
@ -115,27 +115,6 @@ namespace crypto
|
|||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct CLSAG_GGXG_signature_serialized : public CLSAG_GGXG_signature
|
||||
{
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(c)
|
||||
FIELD((std::vector<scalar_t>&)(r_g))
|
||||
FIELD((std::vector<scalar_t>&)(r_x))
|
||||
FIELD(K1)
|
||||
FIELD(K2)
|
||||
FIELD(K3)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(c)
|
||||
BOOST_SERIALIZE((std::vector<scalar_t>&)(r_g))
|
||||
BOOST_SERIALIZE((std::vector<scalar_t>&)(r_x))
|
||||
BOOST_SERIALIZE(K1)
|
||||
BOOST_SERIALIZE(K2)
|
||||
BOOST_SERIALIZE(K3)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct CLSAG_GGXXG_signature_serialized : public CLSAG_GGXXG_signature
|
||||
{
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#define API_RETURN_CODE_WALLET_WRONG_ID "WALLET_WRONG_ID"
|
||||
#define API_RETURN_CODE_WALLET_WATCH_ONLY_NOT_SUPPORTED "WALLET_WATCH_ONLY_NOT_SUPPORTED"
|
||||
#define API_RETURN_CODE_WALLET_AUDITABLE_NOT_SUPPORTED "WALLET_AUDITABLE_NOT_SUPPORTED"
|
||||
#define API_RETURN_CODE_WALLET_FEE_TOO_LOW "API_RETURN_CODE_WALLET_FEE_TOO_LOW"
|
||||
#define API_RETURN_CODE_FILE_NOT_FOUND "FILE_NOT_FOUND"
|
||||
#define API_RETURN_CODE_ALREADY_EXISTS "ALREADY_EXISTS"
|
||||
#define API_RETURN_CODE_CANCELED "CANCELED"
|
||||
|
|
@ -42,4 +43,4 @@
|
|||
#define API_RETURN_CODE_TX_REJECTED "TX_REJECTED"
|
||||
#define API_RETURN_CODE_HTLC_ORIGIN_HASH_MISSMATCHED "HTLC_ORIGIN_HASH_MISSMATCHED"
|
||||
#define API_RETURN_CODE_WRAP "WRAP"
|
||||
#define API_RETURN_CODE_MISSING_ZC_INPUTS "MISSING_ZC_INPUTS"
|
||||
#define API_RETURN_CODE_MISSING_ZC_INPUTS "MISSING_ZC_INPUTS"
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ namespace tools
|
|||
};
|
||||
|
||||
#ifndef TESTNET
|
||||
static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.42.247/pre-download/zano_mdbx_95_2200000.pak", "c3bd64c62495c3f266759750952519f13f32fc161b59547beaa8202b6e26d516", 2628767033, 5100195840 };
|
||||
static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.42.247/pre-download/zano_lmdb_95_2200000.pak", "fcbf0ab3b23836e1a51fa675e719900fb94110cfb74790b3323cebce7fb9f5bd", 3426025872, 4954472448 };
|
||||
static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.42.247/pre-download/zano_mdbx_95_2390000.pak", "ffc8d2220a4d8b3fba51073a422cbb6139c60858469ea086623f9d16329eb5b4", 2767268964, 5368627200 };
|
||||
static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.42.247/pre-download/zano_lmdb_95_2390000.pak", "7e58951bc523eb12e0ec07171bc67b3f96bad4d5454dd2da56f642a872e230d3", 3618283035, 5156397056 };
|
||||
#else
|
||||
static constexpr pre_download_entry c_pre_download_mdbx = { "", "", 0, 0 };
|
||||
static constexpr pre_download_entry c_pre_download_lmdb = { "", "", 0, 0 };
|
||||
|
|
|
|||
|
|
@ -407,8 +407,11 @@ bool generate_genesis(const std::string& path_config, uint64_t premine_split_amo
|
|||
|
||||
ss.str("");
|
||||
ss.clear();
|
||||
const account_public_address dummy_address = AUTO_VAL_INIT(dummy_address);
|
||||
|
||||
std::cout << ENDL << "PROOF PHRASE: " << gcp.proof_string << ENDL;
|
||||
// construct_miner_tx(0, 0, 0, 0, 0, destinations, bl.miner_tx, TRANSACTION_VERSION_PRE_HF4, gcp.proof_string, CURRENCY_MINER_TX_MAX_OUTS); <-- temporarily commented out; this overload needs to be re-implemented -- sowle
|
||||
uint64_t block_reward_without_fee = 0;
|
||||
construct_miner_tx(0, 0, 0, 0, 0, dummy_address, dummy_address, bl.miner_tx, block_reward_without_fee, TRANSACTION_VERSION_PRE_HF4, gcp.proof_string, CURRENCY_MINER_TX_MAX_OUTS, false, pos_entry(), nullptr, nullptr, destinations);
|
||||
currency::blobdata txb = tx_to_blob(bl.miner_tx);
|
||||
|
||||
//self validate block
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
// Copyright (c) 2022-2023 Zano Project
|
||||
// Copyright (c) 2022-2023 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Copyright (c) 2022-2024 Zano Project
|
||||
// Copyright (c) 2022-2024 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
// This file contains implementation of CLSAG (s.a. https://eprint.iacr.org/2019/654.pdf by Goodel at el)
|
||||
// This file contains implementation of the original d-CLSAG (s.a. https://eprint.iacr.org/2019/654.pdf by Goodel at el)
|
||||
// and the extended d/v-CLSAG version (s.a. https://github.com/hyle-team/docs/blob/master/zano/dv-CLSAG-extension/ by sowle)
|
||||
//
|
||||
#include "clsag.h"
|
||||
//#include "misc_log_ex.h"
|
||||
|
|
@ -51,6 +52,7 @@ namespace crypto
|
|||
}
|
||||
hsc.add_point(c_scalar_1div8 * pseudo_out_amount_commitment);
|
||||
hsc.add_key_image(ki);
|
||||
hsc.add_pub_key(sig.K1);
|
||||
hash input_hash = hsc.calc_hash_no_reduce();
|
||||
|
||||
hsc.add_32_chars(CRYPTO_HDS_CLSAG_GG_LAYER_0);
|
||||
|
|
@ -87,10 +89,7 @@ namespace crypto
|
|||
hsc.add_point(alpha * ki_base);
|
||||
scalar_t c_prev = hsc.calc_hash(); // c_{secret_index + 1}
|
||||
|
||||
sig.r.clear();
|
||||
sig.r.reserve(ring_size);
|
||||
for(size_t i = 0; i < ring_size; ++i)
|
||||
sig.r.emplace_back(scalar_t::random());
|
||||
sig.r.resize_and_make_random(ring_size);
|
||||
|
||||
for(size_t j = 0, i = (secret_index + 1) % ring_size; j < ring_size - 1; ++j, i = (i + 1) % ring_size)
|
||||
{
|
||||
|
|
@ -137,6 +136,7 @@ namespace crypto
|
|||
}
|
||||
hsc.add_pub_key(pseudo_out_amount_commitment);
|
||||
hsc.add_key_image(ki);
|
||||
hsc.add_pub_key(sig.K1);
|
||||
hash input_hash = hsc.calc_hash_no_reduce();
|
||||
|
||||
hsc.add_32_chars(CRYPTO_HDS_CLSAG_GG_LAYER_0);
|
||||
|
|
@ -203,8 +203,6 @@ namespace crypto
|
|||
CRYPTO_CHECK_AND_THROW_MES((secret_0_xp * c_point_G).to_public_key() == ring[secret_index].stealth_address, "secret_0_xp mismatch");
|
||||
CRYPTO_CHECK_AND_THROW_MES( secret_1_f * c_point_G == 8 * point_t(ring[secret_index].amount_commitment) - pseudo_out_amount_commitment, "secret_1_f mismatch");
|
||||
CRYPTO_CHECK_AND_THROW_MES( secret_2_t * c_point_X == 8 * point_t(ring[secret_index].blinded_asset_id) - pseudo_out_blinded_asset_id, "secret_2_t mismatch");
|
||||
//CRYPTO_CHECK_AND_THROW_MES( secret_3_q * c_point_G == 8 * point_t(ring[secret_index].concealing_point), "");
|
||||
//CRYPTO_CHECK_AND_THROW_MES( secret_4_x * c_point_X == extended_amount_commitment - 8 * point_t(ring[secret_index].amount_commitment) - 8 * point_t(ring[secret_index].concealing_point), "");
|
||||
#endif
|
||||
|
||||
point_t K1_div8 = (c_scalar_1div8 * secret_1_f) * ki_base;
|
||||
|
|
@ -217,16 +215,6 @@ namespace crypto
|
|||
point_t K2 = K2_div8;
|
||||
K2.modify_mul8();
|
||||
|
||||
//point_t K3_div8 = (c_scalar_1div8 * secret_3_q) * ki_base;
|
||||
//K3_div8.to_public_key(sig.K3);
|
||||
//point_t K3 = K3_div8;
|
||||
//K3.modify_mul8();
|
||||
|
||||
//point_t K4_div8 = (c_scalar_1div8 * secret_4_x) * ki_base;
|
||||
//K4_div8.to_public_key(sig.K4);
|
||||
//point_t K4 = K4_div8;
|
||||
//K4.modify_mul8();
|
||||
|
||||
// calculate aggregation coefficients
|
||||
hash_helper_t::hs_t hsc(4 + 3 * ring_size);
|
||||
hsc.add_scalar(m);
|
||||
|
|
@ -240,6 +228,8 @@ namespace crypto
|
|||
hsc.add_point(c_scalar_1div8 * pseudo_out_amount_commitment);
|
||||
hsc.add_point(c_scalar_1div8 * pseudo_out_blinded_asset_id);
|
||||
hsc.add_key_image(ki);
|
||||
hsc.add_pub_key(sig.K1);
|
||||
hsc.add_pub_key(sig.K2);
|
||||
hash input_hash = hsc.calc_hash_no_reduce();
|
||||
DBG_VAL_PRINT(input_hash);
|
||||
|
||||
|
|
@ -259,11 +249,6 @@ namespace crypto
|
|||
scalar_t agg_coeff_2 = hsc.calc_hash();
|
||||
DBG_VAL_PRINT(agg_coeff_2);
|
||||
|
||||
//hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGX_LAYER_3);
|
||||
//hsc.add_hash(input_hash);
|
||||
//scalar_t agg_coeff_3 = hsc.calc_hash();
|
||||
//DBG_VAL_PRINT(agg_coeff_3);
|
||||
|
||||
// prepare A_i, Q_i
|
||||
std::vector<point_t> A_i, Q_i;
|
||||
A_i.reserve(ring_size), Q_i.reserve(ring_size);
|
||||
|
|
@ -300,18 +285,17 @@ namespace crypto
|
|||
}
|
||||
|
||||
// aggregate secret key (layers 0, 1; G component)
|
||||
scalar_t w_sec_key_g = agg_coeff_0 * secret_0_xp + agg_coeff_1 * secret_1_f; // + agg_coeff_3 * secret_3_q;
|
||||
scalar_t w_sec_key_g = agg_coeff_0 * secret_0_xp + agg_coeff_1 * secret_1_f;
|
||||
DBG_VAL_PRINT(w_sec_key_g * c_point_G);
|
||||
|
||||
// aggregate secret key (layer 2; X component)
|
||||
scalar_t w_sec_key_x = agg_coeff_2 * secret_2_t;
|
||||
DBG_VAL_PRINT(w_sec_key_x * c_point_X);
|
||||
|
||||
// calculate aggregate key image (layers 0, 1, 3; G component)
|
||||
point_t W_key_image_g = agg_coeff_0 * key_image + agg_coeff_1 * K1 /* + agg_coeff_3 * K3 */;
|
||||
// calculate aggregate key image (layers 0, 1; G component)
|
||||
point_t W_key_image_g = agg_coeff_0 * key_image + agg_coeff_1 * K1;
|
||||
DBG_VAL_PRINT(key_image);
|
||||
DBG_VAL_PRINT(K1);
|
||||
//DBG_VAL_PRINT(K3);
|
||||
DBG_VAL_PRINT(W_key_image_g);
|
||||
|
||||
// calculate aggregate key image (layer 2; X component)
|
||||
|
|
@ -338,15 +322,8 @@ namespace crypto
|
|||
//DBG_PRINT("c[" << secret_index << "] = Hs(ih, " << alpha_g * c_point_G << ", " << alpha_g * ki_base << ", " << alpha_x * c_point_X << ", " << alpha_x * ki_base << ")");
|
||||
scalar_t c_prev = hsc.calc_hash(); // c_{secret_index + 1}
|
||||
|
||||
sig.r_g.clear();
|
||||
sig.r_x.clear();
|
||||
sig.r_g.reserve(ring_size);
|
||||
sig.r_x.reserve(ring_size);
|
||||
for(size_t i = 0; i < ring_size; ++i)
|
||||
{
|
||||
sig.r_g.emplace_back(scalar_t::random());
|
||||
sig.r_x.emplace_back(scalar_t::random());
|
||||
}
|
||||
sig.r_g.resize_and_make_random(ring_size);
|
||||
sig.r_x.resize_and_make_random(ring_size);
|
||||
|
||||
for(size_t j = 0, i = (secret_index + 1) % ring_size; j < ring_size - 1; ++j, i = (i + 1) % ring_size)
|
||||
{
|
||||
|
|
@ -403,6 +380,8 @@ namespace crypto
|
|||
hsc.add_pub_key(pseudo_out_amount_commitment);
|
||||
hsc.add_pub_key(pseudo_out_blinded_asset_id);
|
||||
hsc.add_key_image(ki);
|
||||
hsc.add_pub_key(sig.K1);
|
||||
hsc.add_pub_key(sig.K2);
|
||||
hash input_hash = hsc.calc_hash_no_reduce();
|
||||
DBG_VAL_PRINT(input_hash);
|
||||
|
||||
|
|
@ -422,11 +401,6 @@ namespace crypto
|
|||
scalar_t agg_coeff_2 = hsc.calc_hash();
|
||||
DBG_VAL_PRINT(agg_coeff_2);
|
||||
|
||||
//hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGX_LAYER_3);
|
||||
//hsc.add_hash(input_hash);
|
||||
//scalar_t agg_coeff_3 = hsc.calc_hash();
|
||||
//DBG_VAL_PRINT(agg_coeff_3);
|
||||
|
||||
// prepare A_i, Q_i
|
||||
std::vector<point_t> A_i, Q_i;
|
||||
A_i.reserve(ring_size), Q_i.reserve(ring_size);
|
||||
|
|
@ -462,13 +436,11 @@ namespace crypto
|
|||
DBG_VAL_PRINT(W_pub_keys_x[i]);
|
||||
}
|
||||
|
||||
// calculate aggregate key image (layers 0, 1, 3; G components)
|
||||
// calculate aggregate key image (layers 0, 1; G components)
|
||||
point_t W_key_image_g =
|
||||
agg_coeff_0 * key_image +
|
||||
agg_coeff_1 * point_t(sig.K1).modify_mul8();
|
||||
// agg_coeff_3 * point_t(sig.K3).modify_mul8();
|
||||
DBG_VAL_PRINT(point_t(sig.K1).modify_mul8());
|
||||
//DBG_VAL_PRINT(point_t(sig.K3).modify_mul8());
|
||||
DBG_VAL_PRINT(W_key_image_g);
|
||||
|
||||
// calculate aggregate key image (layer 2; X component)
|
||||
|
|
@ -498,7 +470,7 @@ namespace crypto
|
|||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
|
||||
/*
|
||||
|
||||
bool generate_CLSAG_GGXG(const hash& m, const std::vector<CLSAG_GGXG_input_ref_t>& ring, const point_t& pseudo_out_amount_commitment, const point_t& extended_amount_commitment, const key_image& ki,
|
||||
const scalar_t& secret_0_xp, const scalar_t& secret_1_f, const scalar_t& secret_2_x, const scalar_t& secret_3_q, uint64_t secret_index, CLSAG_GGXG_signature& sig)
|
||||
|
|
@ -548,6 +520,9 @@ namespace crypto
|
|||
hsc.add_point(c_scalar_1div8 * pseudo_out_amount_commitment);
|
||||
hsc.add_point(c_scalar_1div8 * extended_amount_commitment);
|
||||
hsc.add_key_image(ki);
|
||||
hsc.add_pub_key(sig.K1);
|
||||
hsc.add_pub_key(sig.K2);
|
||||
hsc.add_pub_key(sig.K3);
|
||||
hash input_hash = hsc.calc_hash_no_reduce();
|
||||
DBG_VAL_PRINT(input_hash);
|
||||
|
||||
|
|
@ -617,7 +592,7 @@ namespace crypto
|
|||
DBG_VAL_PRINT(w_sec_key_x * c_point_X);
|
||||
|
||||
// calculate aggregate key image (layers 0, 1, 3; G component)
|
||||
point_t W_key_image_g = agg_coeff_0 * key_image + agg_coeff_1 * K1 + /*agg_coeff_2 * K2 +*/ agg_coeff_3 * K3;
|
||||
point_t W_key_image_g = agg_coeff_0 * key_image + agg_coeff_1 * K1 + agg_coeff_3 * K3;
|
||||
DBG_VAL_PRINT(key_image);
|
||||
DBG_VAL_PRINT(K1);
|
||||
DBG_VAL_PRINT(K3);
|
||||
|
|
@ -647,15 +622,8 @@ namespace crypto
|
|||
//DBG_PRINT("c[" << secret_index << "] = Hs(ih, " << alpha_g * c_point_G << ", " << alpha_g * ki_base << ", " << alpha_x * c_point_X << ", " << alpha_x * ki_base << ")");
|
||||
scalar_t c_prev = hsc.calc_hash(); // c_{secret_index + 1}
|
||||
|
||||
sig.r_g.clear();
|
||||
sig.r_x.clear();
|
||||
sig.r_g.reserve(ring_size);
|
||||
sig.r_x.reserve(ring_size);
|
||||
for(size_t i = 0; i < ring_size; ++i)
|
||||
{
|
||||
sig.r_g.emplace_back(scalar_t::random());
|
||||
sig.r_x.emplace_back(scalar_t::random());
|
||||
}
|
||||
sig.r_g.resize_and_make_random(ring_size);
|
||||
sig.r_x.resize_and_make_random(ring_size);
|
||||
|
||||
for(size_t j = 0, i = (secret_index + 1) % ring_size; j < ring_size - 1; ++j, i = (i + 1) % ring_size)
|
||||
{
|
||||
|
|
@ -713,6 +681,9 @@ namespace crypto
|
|||
hsc.add_pub_key(pseudo_out_amount_commitment);
|
||||
hsc.add_pub_key(extended_amount_commitment);
|
||||
hsc.add_key_image(ki);
|
||||
hsc.add_pub_key(sig.K1);
|
||||
hsc.add_pub_key(sig.K2);
|
||||
hsc.add_pub_key(sig.K3);
|
||||
hash input_hash = hsc.calc_hash_no_reduce();
|
||||
DBG_VAL_PRINT(input_hash);
|
||||
|
||||
|
|
@ -807,7 +778,7 @@ namespace crypto
|
|||
return c_prev == sig.c;
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
//---------------------------------------------------------------
|
||||
|
||||
|
||||
|
|
@ -868,6 +839,10 @@ namespace crypto
|
|||
hsc.add_point(c_scalar_1div8 * pseudo_out_blinded_asset_id);
|
||||
hsc.add_point(c_scalar_1div8 * extended_amount_commitment);
|
||||
hsc.add_key_image(ki);
|
||||
hsc.add_pub_key(sig.K1);
|
||||
hsc.add_pub_key(sig.K2);
|
||||
hsc.add_pub_key(sig.K3);
|
||||
hsc.add_pub_key(sig.K4);
|
||||
hash input_hash = hsc.calc_hash_no_reduce();
|
||||
DBG_VAL_PRINT(input_hash);
|
||||
|
||||
|
|
@ -976,15 +951,8 @@ namespace crypto
|
|||
//DBG_PRINT("c[" << secret_index << "] = Hs(ih, " << alpha_g * c_point_G << ", " << alpha_g * ki_base << ", " << alpha_x * c_point_X << ", " << alpha_x * ki_base << ")");
|
||||
scalar_t c_prev = hsc.calc_hash(); // c_{secret_index + 1}
|
||||
|
||||
sig.r_g.clear();
|
||||
sig.r_x.clear();
|
||||
sig.r_g.reserve(ring_size);
|
||||
sig.r_x.reserve(ring_size);
|
||||
for(size_t i = 0; i < ring_size; ++i)
|
||||
{
|
||||
sig.r_g.emplace_back(scalar_t::random());
|
||||
sig.r_x.emplace_back(scalar_t::random());
|
||||
}
|
||||
sig.r_g.resize_and_make_random(ring_size);
|
||||
sig.r_x.resize_and_make_random(ring_size);
|
||||
|
||||
for(size_t j = 0, i = (secret_index + 1) % ring_size; j < ring_size - 1; ++j, i = (i + 1) % ring_size)
|
||||
{
|
||||
|
|
@ -1048,6 +1016,10 @@ namespace crypto
|
|||
hsc.add_pub_key(pseudo_out_blinded_asset_id);
|
||||
hsc.add_pub_key(extended_amount_commitment);
|
||||
hsc.add_key_image(ki);
|
||||
hsc.add_pub_key(sig.K1);
|
||||
hsc.add_pub_key(sig.K2);
|
||||
hsc.add_pub_key(sig.K3);
|
||||
hsc.add_pub_key(sig.K4);
|
||||
hash input_hash = hsc.calc_hash_no_reduce();
|
||||
DBG_VAL_PRINT(input_hash);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
// Copyright (c) 2022-2023 Zano Project
|
||||
// Copyright (c) 2022-2023 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Copyright (c) 2022-2024 Zano Project
|
||||
// Copyright (c) 2022-2024 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
// This file contains implementation of CLSAG (s.a. https://eprint.iacr.org/2019/654.pdf by Goodel at el)
|
||||
// This file contains implementation of the original d-CLSAG (s.a. https://eprint.iacr.org/2019/654.pdf by Goodel at el)
|
||||
// and the extended d/v-CLSAG version (s.a. https://github.com/hyle-team/docs/blob/master/zano/dv-CLSAG-extension/ by sowle)
|
||||
//
|
||||
#pragma once
|
||||
#include "crypto-sugar.h"
|
||||
|
|
@ -57,11 +58,11 @@ namespace crypto
|
|||
|
||||
|
||||
//
|
||||
// 3-CLSAG
|
||||
// 3/2-CLSAG
|
||||
//
|
||||
|
||||
|
||||
// 3-CLSAG signature (with respect to the group element G, G, X -- that's why 'GGX')
|
||||
// 3/2-CLSAG signature (with respect to the group element G, G, X -- that's why 'GGX')
|
||||
struct CLSAG_GGX_signature
|
||||
{
|
||||
scalar_t c;
|
||||
|
|
@ -93,12 +94,13 @@ namespace crypto
|
|||
const public_key& pseudo_out_asset_id, const key_image& ki, const CLSAG_GGX_signature& sig);
|
||||
|
||||
|
||||
/*
|
||||
//
|
||||
// 4-CLSAG
|
||||
// 4/2-CLSAG (eventually, it's not used in Zano)
|
||||
//
|
||||
|
||||
|
||||
// 4-CLSAG signature (with respect to the group element G, G, X, G -- that's why 'GGXG')
|
||||
// 4/2-CLSAG signature (with respect to the group element G, G, X, G -- that's why 'GGXG')
|
||||
struct CLSAG_GGXG_signature
|
||||
{
|
||||
scalar_t c;
|
||||
|
|
@ -130,14 +132,14 @@ namespace crypto
|
|||
bool verify_CLSAG_GGXG(const hash& m, const std::vector<CLSAG_GGXG_input_ref_t>& ring, const public_key& pseudo_out_amount_commitment,
|
||||
const public_key& extended_amount_commitment, const key_image& ki, const CLSAG_GGXG_signature& sig);
|
||||
|
||||
|
||||
*/
|
||||
|
||||
//
|
||||
// 5-CLSAG
|
||||
// 5/2-CLSAG
|
||||
//
|
||||
|
||||
|
||||
// 5-CLSAG signature (with respect to the group element G, G, X, X, G -- that's why 'GGXXG')
|
||||
// 5/2-CLSAG signature (with respect to the group element G, G, X, X, G -- that's why 'GGXXG')
|
||||
struct CLSAG_GGXXG_signature
|
||||
{
|
||||
scalar_t c;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ DISABLE_VS_WARNINGS(4146 4244)
|
|||
void fe_mul(fe, const fe, const fe);
|
||||
void fe_sq(fe, const fe);
|
||||
void fe_tobytes(unsigned char *, const fe);
|
||||
static void ge_madd(ge_p1p1 *, const ge_p3 *, const ge_precomp *);
|
||||
static void ge_msub(ge_p1p1 *, const ge_p3 *, const ge_precomp *);
|
||||
static void ge_p2_0(ge_p2 *);
|
||||
static void ge_p3_dbl(ge_p1p1 *, const ge_p3 *);
|
||||
|
|
@ -119,7 +118,7 @@ Postconditions:
|
|||
|h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
||||
*/
|
||||
|
||||
static void fe_add(fe h, const fe f, const fe g) {
|
||||
void fe_add(fe h, const fe f, const fe g) {
|
||||
int32_t f0 = f[0];
|
||||
int32_t f1 = f[1];
|
||||
int32_t f2 = f[2];
|
||||
|
|
@ -1425,7 +1424,7 @@ int ge_frombytes_vartime(ge_p3 *h, const unsigned char *s) {
|
|||
r = p + q
|
||||
*/
|
||||
|
||||
static void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
|
||||
void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
|
||||
fe t0;
|
||||
fe_add(r->X, p->Y, p->X);
|
||||
fe_sub(r->Y, p->Y, p->X);
|
||||
|
|
@ -4314,3 +4313,171 @@ void ge_cached_to_p2(ge_p2 *r, const ge_cached *c)
|
|||
|
||||
fe_copy(r->Z, c->Z);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// EXPERIMENTAL
|
||||
//
|
||||
|
||||
// With these select_vartime/ge_scalarmult_base_vartime I got ~25% speed up comparing to the select/ge_scalarmult_base -- sowle
|
||||
static void select_vartime(ge_precomp *t, int pos, signed char b)
|
||||
{
|
||||
unsigned char bnegative = negative(b);
|
||||
unsigned char babs = b - (((-bnegative) & b) << 1);
|
||||
const ge_precomp* base;
|
||||
|
||||
if (babs == 0)
|
||||
{
|
||||
ge_precomp_0(t);
|
||||
}
|
||||
else if (bnegative == 0)
|
||||
{
|
||||
base = &ge_base[pos][babs - 1];
|
||||
fe_copy(t->yplusx, base->yplusx);
|
||||
fe_copy(t->yminusx, base->yminusx);
|
||||
fe_copy(t->xy2d, base->xy2d);
|
||||
}
|
||||
else
|
||||
{
|
||||
base = &ge_base[pos][babs - 1];
|
||||
fe_copy(t->yplusx, base->yminusx);
|
||||
fe_copy(t->yminusx, base->yplusx);
|
||||
fe_neg(t->xy2d, base->xy2d);
|
||||
}
|
||||
}
|
||||
|
||||
void ge_scalarmult_base_vartime(ge_p3 *h, const unsigned char *a)
|
||||
{
|
||||
signed char e[64];
|
||||
signed char carry;
|
||||
ge_p1p1 r;
|
||||
ge_p2 s;
|
||||
ge_precomp t;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; ++i) {
|
||||
e[2 * i + 0] = (a[i] >> 0) & 15;
|
||||
e[2 * i + 1] = (a[i] >> 4) & 15;
|
||||
}
|
||||
/* each e[i] is between 0 and 15 */
|
||||
/* e[63] is between 0 and 7 */
|
||||
|
||||
carry = 0;
|
||||
for (i = 0; i < 63; ++i) {
|
||||
e[i] += carry;
|
||||
carry = e[i] + 8;
|
||||
carry >>= 4;
|
||||
e[i] -= carry << 4;
|
||||
}
|
||||
e[63] += carry;
|
||||
/* each e[i] is between -8 and 8 */
|
||||
|
||||
ge_p3_0(h);
|
||||
for (i = 1; i < 64; i += 2) {
|
||||
select_vartime(&t, i / 2, e[i]);
|
||||
ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r);
|
||||
}
|
||||
|
||||
ge_p3_dbl(&r, h); ge_p1p1_to_p2(&s, &r);
|
||||
ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r);
|
||||
ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r);
|
||||
ge_p2_dbl(&r, &s); ge_p1p1_to_p3(h, &r);
|
||||
|
||||
for (i = 0; i < 64; i += 2) {
|
||||
select_vartime(&t, i / 2, e[i]);
|
||||
ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void select_custom_precomp_vartime(ge_precomp *t, const precomp_data_t base_precomp, int pos, signed char b)
|
||||
{
|
||||
unsigned char bnegative = negative(b);
|
||||
unsigned char babs = b - (((-bnegative) & b) << 1);
|
||||
const ge_precomp* base;
|
||||
|
||||
if (babs == 0)
|
||||
{
|
||||
ge_precomp_0(t);
|
||||
}
|
||||
else if (bnegative == 0)
|
||||
{
|
||||
base = &base_precomp[pos][babs - 1];
|
||||
fe_copy(t->yplusx, base->yplusx);
|
||||
fe_copy(t->yminusx, base->yminusx);
|
||||
fe_copy(t->xy2d, base->xy2d);
|
||||
}
|
||||
else
|
||||
{
|
||||
base = &base_precomp[pos][babs - 1];
|
||||
fe_copy(t->yplusx, base->yminusx);
|
||||
fe_copy(t->yminusx, base->yplusx);
|
||||
fe_neg(t->xy2d, base->xy2d);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ge_scalarmult_precomp_vartime(ge_p3 *h, const precomp_data_t base_precomp, const unsigned char *a)
|
||||
{
|
||||
signed char e[64];
|
||||
signed char carry;
|
||||
ge_p1p1 r;
|
||||
ge_p2 s;
|
||||
ge_precomp t;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; ++i) {
|
||||
e[2 * i + 0] = (a[i] >> 0) & 15;
|
||||
e[2 * i + 1] = (a[i] >> 4) & 15;
|
||||
}
|
||||
/* each e[i] is between 0 and 15 */
|
||||
/* e[63] is between 0 and 7 */
|
||||
|
||||
carry = 0;
|
||||
for (i = 0; i < 63; ++i) {
|
||||
e[i] += carry;
|
||||
carry = e[i] + 8;
|
||||
carry >>= 4;
|
||||
e[i] -= carry << 4;
|
||||
}
|
||||
e[63] += carry;
|
||||
/* each e[i] is between -8 and 8 */
|
||||
|
||||
ge_p3_0(h);
|
||||
for (i = 1; i < 64; i += 2) {
|
||||
select_custom_precomp_vartime(&t, base_precomp, i / 2, e[i]);
|
||||
ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r);
|
||||
}
|
||||
|
||||
ge_p3_dbl(&r, h); ge_p1p1_to_p2(&s, &r);
|
||||
ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r);
|
||||
ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r);
|
||||
ge_p2_dbl(&r, &s); ge_p1p1_to_p3(h, &r);
|
||||
|
||||
for (i = 0; i < 64; i += 2) {
|
||||
select_custom_precomp_vartime(&t, base_precomp, i / 2, e[i]);
|
||||
ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r);
|
||||
}
|
||||
}
|
||||
|
||||
void ge_p3_to_precomp(ge_precomp *r, const ge_p3* p)
|
||||
{
|
||||
fe recip;
|
||||
fe x;
|
||||
fe y;
|
||||
//unsigned char s[32];
|
||||
|
||||
fe_invert(recip, p->Z);
|
||||
fe_mul(x, p->X, recip);
|
||||
fe_mul(y, p->Y, recip);
|
||||
fe_sub(r->yminusx, y, x);
|
||||
fe_add(r->yplusx, y, x);
|
||||
fe_mul(r->xy2d, x, y);
|
||||
fe_mul(r->xy2d, r->xy2d, fe_d2);
|
||||
|
||||
// to get canonical representation and obtain the very same beautiful numbers for ge_base in crypto-ops-data.c (maybe unnecessary, TODO -- sowle)
|
||||
//fe_tobytes(s, r->yminusx); fe_frombytes(r->yminusx, s);
|
||||
//fe_tobytes(s, r->yplusx); fe_frombytes(r->yplusx, s);
|
||||
//fe_tobytes(s, r->xy2d); fe_frombytes(r->xy2d, s);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ void ge_double_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const ge_
|
|||
|
||||
extern const fe fe_sqrtm1;
|
||||
extern const fe fe_d;
|
||||
extern const fe fe_d2;
|
||||
int ge_frombytes_vartime(ge_p3 *, const unsigned char *);
|
||||
|
||||
/* From ge_p1p1_to_p2.c */
|
||||
|
|
@ -112,12 +113,19 @@ void ge_p2_to_p3(ge_p3 *r, const ge_p2 *t);
|
|||
void ge_bytes_hash_to_ec(ge_p3 *, const void *, size_t);
|
||||
void ge_bytes_hash_to_ec_32(ge_p3 *, const unsigned char *);
|
||||
void ge_cached_to_p2(ge_p2 *r, const ge_cached *c);
|
||||
void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q);
|
||||
|
||||
void ge_p3_0(ge_p3 *h);
|
||||
void ge_sub(ge_p1p1 *, const ge_p3 *, const ge_cached *);
|
||||
void ge_double_scalarmult_base_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b);
|
||||
void ge_scalarmult_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A);
|
||||
void ge_scalarmult_vartime_p3_v2(ge_p3 *r, const unsigned char *a, const ge_p3 *A);
|
||||
void ge_scalarmult_base_vartime(ge_p3 *h, const unsigned char *a);
|
||||
|
||||
/* precomp_data[i][j] = (j + 1) * 256^i * G */
|
||||
typedef ge_precomp (precomp_data_t)[32][8];
|
||||
void ge_scalarmult_precomp_vartime(ge_p3 *h, const precomp_data_t base_precomp, const unsigned char *a);
|
||||
void ge_p3_to_precomp(ge_precomp *r, const ge_p3* p);
|
||||
|
||||
extern const fe fe_ma2;
|
||||
extern const fe fe_ma;
|
||||
|
|
@ -139,6 +147,7 @@ void sc_invert(unsigned char*, const unsigned char*);
|
|||
|
||||
void fe_sq(fe h, const fe f);
|
||||
int fe_isnonzero(const fe f);
|
||||
void fe_add(fe h, const fe f, const fe g);
|
||||
void fe_sub(fe h, const fe f, const fe g);
|
||||
void fe_mul(fe, const fe, const fe);
|
||||
void fe_frombytes(fe h, const unsigned char *s);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2020-2023 Zano Project
|
||||
// Copyright (c) 2020-2023 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Copyright (c) 2020-2024 Zano Project
|
||||
// Copyright (c) 2020-2024 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
|
|
@ -517,6 +517,24 @@ namespace crypto
|
|||
m_u64[bit_index >> 6] &= ~(1ull << (bit_index & 63));
|
||||
}
|
||||
|
||||
// the result is guaranteed to be within [ 0; 2 ^ bits_count )
|
||||
uint64_t get_bits(uint8_t bit_index_first, uint8_t bits_count) const
|
||||
{
|
||||
if (bits_count == 0 || bits_count > 64)
|
||||
return 0;
|
||||
uint8_t bits_count_m_1 = bits_count - 1;
|
||||
unsigned int bit_index_last = bit_index_first + bits_count_m_1;
|
||||
if (bit_index_last > 255)
|
||||
bit_index_last = 255;
|
||||
|
||||
uint64_t result = m_u64[bit_index_first >> 6] >> (bit_index_first & 63);
|
||||
if (bits_count_m_1 > (bit_index_last & 63))
|
||||
result |= m_u64[bit_index_last >> 6] << (bits_count_m_1 - (bit_index_last & 63));
|
||||
|
||||
uint64_t result_mask = ((1ull << bits_count_m_1) - 1) << 1 | 1; // (just because 1ull << 64 in undefined behaviour, not a 0 as one would expect)
|
||||
return result & result_mask;
|
||||
}
|
||||
|
||||
// does not reduce
|
||||
static scalar_t power_of_2(uint8_t exponent)
|
||||
{
|
||||
|
|
@ -612,9 +630,13 @@ namespace crypto
|
|||
|
||||
bool is_zero() const
|
||||
{
|
||||
// (0, 1) ~ (0, z, z, 0)
|
||||
// (0, 1) ~ (0, z, z, 0) for any non-zero z https://www.rfc-editor.org/rfc/rfc8032#page-17
|
||||
if (fe_isnonzero(m_p3.X) != 0)
|
||||
return false;
|
||||
return false; // x != 0
|
||||
if (fe_isnonzero(m_p3.Z) == 0)
|
||||
return false; // z == 0
|
||||
if (fe_isnonzero(m_p3.T) != 0)
|
||||
return false; // t != 0
|
||||
fe y_minus_z;
|
||||
fe_sub(y_minus_z, m_p3.Y, m_p3.Z);
|
||||
return fe_isnonzero(y_minus_z) == 0;
|
||||
|
|
@ -707,14 +729,15 @@ namespace crypto
|
|||
friend point_t operator*(const scalar_t& lhs, const point_t& rhs)
|
||||
{
|
||||
point_t result;
|
||||
ge_scalarmult_p3(&result.m_p3, lhs.m_s, &rhs.m_p3);
|
||||
//ge_scalarmult_p3(&result.m_p3, lhs.m_s, &rhs.m_p3);
|
||||
ge_scalarmult_vartime_p3(&result.m_p3, lhs.m_s, &rhs.m_p3);
|
||||
return result;
|
||||
}
|
||||
|
||||
point_t& operator*=(const scalar_t& rhs)
|
||||
{
|
||||
// TODO: ge_scalarmult_vartime_p3
|
||||
ge_scalarmult_p3(&m_p3, rhs.m_s, &m_p3);
|
||||
//ge_scalarmult_p3(&m_p3, rhs.m_s, &m_p3);
|
||||
ge_scalarmult_vartime_p3(&m_p3, rhs.m_s, &m_p3);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -723,7 +746,8 @@ namespace crypto
|
|||
point_t result;
|
||||
scalar_t reciprocal;
|
||||
sc_invert(&reciprocal.m_s[0], &rhs.m_s[0]);
|
||||
ge_scalarmult_p3(&result.m_p3, &reciprocal.m_s[0], &lhs.m_p3);
|
||||
//ge_scalarmult_p3(&result.m_p3, &reciprocal.m_s[0], &lhs.m_p3);
|
||||
ge_scalarmult_vartime_p3(&result.m_p3, &reciprocal.m_s[0], &lhs.m_p3);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -742,6 +766,24 @@ namespace crypto
|
|||
return *this;
|
||||
}
|
||||
|
||||
point_t modify_mul_pow_2(size_t power)
|
||||
{
|
||||
if (power > 0)
|
||||
{
|
||||
ge_p1p1 p1;
|
||||
ge_p2 p2;
|
||||
ge_p3_to_p2(&p2, &m_p3);
|
||||
for (size_t i = 1; i < power; ++i)
|
||||
{
|
||||
ge_p2_dbl(&p1, &p2);
|
||||
ge_p1p1_to_p2(&p2, &p1);
|
||||
}
|
||||
ge_p2_dbl(&p1, &p2);
|
||||
ge_p1p1_to_p3(&m_p3, &p1);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// returns a * this + G
|
||||
point_t mul_plus_G(const scalar_t& a) const
|
||||
{
|
||||
|
|
@ -867,7 +909,8 @@ namespace crypto
|
|||
friend point_t operator*(const scalar_t& lhs, const point_g_t&)
|
||||
{
|
||||
point_t result;
|
||||
ge_scalarmult_base(&result.m_p3, &lhs.m_s[0]);
|
||||
//ge_scalarmult_base(&result.m_p3, &lhs.m_s[0]);
|
||||
ge_scalarmult_base_vartime(&result.m_p3, &lhs.m_s[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -876,7 +919,8 @@ namespace crypto
|
|||
point_t result;
|
||||
scalar_t reciprocal;
|
||||
sc_invert(&reciprocal.m_s[0], &rhs.m_s[0]);
|
||||
ge_scalarmult_base(&result.m_p3, &reciprocal.m_s[0]);
|
||||
//ge_scalarmult_base(&result.m_p3, &reciprocal.m_s[0]);
|
||||
ge_scalarmult_base_vartime(&result.m_p3, &reciprocal.m_s[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -885,6 +929,42 @@ namespace crypto
|
|||
}; // struct point_g_t
|
||||
|
||||
|
||||
void construct_precomp_data(precomp_data_t precomp_data, const point_t& point);
|
||||
|
||||
//
|
||||
// point_pc_t -- point with 30kB of precomputed data, which make possible to do very fast single scalar multiplication
|
||||
//
|
||||
struct point_pc_t : public point_t
|
||||
{
|
||||
constexpr point_pc_t(const int32_t(&v)[40], const precomp_data_t* precomp_data_p)
|
||||
: point_t(v)
|
||||
, m_precomp_data_p(precomp_data_p)
|
||||
{
|
||||
//construct_precomp_data(m_precomp_data, *this);
|
||||
}
|
||||
|
||||
friend point_t operator*(const scalar_t& lhs, const point_pc_t& self)
|
||||
{
|
||||
point_t result;
|
||||
ge_scalarmult_precomp_vartime(&result.m_p3, *self.m_precomp_data_p, &lhs.m_s[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
friend point_t operator/(const point_pc_t& self, const scalar_t& rhs)
|
||||
{
|
||||
point_t result;
|
||||
scalar_t reciprocal;
|
||||
sc_invert(&reciprocal.m_s[0], &rhs.m_s[0]);
|
||||
ge_scalarmult_precomp_vartime(&result.m_p3, *self.m_precomp_data_p, &reciprocal.m_s[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
static_assert(sizeof(crypto::public_key) == 32, "size error");
|
||||
|
||||
const precomp_data_t* m_precomp_data_p;
|
||||
}; // struct point_pc_t
|
||||
|
||||
|
||||
//
|
||||
// vector of scalars
|
||||
//
|
||||
|
|
@ -1042,18 +1122,30 @@ namespace crypto
|
|||
|
||||
|
||||
//
|
||||
// Global constants (checked in crypto_constants test)
|
||||
// Global constants (checked in crypto_constants and crypto_generators_precomp tests)
|
||||
//
|
||||
|
||||
static constexpr point_t c_point_0 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }};
|
||||
static constexpr point_g_t c_point_G {{ 25485296, 5318399, 8791791, -8299916, -14349720, 6939349, -3324311, -7717049, 7287234, -6577708, -758052, -1832720, 13046421, -4857925, 6576754, 14371947, -13139572, 6845540, -2198883, -4003719, -947565, 6097708, -469190, 10704810, -8556274, -15589498, -16424464, -16608899, 14028613, -5004649, 6966464, -2456167, 7033433, 6781840, 28785542, 12262365, -2659449, 13959020, -21013759, -5262166 }};
|
||||
static constexpr point_t c_point_H {{ 20574939, 16670001, -29137604, 14614582, 24883426, 3503293, 2667523, 420631, 2267646, -4769165, -11764015, -12206428, -14187565, -2328122, -16242653, -788308, -12595746, -8251557, -10110987, 853396, -4982135, 6035602, -21214320, 16156349, 977218, 2807645, 31002271, 5694305, -16054128, 5644146, -15047429, -568775, -22568195, -8089957, -27721961, -10101877, -29459620, -13359100, -31515170, -6994674 }};
|
||||
static constexpr point_t c_point_H2 {{ 1318371, 14804112, 12545972, -13482561, -12089798, -16020744, -21221907, -8410994, -33080606, 11275578, 3807637, 11185450, -23227561, -12892068, 1356866, -1025012, -8022738, -8139671, -20315029, -13916324, -6475650, -7025596, 12403179, -5139984, -12068178, 10445584, -14826705, -4927780, 13964546, 12525942, -2314107, -10566315, 32243863, 15603849, 5154154, 4276633, -20918372, -15718796, -26386151, 8434696 }};
|
||||
static constexpr point_t c_point_U {{ 30807552, 984924, 23426137, -5598760, 7545909, 16325843, 993742, 2594106, -31962071, -959867, 16454190, -4091093, 1197656, 13586872, -9269020, -14133290, 1869274, 13360979, -24627258, -10663086, 2212027, 1198856, 20515811, 15870563, -23833732, 9839517, -19416306, 11567295, -4212053, 348531, -2671541, 484270, -19128078, 1236698, -16002690, 9321345, 9776066, 10711838, 11187722, -16371275 }};
|
||||
static constexpr point_t c_point_X {{ 25635916, -5459446, 5768861, 5666160, -6357364, -12939311, 29490001, -4543704, -31266450, -2582476, 23705213, 9562626, -716512, 16560168, 7947407, 2039790, -2752711, 4742449, 3356761, 16338966, 17303421, -5790717, -5684800, 12062431, -3307947, 8139265, -26544839, 12058874, 3452748, 3359034, 26514848, -6060876, 31255039, 11154418, -21741975, -3782423, -19871841, 5729859, 21754676, -12454027 }};
|
||||
static constexpr point_t c_point_H_plus_G {{ 12291435, 3330843, -3390294, 13894858, -1099584, -6848191, 12040668, -15950068, -7494633, 12566672, -5526901, -16645799, -31081168, -1095427, -13082463, 4573480, -11255691, 4344628, 33477173, 11137213, -3837023, -12436594, -8471924, -814016, 10785607, 9492721, 10992667, 7406385, -5687296, -127915, -6229107, -9324867, 558657, 6493750, 4895261, 12642545, 9549220, 696086, 21894285, -10521807 }};
|
||||
static constexpr point_t c_point_H_minus_G {{ -28347682, 3523701, -3380175, -14453727, 4238027, -6032522, 20235758, 4091609, 12557126, -8064113, 4212476, -13419094, -114185, -7650727, -24238, 16663404, 23676363, -6819610, 18286466, 8714527, -3837023, -12436594, -8471924, -814016, 10785607, 9492721, 10992667, 7406385, -5687296, -127915, -20450317, 13815641, -11604061, -447489, 27380225, 9400847, -8551293, -1173627, -28110171, 14241295 }};
|
||||
|
||||
namespace xdetails
|
||||
{
|
||||
extern const precomp_data_t c_point_H_precomp_data;
|
||||
extern const precomp_data_t c_point_H2_precomp_data;
|
||||
extern const precomp_data_t c_point_U_precomp_data;
|
||||
extern const precomp_data_t c_point_X_precomp_data;
|
||||
extern const precomp_data_t c_point_H_plus_G_precomp_data;
|
||||
extern const precomp_data_t c_point_H_minus_G_precomp_data;
|
||||
};
|
||||
|
||||
inline constexpr point_t c_point_0 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }};
|
||||
inline constexpr point_g_t c_point_G {{ 25485296, 5318399, 8791791, -8299916, -14349720, 6939349, -3324311, -7717049, 7287234, -6577708, -758052, -1832720, 13046421, -4857925, 6576754, 14371947, -13139572, 6845540, -2198883, -4003719, -947565, 6097708, -469190, 10704810, -8556274, -15589498, -16424464, -16608899, 14028613, -5004649, 6966464, -2456167, 7033433, 6781840, 28785542, 12262365, -2659449, 13959020, -21013759, -5262166 }};
|
||||
|
||||
inline constexpr point_pc_t c_point_H {{ 20574939, 16670001, -29137604, 14614582, 24883426, 3503293, 2667523, 420631, 2267646, -4769165, -11764015, -12206428, -14187565, -2328122, -16242653, -788308, -12595746, -8251557, -10110987, 853396, -4982135, 6035602, -21214320, 16156349, 977218, 2807645, 31002271, 5694305, -16054128, 5644146, -15047429, -568775, -22568195, -8089957, -27721961, -10101877, -29459620, -13359100, -31515170, -6994674 }, &xdetails::c_point_H_precomp_data };
|
||||
inline constexpr point_pc_t c_point_H2 {{ 1318371, 14804112, 12545972, -13482561, -12089798, -16020744, -21221907, -8410994, -33080606, 11275578, 3807637, 11185450, -23227561, -12892068, 1356866, -1025012, -8022738, -8139671, -20315029, -13916324, -6475650, -7025596, 12403179, -5139984, -12068178, 10445584, -14826705, -4927780, 13964546, 12525942, -2314107, -10566315, 32243863, 15603849, 5154154, 4276633, -20918372, -15718796, -26386151, 8434696 }, &xdetails::c_point_H2_precomp_data };
|
||||
inline constexpr point_pc_t c_point_U {{ 30807552, 984924, 23426137, -5598760, 7545909, 16325843, 993742, 2594106, -31962071, -959867, 16454190, -4091093, 1197656, 13586872, -9269020, -14133290, 1869274, 13360979, -24627258, -10663086, 2212027, 1198856, 20515811, 15870563, -23833732, 9839517, -19416306, 11567295, -4212053, 348531, -2671541, 484270, -19128078, 1236698, -16002690, 9321345, 9776066, 10711838, 11187722, -16371275 }, &xdetails::c_point_U_precomp_data };
|
||||
inline constexpr point_pc_t c_point_X {{ 25635916, -5459446, 5768861, 5666160, -6357364, -12939311, 29490001, -4543704, -31266450, -2582476, 23705213, 9562626, -716512, 16560168, 7947407, 2039790, -2752711, 4742449, 3356761, 16338966, 17303421, -5790717, -5684800, 12062431, -3307947, 8139265, -26544839, 12058874, 3452748, 3359034, 26514848, -6060876, 31255039, 11154418, -21741975, -3782423, -19871841, 5729859, 21754676, -12454027 }, &xdetails::c_point_X_precomp_data };
|
||||
inline constexpr point_pc_t c_point_H_plus_G {{ 12291435, 3330843, -3390294, 13894858, -1099584, -6848191, 12040668, -15950068, -7494633, 12566672, -5526901, -16645799, -31081168, -1095427, -13082463, 4573480, -11255691, 4344628, 33477173, 11137213, -3837023, -12436594, -8471924, -814016, 10785607, 9492721, 10992667, 7406385, -5687296, -127915, -6229107, -9324867, 558657, 6493750, 4895261, 12642545, 9549220, 696086, 21894285, -10521807 }, &xdetails::c_point_H_plus_G_precomp_data };
|
||||
inline constexpr point_pc_t c_point_H_minus_G {{ -28347682, 3523701, -3380175, -14453727, 4238027, -6032522, 20235758, 4091609, 12557126, -8064113, 4212476, -13419094, -114185, -7650727, -24238, 16663404, 23676363, -6819610, 18286466, 8714527, -3837023, -12436594, -8471924, -814016, 10785607, 9492721, 10992667, 7406385, -5687296, -127915, -20450317, 13815641, -11604061, -447489, 27380225, 9400847, -8551293, -1173627, -28110171, 14241295 }, &xdetails::c_point_H_minus_G_precomp_data };
|
||||
|
||||
|
||||
//
|
||||
// hash functions' helper
|
||||
//
|
||||
|
|
@ -1250,6 +1342,15 @@ namespace crypto
|
|||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static scalar_t hs(const char(&str32)[32], const scalar_t& s, const crypto::public_key& pk)
|
||||
{
|
||||
hs_t hs_calculator(2);
|
||||
hs_calculator.add_32_chars(str32);
|
||||
hs_calculator.add_scalar(s);
|
||||
hs_calculator.add_pub_key(pk);
|
||||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static scalar_t hs(const crypto::public_key& pk, const uint64_t i)
|
||||
{
|
||||
hs_t hs_calculator(2);
|
||||
|
|
|
|||
25
src/crypto/msm.cpp
Normal file
25
src/crypto/msm.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) 2023-2023 Zano Project
|
||||
// Copyright (c) 2023-2023 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
#include "epee/include/misc_log_ex.h"
|
||||
//#include "zarcanum.h"
|
||||
#include "msm.h"
|
||||
//#include "../currency_core/crypto_config.h" // TODO: move it to the crypto
|
||||
//#include "../common/crypto_stream_operators.h" // TODO: move it to the crypto
|
||||
|
||||
#if 0
|
||||
# define DBG_VAL_PRINT(x) std::cout << std::setw(30) << std::left << #x ": " << x << std::endl
|
||||
# define DBG_PRINT(x) std::cout << x << std::endl
|
||||
#else
|
||||
# define DBG_VAL_PRINT(x) (void(0))
|
||||
# define DBG_PRINT(x) (void(0))
|
||||
#endif
|
||||
|
||||
namespace crypto
|
||||
{
|
||||
|
||||
|
||||
|
||||
} // namespace crypto
|
||||
173
src/crypto/msm.h
Normal file
173
src/crypto/msm.h
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
// Copyright (c) 2023-2023 Zano Project (https://zano.org/)
|
||||
// Copyright (c) 2023-2023 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#pragma once
|
||||
|
||||
// This file contains Multi-Scalar Multiplication routines
|
||||
|
||||
#include "epee/include/misc_log_ex.h"
|
||||
#include "crypto-sugar.h"
|
||||
|
||||
namespace crypto
|
||||
{
|
||||
|
||||
template<typename CT>
|
||||
bool msm_and_check_zero_naive(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(g_scalars.size() <= CT::c_bpp_mn_max, false, "g_scalars oversized");
|
||||
CHECK_AND_ASSERT_MES(h_scalars.size() <= CT::c_bpp_mn_max, false, "h_scalars oversized");
|
||||
|
||||
point_t result = summand;
|
||||
|
||||
for (size_t i = 0; i < g_scalars.size(); ++i)
|
||||
result += g_scalars[i] * CT::get_generator(false, i);
|
||||
|
||||
for (size_t i = 0; i < h_scalars.size(); ++i)
|
||||
result += h_scalars[i] * CT::get_generator(true, i);
|
||||
|
||||
if (!result.is_zero())
|
||||
{
|
||||
LOG_PRINT_L0("msm result is non zero: " << result);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// https://eprint.iacr.org/2022/999.pdf
|
||||
// "Pippenger algorithm [1], and its variant that is widely used in the ZK space is called the bucket method"
|
||||
template<typename CT>
|
||||
bool msm_and_check_zero_pippenger_v3(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand, uint8_t c)
|
||||
{
|
||||
// TODO: with c = 8 and with direct access got much worse result than with c = 7 and get_bits() for N = 128..256, consider checking again for bigger datasets (N>256)
|
||||
// TODO: consider preparing a cached generators' points
|
||||
|
||||
CHECK_AND_ASSERT_MES(g_scalars.size() <= CT::c_bpp_mn_max, false, "g_scalars oversized");
|
||||
CHECK_AND_ASSERT_MES(h_scalars.size() <= CT::c_bpp_mn_max, false, "h_scalars oversized");
|
||||
CHECK_AND_ASSERT_MES(c < 10, false, "c is too big");
|
||||
|
||||
size_t C = 1ull << c;
|
||||
|
||||
// k_max * c + (c-1) >= max_bit_idx
|
||||
//
|
||||
// max_bit_idx - (c - 1) max_bit_idx - (c - 1) + (c - 1) max_bit_idx
|
||||
// k_max = ceil ( --------------------- ) = floor ( ------------------------------ ) = floor ( ----------- )
|
||||
// c c c
|
||||
const size_t b = 253; // the maximum number of bits in x https://eprint.iacr.org/2022/999.pdf TODO: we may also scan for maximum bit used in all the scalars if all the scalars are small
|
||||
const size_t max_bit_idx = b - 1;
|
||||
const size_t k_max = max_bit_idx / c;
|
||||
const size_t K = k_max + 1;
|
||||
|
||||
std::vector<point_t> buckets(C * K);
|
||||
std::vector<bool> buckets_inited(C * K);
|
||||
std::vector<point_t> Sk(K);
|
||||
std::vector<bool> Sk_inited(K);
|
||||
std::vector<point_t> Gk(K);
|
||||
std::vector<bool> Gk_inited(K);
|
||||
|
||||
// first loop, calculate partial bucket sums
|
||||
for (size_t n = 0; n < g_scalars.size(); ++n)
|
||||
{
|
||||
for (size_t k = 0; k < K; ++k)
|
||||
{
|
||||
uint64_t l = g_scalars[n].get_bits((uint8_t)(k * c), c); // l in [0; 2^c-1]
|
||||
if (l != 0)
|
||||
{
|
||||
size_t bucket_id = l * K + k;
|
||||
if (buckets_inited[bucket_id])
|
||||
buckets[bucket_id] += CT::get_generator(false, n);
|
||||
else
|
||||
{
|
||||
buckets[bucket_id] = CT::get_generator(false, n);
|
||||
buckets_inited[bucket_id] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// still the first loop (continued)
|
||||
for (size_t n = 0; n < h_scalars.size(); ++n)
|
||||
{
|
||||
for (size_t k = 0; k < K; ++k)
|
||||
{
|
||||
uint64_t l = h_scalars[n].get_bits((uint8_t)(k * c), c); // l in [0; 2^c-1]
|
||||
if (l != 0)
|
||||
{
|
||||
size_t bucket_id = l * K + k;
|
||||
if (buckets_inited[bucket_id])
|
||||
buckets[bucket_id] += CT::get_generator(true, n);
|
||||
else
|
||||
{
|
||||
buckets[bucket_id] = CT::get_generator(true, n);
|
||||
buckets_inited[bucket_id] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the second loop
|
||||
for (size_t l = C - 1; l > 0; --l)
|
||||
{
|
||||
for (size_t k = 0; k < K; ++k)
|
||||
{
|
||||
size_t bucket_id = l * K + k;
|
||||
if (buckets_inited[bucket_id])
|
||||
{
|
||||
if (Sk_inited[k])
|
||||
Sk[k] += buckets[bucket_id];
|
||||
else
|
||||
{
|
||||
Sk[k] = buckets[bucket_id];
|
||||
Sk_inited[k] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (Sk_inited[k])
|
||||
{
|
||||
if (Gk_inited[k])
|
||||
Gk[k] += Sk[k];
|
||||
else
|
||||
{
|
||||
Gk[k] = Sk[k];
|
||||
Gk_inited[k] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the third loop: Horner’s rule
|
||||
point_t result = Gk_inited[K - 1] ? Gk[K - 1] : c_point_0;
|
||||
for (size_t k = K - 2; k != SIZE_MAX; --k)
|
||||
{
|
||||
result.modify_mul_pow_2(c);
|
||||
if (Gk_inited[k])
|
||||
result += Gk[k];
|
||||
}
|
||||
|
||||
result += summand;
|
||||
|
||||
if (!result.is_zero())
|
||||
{
|
||||
LOG_PRINT_L0("multiexp result is non zero: " << result);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Just switcher
|
||||
|
||||
template<typename CT>
|
||||
bool msm_and_check_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand)
|
||||
{
|
||||
//return msm_and_check_zero_naive<CT>(g_scalars, h_scalars, summand);
|
||||
return msm_and_check_zero_pippenger_v3<CT>(g_scalars, h_scalars, summand, 7);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace crypto
|
||||
|
|
@ -234,7 +234,7 @@ namespace crypto
|
|||
|
||||
const size_t m = std::max(static_cast<uint64_t>(1), constexpr_ceil_log_n(ring_size, n));
|
||||
const size_t N = constexpr_pow(m, n);
|
||||
const size_t mn = m * n;
|
||||
//const size_t mn = m * n;
|
||||
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.Pk.size() == m, 1);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.f.size() == m * (n - 1), 2);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,14 @@ namespace crypto
|
|||
// Disclaimer: shouldn't be used in production code until the security proofs and the code are peer-reviewed.
|
||||
//
|
||||
|
||||
// m+2 group elements, m(n-1)+2 field elements
|
||||
// m+2 group elements, m(n-1)+2 field elements.
|
||||
// Assuming fixed n=4, m = log4(ring_sz) the size is (log4(ring_sz) + 2) group elements and (3*log4(ring_sz) + 2) or, in total, (4*log4(ring_sz) + 4) 32-bytes words
|
||||
|
||||
// ring_sz = m (inputs number)
|
||||
// sig_count = k (outputs number)
|
||||
// thus:
|
||||
// k * (log4(m) + 2) group elements and k * (3*log4(m) + 2) field elements
|
||||
|
||||
struct BGE_proof
|
||||
{
|
||||
public_key A; // premultiplied by 1/8
|
||||
|
|
|
|||
|
|
@ -716,7 +716,7 @@ namespace crypto
|
|||
|
||||
point_t GH_exponents = c_point_0;
|
||||
CT::calc_pedersen_commitment(G_scalar, H_scalar, GH_exponents);
|
||||
bool result = multiexp_and_check_being_zero<CT>(g_scalars, h_scalars, summand + GH_exponents);
|
||||
bool result = msm_and_check_zero<CT>(g_scalars, h_scalars, summand + GH_exponents);
|
||||
if (result)
|
||||
DBG_PRINT(ENDL << " . . . . bpp_verify() -- SUCCEEDED!!!" << ENDL);
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -734,7 +734,7 @@ namespace crypto
|
|||
|
||||
point_t GH_exponents = c_point_0;
|
||||
CT::calc_pedersen_commitment_2(G_scalar, H_scalar, H2_scalar, GH_exponents);
|
||||
bool result = multiexp_and_check_being_zero<CT>(g_scalars, h_scalars, summand + GH_exponents);
|
||||
bool result = msm_and_check_zero<CT>(g_scalars, h_scalars, summand + GH_exponents);
|
||||
if (result)
|
||||
DBG_PRINT(ENDL << " . . . . bppe_verify() -- SUCCEEDED!!!" << ENDL);
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace crypto
|
|||
////////////////////////////////////////
|
||||
struct bpp_ct_generators_HGX
|
||||
{
|
||||
// NOTE! This notation follows the original BP+ whitepaper, see mapping to Zano's generators below
|
||||
// NOTE! This notation follows the original BP+ whitepaper, see mapping to Zano's generators in range_proofs.cpp
|
||||
static const point_t& bpp_G;
|
||||
static const point_t& bpp_H;
|
||||
static const point_t& bpp_H2;
|
||||
|
|
@ -49,7 +49,7 @@ namespace crypto
|
|||
|
||||
struct bpp_ct_generators_UGX
|
||||
{
|
||||
// NOTE! This notation follows the original BP+ whitepaper, see mapping to Zano's generators below
|
||||
// NOTE! This notation follows the original BP+ whitepaper, see mapping to Zano's generators in range_proofs.cpp
|
||||
static const point_t& bpp_G;
|
||||
static const point_t& bpp_H;
|
||||
static const point_t& bpp_H2;
|
||||
|
|
@ -138,32 +138,11 @@ namespace crypto
|
|||
|
||||
typedef bpp_crypto_trait_zano<bpp_ct_generators_HGX, 128, 16> bpp_crypto_trait_Zarcanum;
|
||||
|
||||
|
||||
// efficient multiexponentiation (naive stub implementation atm, TODO)
|
||||
template<typename CT>
|
||||
bool multiexp_and_check_being_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(g_scalars.size() <= CT::c_bpp_mn_max, false, "g_scalars oversized");
|
||||
CHECK_AND_ASSERT_MES(h_scalars.size() <= CT::c_bpp_mn_max, false, "h_scalars oversized");
|
||||
|
||||
point_t result = summand;
|
||||
|
||||
for (size_t i = 0; i < g_scalars.size(); ++i)
|
||||
result += g_scalars[i] * CT::get_generator(false, i);
|
||||
|
||||
for (size_t i = 0; i < h_scalars.size(); ++i)
|
||||
result += h_scalars[i] * CT::get_generator(true, i);
|
||||
|
||||
if (!result.is_zero())
|
||||
{
|
||||
LOG_PRINT_L0("multiexp result is non zero: " << result);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace crypto
|
||||
|
||||
#include "epee/include/profile_tools.h" // <- remove this, sowle
|
||||
|
||||
#include "msm.h"
|
||||
#include "range_proof_bpp.h"
|
||||
#include "range_proof_bppe.h"
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ namespace crypto
|
|||
TRY_ENTRY()
|
||||
{
|
||||
DBG_PRINT("zarcanum_verify_proof");
|
||||
bool r = false;
|
||||
//bool r = false;
|
||||
|
||||
//std::cout << "===== zarcanum_verify_proof =====" << ENDL
|
||||
// << "m: " << m << ENDL
|
||||
|
|
|
|||
|
|
@ -126,6 +126,9 @@ namespace crypto
|
|||
template<generator_tag gen>
|
||||
inline bool verify_schnorr_sig(const hash& m, const public_key& A, const generic_schnorr_sig& sig) noexcept;
|
||||
|
||||
// TODO @#@# make optimized version inline bool verify_schnorr_sig(const hash& m, const point_t& A, const generic_schnorr_sig& sig) noexcept;
|
||||
// and change check_tx_balance() accordingly
|
||||
|
||||
template<>
|
||||
inline bool verify_schnorr_sig<gt_G>(const hash& m, const public_key& A, const generic_schnorr_sig& sig) noexcept
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1345,7 +1345,12 @@ bool blockchain_storage::validate_miner_transaction(const block& b,
|
|||
return false;
|
||||
}
|
||||
|
||||
uint64_t block_reward = base_reward + fee;
|
||||
uint64_t block_reward = base_reward;
|
||||
// before HF4: add tx fee to the block reward; after HF4: burn it
|
||||
if (b.miner_tx.version < TRANSACTION_VERSION_POST_HF4)
|
||||
{
|
||||
block_reward += fee;
|
||||
}
|
||||
|
||||
crypto::hash tx_id_for_post_hf4_era = b.miner_tx.version > TRANSACTION_VERSION_PRE_HF4 ? get_transaction_hash(b.miner_tx) : null_hash;
|
||||
if (!check_tx_balance(b.miner_tx, tx_id_for_post_hf4_era, block_reward))
|
||||
|
|
@ -1360,13 +1365,10 @@ bool blockchain_storage::validate_miner_transaction(const block& b,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (b.miner_tx.version > TRANSACTION_VERSION_PRE_HF4)
|
||||
if (!verify_asset_surjection_proof(b.miner_tx, tx_id_for_post_hf4_era))
|
||||
{
|
||||
if (!verify_asset_surjection_proof(b.miner_tx, tx_id_for_post_hf4_era))
|
||||
{
|
||||
LOG_ERROR("asset surjection proof verification failed for miner tx");
|
||||
return false;
|
||||
}
|
||||
LOG_ERROR("asset surjection proof verification failed for miner tx");
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_PRINT_MAGENTA("Mining tx verification ok, blocks_size_median = " << blocks_size_median, LOG_LEVEL_2);
|
||||
|
|
@ -1522,6 +1524,7 @@ bool blockchain_storage::create_block_template(const create_block_template_param
|
|||
stakeholder_address,
|
||||
b.miner_tx,
|
||||
resp.block_reward_without_fee,
|
||||
resp.block_reward,
|
||||
get_tx_version(height, m_core_runtime_config.hard_forks),
|
||||
ex_nonce,
|
||||
CURRENCY_MINER_TX_MAX_OUTS,
|
||||
|
|
@ -2046,9 +2049,18 @@ bool blockchain_storage::is_reorganize_required(const block_extended_info& main_
|
|||
wide_difficulty_type main_pow_diff_begin = get_last_alt_x_block_cumulative_precise_adj_difficulty(alt_chain_type(), connection_point.height - 1, false);
|
||||
main_cumul_diff.pow_diff = main_pow_diff_end - main_pow_diff_begin;
|
||||
|
||||
//TODO: measurement of precise cumulative difficult
|
||||
boost::multiprecision::uint1024_t alt = get_a_to_b_relative_cumulative_difficulty(difficulty_pos_at_split_point, difficulty_pow_at_split_point, alt_cumul_diff, main_cumul_diff);
|
||||
boost::multiprecision::uint1024_t main = get_a_to_b_relative_cumulative_difficulty(difficulty_pos_at_split_point, difficulty_pow_at_split_point, main_cumul_diff, alt_cumul_diff);
|
||||
boost::multiprecision::uint1024_t alt = 0;
|
||||
boost::multiprecision::uint1024_t main = 0;
|
||||
if (m_core_runtime_config.is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, alt_chain_bei.height))
|
||||
{
|
||||
alt = get_a_to_b_relative_cumulative_difficulty(difficulty_pos_at_split_point, difficulty_pow_at_split_point, alt_cumul_diff, main_cumul_diff);
|
||||
main = get_a_to_b_relative_cumulative_difficulty(difficulty_pos_at_split_point, difficulty_pow_at_split_point, main_cumul_diff, alt_cumul_diff);
|
||||
}
|
||||
else
|
||||
{
|
||||
alt = get_a_to_b_relative_cumulative_difficulty(difficulty_pos_at_split_point, difficulty_pow_at_split_point, alt_cumul_diff, main_cumul_diff);
|
||||
main = get_a_to_b_relative_cumulative_difficulty(difficulty_pos_at_split_point, difficulty_pow_at_split_point, main_cumul_diff, alt_cumul_diff);
|
||||
}
|
||||
LOG_PRINT_L1("[FORK_CHOICE]: " << ENDL
|
||||
<< "difficulty_pow_at_split_point:" << difficulty_pow_at_split_point << ENDL
|
||||
<< "difficulty_pos_at_split_point:" << difficulty_pos_at_split_point << ENDL
|
||||
|
|
@ -2065,6 +2077,21 @@ bool blockchain_storage::is_reorganize_required(const block_extended_info& main_
|
|||
return false;
|
||||
else
|
||||
{
|
||||
if (is_hardfork_active(ZANO_HARDFORK_04_ZARCANUM))
|
||||
{
|
||||
// prefer blocks with more summary fee(to motivate stakers include transactions)
|
||||
|
||||
// since we don't have "summary block fee" field yet, we can use this_block_tx_fee_median multiplied to transactions
|
||||
// count as an indirect measure of sumarry paid fee. If this approach won't be doing it's job it's subject
|
||||
// to reconsider and introducing additional field in block_extended_info structure
|
||||
|
||||
if (alt_chain_bei.this_block_tx_fee_median * alt_chain_bei.bl.tx_hashes.size() >
|
||||
main_chain_bei.this_block_tx_fee_median * main_chain_bei.bl.tx_hashes.size())
|
||||
{
|
||||
//with the rest equal, alt block has more fees in it, prefer it
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!is_pos_block(main_chain_bei.bl))
|
||||
return false; // do not reorganize on the same cummul diff if it's a PoW block
|
||||
|
||||
|
|
@ -2660,6 +2687,215 @@ bool blockchain_storage::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDO
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::get_target_outs_for_amount_prezarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const
|
||||
{
|
||||
size_t decoys_count = details.offsets.size();
|
||||
uint64_t amount = details.amount;
|
||||
|
||||
uint64_t outs_container_size = m_db_outputs.get_item_size(details.amount);
|
||||
if (!outs_container_size)
|
||||
{
|
||||
LOG_ERROR("COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS: not outs for amount " << amount << ", wallet should use some real outs when it lookup for some mix, so, at least one out for this amount should exist");
|
||||
return false;//actually this is strange situation, wallet should use some real outs when it lookup for some mix, so, at least one out for this amount should exist
|
||||
}
|
||||
//it is not good idea to use top fresh outs, because it increases possibility of transaction canceling on split
|
||||
//lets find upper bound of not fresh outs
|
||||
size_t up_index_limit = 0;
|
||||
auto it_limit = amounts_to_up_index_limit_cache.find(amount);
|
||||
if (it_limit == amounts_to_up_index_limit_cache.end())
|
||||
{
|
||||
up_index_limit = find_end_of_allowed_index(amount);
|
||||
amounts_to_up_index_limit_cache[up_index_limit];
|
||||
}
|
||||
else
|
||||
{
|
||||
up_index_limit = it_limit->second;
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(up_index_limit <= outs_container_size, false, "internal error: find_end_of_allowed_index returned wrong index=" << up_index_limit << ", with amount_outs.size = " << outs_container_size);
|
||||
if (up_index_limit >= decoys_count)
|
||||
{
|
||||
std::set<size_t> used;
|
||||
used.insert(details.own_global_index);
|
||||
for (uint64_t j = 0; j != decoys_count || used.size() >= up_index_limit;)
|
||||
{
|
||||
size_t g_index_initial = crypto::rand<size_t>() % up_index_limit;
|
||||
size_t g_index = g_index_initial;
|
||||
//enumerate via whole loop from g_index to up_index_limit and then from 0 to g_index
|
||||
while (true)
|
||||
{
|
||||
if (!used.count(g_index))
|
||||
break;
|
||||
g_index++;
|
||||
|
||||
if (g_index >= up_index_limit)
|
||||
g_index = 0;
|
||||
if (g_index == g_index_initial)
|
||||
{
|
||||
// we enumerated full circle and couldn't find needed amount of outs
|
||||
LOG_PRINT_YELLOW("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << decoys_count << ", added " << result_outs.outs.size() << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total", LOG_LEVEL_0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool added = add_out_to_get_random_outs(result_outs, amount, g_index, decoys_count, req.use_forced_mix_outs, req.height_upper_limit);
|
||||
used.insert(g_index);
|
||||
if (added)
|
||||
++j;
|
||||
}
|
||||
if (result_outs.outs.size() < decoys_count)
|
||||
{
|
||||
LOG_PRINT_YELLOW("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << decoys_count << ", added " << result_outs.outs.size() << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total", LOG_LEVEL_0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t added = 0;
|
||||
for (size_t i = 0; i != up_index_limit; i++)
|
||||
added += add_out_to_get_random_outs(result_outs, amount, i, decoys_count, req.use_forced_mix_outs, req.height_upper_limit) ? 1 : 0;
|
||||
LOG_PRINT_YELLOW("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << decoys_count << ", added " << added << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total - respond with all good outs", LOG_LEVEL_0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::get_target_outs_for_postzarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const
|
||||
{
|
||||
std::set<uint64_t> used;
|
||||
used.insert(details.own_global_index);
|
||||
for (auto offset : details.offsets)
|
||||
{
|
||||
|
||||
//perfectly we would need to find transaction's output on the given height, with the given probability
|
||||
//of being coinbase(coinbase outputs should be included less in decoy selection algorithm)
|
||||
bool is_coinbase = (crypto::rand<uint64_t>() % 101) > req.coinbase_percents ? false : true;
|
||||
|
||||
//TODO: Consider including PoW coinbase to transactions(does it needed?)
|
||||
|
||||
// convert offset to estimated height
|
||||
uint64_t estimated_h = this->get_current_blockchain_size() - 1 - offset;
|
||||
//make sure it's after zc hardfork
|
||||
if (estimated_h < m_core_runtime_config.hard_forks.m_height_the_hardfork_n_active_after[ZANO_HARDFORK_04_ZARCANUM])
|
||||
{
|
||||
LOG_ERROR("Wrong estimated offset(" << offset << "), it hits zone before zarcanum hardfork");
|
||||
return false;
|
||||
}
|
||||
|
||||
#define TARGET_RANDOM_OUTS_SELECTIOM_POOL_MIN 10
|
||||
//try to find output around given H
|
||||
std::vector<uint64_t> selected_global_indexes;
|
||||
auto process_tx = [&](const crypto::hash& tx_id) {
|
||||
|
||||
auto tx_ptr = m_db_transactions.find(tx_id);
|
||||
CHECK_AND_ASSERT_THROW_MES(tx_ptr, "internal error: tx_id " << tx_id << " around estimated_h = " << estimated_h << " not found in db");
|
||||
//go through tx outputs
|
||||
for (size_t i = 0; i != tx_ptr->tx.vout.size(); i++)
|
||||
{
|
||||
if (tx_ptr->tx.vout[i].type() != typeid(tx_out_zarcanum))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const tx_out_zarcanum& z_out = boost::get<tx_out_zarcanum>(tx_ptr->tx.vout[i]);
|
||||
|
||||
// NOTE: second part of condition (mix_attr >= CURRENCY_TO_KEY_OUT_FORCED_MIX_LOWER_BOUND && ..) might be not accurate
|
||||
// since the wallet might want to request more inputs then it planning to do mixins. For now let's keep it this way and fix
|
||||
// it if we see the problems about it.
|
||||
if (z_out.mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX || (z_out.mix_attr >= CURRENCY_TO_KEY_OUT_FORCED_MIX_LOWER_BOUND && z_out.mix_attr < details.offsets.size()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip spent outptus
|
||||
if (tx_ptr->m_spent_flags[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (used.find(tx_ptr->m_global_output_indexes[i]) != used.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// add output
|
||||
// note: code that will process selected_global_indes will be revisiting transactions entries to obtain all
|
||||
// needed data, that should work relatively effective because of on-top-of-db cache keep daya unserialized
|
||||
selected_global_indexes.push_back(tx_ptr->m_global_output_indexes[i]);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
while (selected_global_indexes.size() < TARGET_RANDOM_OUTS_SELECTIOM_POOL_MIN)
|
||||
{
|
||||
auto block_ptr = m_db_blocks.get(estimated_h);
|
||||
if (is_coinbase && is_pos_block(block_ptr->bl) )
|
||||
{
|
||||
process_tx(get_transaction_hash(block_ptr->bl.miner_tx));
|
||||
}
|
||||
else
|
||||
{
|
||||
//looking for regular output of regular transactions
|
||||
for (auto tx_id : block_ptr->bl.tx_hashes)
|
||||
{
|
||||
process_tx(tx_id);
|
||||
}
|
||||
}
|
||||
if(estimated_h)
|
||||
estimated_h--;
|
||||
else
|
||||
{
|
||||
//likely unusual situation when blocks enumerated all way back to genesis
|
||||
//let's check if we have at least something
|
||||
if (!selected_global_indexes.size())
|
||||
{
|
||||
//need to regenerate offsets
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//pick up a random output from selected_global_indes
|
||||
uint64_t global_index = selected_global_indexes[crypto::rand<uint64_t>() % selected_global_indexes.size()];
|
||||
bool res = add_out_to_get_random_outs(result_outs, details.amount, global_index, details.offsets.size(), req.use_forced_mix_outs, req.height_upper_limit);
|
||||
CHECK_AND_ASSERT_THROW_MES(res, "Failed to add_out_to_get_random_outs([" << global_index << "]) at postzarcanum era");
|
||||
used.insert(global_index);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::get_random_outs_for_amounts2(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res)const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
LOG_PRINT_L3("[get_random_outs_for_amounts] amounts: " << req.amounts.size());
|
||||
std::map<uint64_t, uint64_t> amounts_to_up_index_limit_cache;
|
||||
uint64_t count_zarcanum_blocks = 0;
|
||||
if(is_hardfork_active(ZANO_HARDFORK_04_ZARCANUM))
|
||||
count_zarcanum_blocks = this->get_current_blockchain_size() - m_core_runtime_config.hard_forks.m_height_the_hardfork_n_active_after[ZANO_HARDFORK_04_ZARCANUM];
|
||||
|
||||
|
||||
for (size_t i = 0; i != req.amounts.size(); i++)
|
||||
{
|
||||
uint64_t amount = req.amounts[i].amount;
|
||||
//const std::vector<uint64_t>& offsets = req.amounts[i].offsets;
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs = *res.outs.insert(res.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount());
|
||||
result_outs.amount = amount;
|
||||
|
||||
bool r = false;
|
||||
if (amount == 0 && count_zarcanum_blocks > 20000)
|
||||
{
|
||||
//zarcanum era inputs
|
||||
r = get_target_outs_for_postzarcanum(req, req.amounts[i], result_outs, amounts_to_up_index_limit_cache);
|
||||
}
|
||||
else
|
||||
{
|
||||
//zarcanum era inputs
|
||||
r = get_target_outs_for_amount_prezarcanum(req, req.amounts[i], result_outs, amounts_to_up_index_limit_cache);
|
||||
}
|
||||
if (!r)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
boost::multiprecision::uint128_t blockchain_storage::total_coins() const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
|
@ -4096,6 +4332,7 @@ uint64_t blockchain_storage::get_tx_fee_median() const
|
|||
//------------------------------------------------------------------
|
||||
uint64_t blockchain_storage::get_alias_coast(const std::string& alias) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
uint64_t median_fee = get_tx_fee_median();
|
||||
//CHECK_AND_ASSERT_MES_NO_RET(median_fee, "can't calculate median");
|
||||
|
||||
|
|
@ -4106,9 +4343,29 @@ uint64_t blockchain_storage::get_alias_coast(const std::string& alias) const
|
|||
return get_alias_coast_from_fee(alias, median_fee);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
uint64_t blockchain_storage::get_tx_fee_window_value_median() const
|
||||
{
|
||||
// calc it every time and cache it so it won't recalculated before next block
|
||||
// it's effective because it's not affect sync time and needed only when node is synced
|
||||
// and processing transactions
|
||||
|
||||
misc_utils::median_helper<uint64_t, uint64_t> mh;
|
||||
for (uint64_t i = 0; i < CORE_FEE_BLOCKS_LOOKUP_WINDOW; i++)
|
||||
{
|
||||
uint64_t h = m_db_blocks.size() - 1 - i;
|
||||
if (h >= m_db_blocks.size())
|
||||
break;
|
||||
|
||||
auto block_ptr = m_db_blocks[h];
|
||||
CHECK_AND_ASSERT_THROW_MES(block_ptr, "Unexpected missing block " << h << " in get_tx_fee_window_value_median");
|
||||
mh.push_item(block_ptr->block_cumulative_size, 0);
|
||||
}
|
||||
|
||||
return (mh.get_median() + mh.get_avg())/2;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::unprocess_blockchain_tx_attachments(const transaction& tx, uint64_t h, uint64_t timestamp)
|
||||
{
|
||||
|
||||
size_t cnt_serv_attach = get_service_attachments_count_in_tx(tx);
|
||||
if (cnt_serv_attach == 0)
|
||||
return true;
|
||||
|
|
@ -4420,7 +4677,7 @@ uint64_t blockchain_storage::tx_fee_median_for_height(uint64_t h)const
|
|||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::validate_all_aliases_for_new_median_mode()
|
||||
{
|
||||
LOG_PRINT_L0("Started reinitialization of median fee...");
|
||||
LOG_PRINT_L0("Started reinitialization of median fee...");
|
||||
math_helper::once_a_time_seconds<10> log_idle;
|
||||
uint64_t sz = m_db_blocks.size();
|
||||
for (uint64_t i = 0; i != sz; i++)
|
||||
|
|
@ -4536,7 +4793,7 @@ bool blockchain_storage::print_tx_outputs_lookup(const crypto::hash& tx_id)const
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool check_tx_explicit_asset_id_rules(const transaction& tx, bool all_tx_ins_have_explicit_asset_ids)
|
||||
bool check_tx_explicit_asset_id_rules(const transaction& tx, bool all_tx_ins_have_explicit_native_asset_ids)
|
||||
{
|
||||
if (tx.version <= TRANSACTION_VERSION_PRE_HF4)
|
||||
return true;
|
||||
|
|
@ -4544,13 +4801,13 @@ bool check_tx_explicit_asset_id_rules(const transaction& tx, bool all_tx_ins_hav
|
|||
// ( assuming that post-HF4 txs can only have tx_out_zarcanum outs )
|
||||
|
||||
bool r = false;
|
||||
// if all tx inputs have explicit asset id AND it does not emit a new asset THEN all outputs must have explicit asset id (native coin)
|
||||
if (all_tx_ins_have_explicit_asset_ids && !is_asset_emitting_transaction(tx))
|
||||
// if all tx inputs have explicit native asset id AND it does not emit a new asset THEN all outputs must have explicit asset id (native coin)
|
||||
if (all_tx_ins_have_explicit_native_asset_ids && !is_asset_emitting_transaction(tx))
|
||||
{
|
||||
for(size_t j = 0, k = tx.vout.size(); j < k; ++j)
|
||||
{
|
||||
r = crypto::point_t(boost::get<tx_out_zarcanum>(tx.vout[j]).blinded_asset_id).modify_mul8().to_public_key() == native_coin_asset_id;
|
||||
CHECK_AND_ASSERT_MES(r, false, "output #" << j << " has a non-explicit asset id");
|
||||
CHECK_AND_ASSERT_MES(r, false, "output #" << j << " has a non-explicit asset id in a tx where all inputs have an explicit native asset id");
|
||||
}
|
||||
}
|
||||
else // otherwise all outputs must have hidden asset id (unless they burn money by sending them to null pubkey)
|
||||
|
|
@ -4559,7 +4816,7 @@ bool check_tx_explicit_asset_id_rules(const transaction& tx, bool all_tx_ins_hav
|
|||
{
|
||||
const tx_out_zarcanum& zo = boost::get<tx_out_zarcanum>(tx.vout[j]);
|
||||
r = zo.stealth_address == null_pkey || crypto::point_t(zo.blinded_asset_id).modify_mul8().to_public_key() != native_coin_asset_id;
|
||||
CHECK_AND_ASSERT_MES(r, false, "output #" << j << " has an explicit asset id");
|
||||
CHECK_AND_ASSERT_MES(r, false, "output #" << j << " has an explicit asset id in a tx where not all inputs have an explicit native asset id");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -4605,7 +4862,7 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
|
|||
{
|
||||
size_t sig_index = 0;
|
||||
max_used_block_height = 0;
|
||||
bool all_tx_ins_have_explicit_asset_ids = true;
|
||||
bool all_tx_ins_have_explicit_native_asset_ids = true;
|
||||
|
||||
auto local_check_key_image = [&](const crypto::key_image& ki) -> bool
|
||||
{
|
||||
|
|
@ -4667,7 +4924,7 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
|
|||
if (!local_check_key_image(in_zc.k_image))
|
||||
return false;
|
||||
|
||||
if (!check_tx_input(tx, sig_index, in_zc, tx_prefix_hash, max_used_block_height, all_tx_ins_have_explicit_asset_ids))
|
||||
if (!check_tx_input(tx, sig_index, in_zc, tx_prefix_hash, max_used_block_height, all_tx_ins_have_explicit_native_asset_ids))
|
||||
{
|
||||
LOG_ERROR("Failed to validate zc input #" << sig_index << " in tx: " << tx_prefix_hash);
|
||||
return false;
|
||||
|
|
@ -4690,7 +4947,7 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
|
|||
CHECK_AND_ASSERT_MES(r, false, "Failed to validate attachments in tx " << tx_prefix_hash << ": incorrect extra_attachment_info in tx.extra");
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(check_tx_explicit_asset_id_rules(tx, all_tx_ins_have_explicit_asset_ids), false, "tx does not comply with explicit asset id rules");
|
||||
CHECK_AND_ASSERT_MES(check_tx_explicit_asset_id_rules(tx, all_tx_ins_have_explicit_native_asset_ids), false, "tx does not comply with explicit asset id rules");
|
||||
}
|
||||
TIME_MEASURE_FINISH_PD(tx_check_inputs_attachment_check);
|
||||
return true;
|
||||
|
|
@ -5074,7 +5331,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
|
|||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_zc_input& zc_in, const crypto::hash& tx_prefix_hash,
|
||||
uint64_t& max_related_block_height, bool& all_tx_ins_have_explicit_asset_ids) const
|
||||
uint64_t& max_related_block_height, bool& all_tx_ins_have_explicit_native_asset_ids) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
|
|
@ -5107,8 +5364,8 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
|
|||
for(auto& zc_out : scan_contex.zc_outs)
|
||||
{
|
||||
ring.emplace_back(zc_out.stealth_address, zc_out.amount_commitment, zc_out.blinded_asset_id);
|
||||
if (all_tx_ins_have_explicit_asset_ids && crypto::point_t(zc_out.blinded_asset_id).modify_mul8().to_public_key() != native_coin_asset_id)
|
||||
all_tx_ins_have_explicit_asset_ids = false;
|
||||
if (all_tx_ins_have_explicit_native_asset_ids && crypto::point_t(zc_out.blinded_asset_id).modify_mul8().to_public_key() != native_coin_asset_id)
|
||||
all_tx_ins_have_explicit_native_asset_ids = false;
|
||||
}
|
||||
|
||||
// calculate corresponding tx prefix hash
|
||||
|
|
@ -5587,9 +5844,12 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti
|
|||
return false;
|
||||
}
|
||||
|
||||
size_t count_ado = 0;
|
||||
//extra
|
||||
for (const auto el : tx.extra)
|
||||
{
|
||||
if (el.type() == typeid(asset_descriptor_operation))
|
||||
count_ado++;
|
||||
if (!var_is_after_hardfork_1_zone && !is_allowed_before_hardfork1(el))
|
||||
return false;
|
||||
if (!var_is_after_hardfork_2_zone && !is_allowed_before_hardfork2(el))
|
||||
|
|
@ -5614,18 +5874,38 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti
|
|||
|
||||
// TODO @#@# consider: 1) tx.proofs, 2) new proof data structures
|
||||
|
||||
|
||||
if (var_is_after_hardfork_4_zone)
|
||||
{
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(tx.version > TRANSACTION_VERSION_PRE_HF4, false, "HF4: tx with version " << tx.version << " is not allowed");
|
||||
CHECK_AND_ASSERT_MES(tx.vout.size() >= CURRENCY_TX_MIN_ALLOWED_OUTS, false, "HF4: tx.vout has " << tx.vout.size() << " element(s), while required minimum is " << CURRENCY_TX_MIN_ALLOWED_OUTS);
|
||||
|
||||
if (is_pos_miner_tx(tx))
|
||||
CHECK_AND_ASSERT_MES(tx.vout.size() == 1 || tx.vout.size() >= CURRENCY_TX_MIN_ALLOWED_OUTS, false, "HF4: tx.vout has " << tx.vout.size() << " element(s), while 1 or >= " << CURRENCY_TX_MIN_ALLOWED_OUTS << " is expected for a PoS miner tx");
|
||||
else
|
||||
CHECK_AND_ASSERT_MES(tx.vout.size() >= CURRENCY_TX_MIN_ALLOWED_OUTS, false, "HF4: tx.vout has " << tx.vout.size() << " element(s), while required minimum is " << CURRENCY_TX_MIN_ALLOWED_OUTS);
|
||||
|
||||
if(!validate_inputs_sorting(tx))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool mode_separate = get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE? true:false;
|
||||
if (is_coinbase(tx) && mode_separate)
|
||||
{
|
||||
LOG_ERROR("TX_FLAG_SIGNATURE_MODE_SEPARATE not allowed for coinbase tx");
|
||||
return false;
|
||||
}
|
||||
if (count_ado > 1)
|
||||
{
|
||||
LOG_ERROR("More then 1 asset_descriptor_operation not allowed in tx");
|
||||
return false;
|
||||
}
|
||||
if (mode_separate && count_ado > 0)
|
||||
{
|
||||
LOG_ERROR("asset_descriptor_operation not allowed in tx with TX_FLAG_SIGNATURE_MODE_SEPARATE");
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
@ -5697,10 +5977,12 @@ bool blockchain_storage::validate_pos_block(const block& b,
|
|||
CHECK_AND_ASSERT_MES(b.miner_tx.vin[1].type() == typeid(txin_to_key) || b.miner_tx.vin[1].type() == typeid(txin_zc_input), false, "incorrect input 1 type: " << b.miner_tx.vin[1].type().name());
|
||||
const crypto::key_image& stake_key_image = get_key_image_from_txin_v(b.miner_tx.vin[1]);
|
||||
//check keyimage if it's main chain candidate
|
||||
TIME_MEASURE_START_PD(pos_validate_ki_search);
|
||||
if (!for_altchain)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(!have_tx_keyimg_as_spent(stake_key_image), false, "stake key image has been already spent in blockchain: " << stake_key_image);
|
||||
}
|
||||
TIME_MEASURE_FINISH_PD(pos_validate_ki_search);
|
||||
|
||||
if (!is_hardfork_active(ZANO_HARDFORK_04_ZARCANUM))
|
||||
{
|
||||
|
|
@ -5735,8 +6017,10 @@ bool blockchain_storage::validate_pos_block(const block& b,
|
|||
CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1, false, "incorrect number of stake input signatures: " << b.miner_tx.signatures.size());
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.signatures[0].type() == typeid(zarcanum_sig), false, "incorrect sig 0 type: " << b.miner_tx.signatures[0].type().name());
|
||||
|
||||
//std::stringstream ss;
|
||||
if (!for_altchain)
|
||||
{
|
||||
TIME_MEASURE_START_PD(pos_validate_get_out_keys_for_inputs);
|
||||
// do general input check for main chain blocks only
|
||||
// TODO @#@#: txs in alternative PoS blocks (including miner_tx) must be validated by validate_alt_block_txs()
|
||||
const zarcanum_sig& sig = boost::get<zarcanum_sig>(b.miner_tx.signatures[0]);
|
||||
|
|
@ -5745,11 +6029,25 @@ bool blockchain_storage::validate_pos_block(const block& b,
|
|||
uint64_t dummy_source_max_unlock_time_for_pos_coinbase_dummy = 0; // won't be used
|
||||
scan_for_keys_context scan_contex = AUTO_VAL_INIT(scan_contex);
|
||||
r = get_output_keys_for_input_with_checks(b.miner_tx, stake_input, dummy_output_keys, max_related_block_height, dummy_source_max_unlock_time_for_pos_coinbase_dummy, scan_contex);
|
||||
|
||||
//#define ADD_ITEM_TO_SS(item) ss << " " #item ": " << m_performance_data.item.get_last_val() << ENDL
|
||||
// ADD_ITEM_TO_SS(tx_check_inputs_loop_scan_outputkeys_get_item_size);
|
||||
// ADD_ITEM_TO_SS(tx_check_inputs_loop_scan_outputkeys_relative_to_absolute);
|
||||
// ADD_ITEM_TO_SS(tx_check_inputs_loop_scan_outputkeys_loop);
|
||||
// ADD_ITEM_TO_SS(tx_check_inputs_loop_scan_outputkeys_loop_iteration);
|
||||
// ss << " tx_check_inputs_loop_scan_outputkeys_loop_iteration (avg): " << m_performance_data.tx_check_inputs_loop_scan_outputkeys_loop_iteration.get_avg() << ENDL;
|
||||
// ADD_ITEM_TO_SS(tx_check_inputs_loop_scan_outputkeys_loop_get_subitem);
|
||||
// ADD_ITEM_TO_SS(tx_check_inputs_loop_scan_outputkeys_loop_find_tx);
|
||||
// ADD_ITEM_TO_SS(tx_check_inputs_loop_scan_outputkeys_loop_handle_output);
|
||||
//#undef ADD_ITEM_TO_SS
|
||||
|
||||
CHECK_AND_ASSERT_MES(r, false, "get_output_keys_for_input_with_checks failed for stake input");
|
||||
CHECK_AND_ASSERT_MES(scan_contex.zc_outs.size() == stake_input.key_offsets.size(), false, "incorrect number of referenced outputs found: " << scan_contex.zc_outs.size() << ", while " << stake_input.key_offsets.size() << " is expected.");
|
||||
// make sure that all referring inputs are either older then, or the same age as, the most resent PoW block.
|
||||
CHECK_AND_ASSERT_MES(max_related_block_height <= last_pow_block_height, false, "stake input refs' max related block height is " << max_related_block_height << " while last PoW block height is " << last_pow_block_height);
|
||||
|
||||
TIME_MEASURE_FINISH_PD(pos_validate_get_out_keys_for_inputs);
|
||||
|
||||
// build a ring of references
|
||||
vector<crypto::CLSAG_GGXXG_input_ref_t> ring;
|
||||
ring.reserve(scan_contex.zc_outs.size());
|
||||
|
|
@ -5759,8 +6057,12 @@ bool blockchain_storage::validate_pos_block(const block& b,
|
|||
crypto::scalar_t last_pow_block_id_hashed = crypto::hash_helper_t::hs(CRYPTO_HDS_ZARCANUM_LAST_POW_HASH, sm.last_pow_id);
|
||||
|
||||
uint8_t err = 0;
|
||||
TIME_MEASURE_START_PD(pos_validate_zvp);
|
||||
r = crypto::zarcanum_verify_proof(id, kernel_hash, ring, last_pow_block_id_hashed, stake_input.k_image, basic_diff, sig, &err);
|
||||
TIME_MEASURE_FINISH_PD(pos_validate_zvp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "zarcanum_verify_proof failed with code " << (int)err);
|
||||
//std::stringstream ss;
|
||||
//std::cout << " validate_pos_block > get_output_keys_for_input_with_checks: " << ENDL << ss.str();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -6214,7 +6516,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
}
|
||||
TIME_MEASURE_FINISH_PD(tx_check_inputs_time);
|
||||
tx_total_inputs_processing_time += tx_check_inputs_time;
|
||||
tx_total_inputs_count++;
|
||||
tx_total_inputs_count += tx.vin.size();
|
||||
burned_coins += get_burned_amount(tx);
|
||||
|
||||
TIME_MEASURE_START_PD(tx_prapare_append);
|
||||
|
|
@ -6265,6 +6567,8 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
|
||||
if (!m_is_in_checkpoint_zone)
|
||||
{
|
||||
// validate_miner_transaction will check balance proof and asset surjection proof
|
||||
// and, as a side effect, it MAY recalculate base_reward, consider redisign, TODO -- sowle
|
||||
TIME_MEASURE_START_PD(validate_miner_transaction_time);
|
||||
if (!validate_miner_transaction(bl, cumulative_block_size, fee_summary, base_reward, already_generated_coins)) // TODO @#@# base_reward will be calculated once again, consider refactoring
|
||||
{
|
||||
|
|
@ -6345,11 +6649,12 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
bvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bei.cumulative_diff_adjusted += cumulative_diff_delta;
|
||||
//this used only in pre-hardfork 1
|
||||
bei.cumulative_diff_adjusted += cumulative_diff_delta;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// rebuild cumulative_diff_precise_adjusted for whole period
|
||||
// cumulative_diff_precise_adjusted - native cumulative difficulty adjusted ONLY by sequence_factor
|
||||
wide_difficulty_type diff_precise_adj = correct_difficulty_with_sequence_factor(sequence_factor, current_diffic);
|
||||
bei.cumulative_diff_precise_adjusted = last_x_h ? m_db_blocks[last_x_h]->cumulative_diff_precise_adjusted + diff_precise_adj : diff_precise_adj;
|
||||
|
||||
|
|
@ -6364,6 +6669,10 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
return false;
|
||||
}
|
||||
bei.already_generated_coins = already_generated_coins - burned_coins + base_reward;
|
||||
if (bei.bl.miner_tx.version >= TRANSACTION_VERSION_POST_HF4)
|
||||
{
|
||||
bei.already_generated_coins -= fee_summary;
|
||||
}
|
||||
|
||||
auto blocks_index_ptr = m_db_blocks_index.get(id);
|
||||
if (blocks_index_ptr)
|
||||
|
|
@ -6414,7 +6723,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
TIME_MEASURE_FINISH_PD_MS(block_processing_time_0_ms);
|
||||
|
||||
//print result
|
||||
stringstream powpos_str_entry, timestamp_str_entry;
|
||||
stringstream powpos_str_entry, timestamp_str_entry, pos_validation_str_entry;
|
||||
if (is_pos_bl)
|
||||
{ // PoS
|
||||
int64_t actual_ts = get_block_datetime(bei.bl); // signed int is intentionally used here
|
||||
|
|
@ -6428,6 +6737,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
else
|
||||
powpos_str_entry << "hidden";
|
||||
timestamp_str_entry << ", actual ts: " << actual_ts << " (diff: " << std::showpos << ts_diff << "s) block ts: " << std::noshowpos << bei.bl.timestamp << " (shift: " << std::showpos << static_cast<int64_t>(bei.bl.timestamp) - actual_ts << ")";
|
||||
pos_validation_str_entry << "(" << m_performance_data.pos_validate_ki_search.get_last_val() << "/" << m_performance_data.pos_validate_get_out_keys_for_inputs.get_last_val() << "/" << m_performance_data.pos_validate_zvp.get_last_val() << ")";
|
||||
}
|
||||
else
|
||||
{ // PoW
|
||||
|
|
@ -6442,23 +6752,41 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
LOG_PRINT_L1("+++++ BLOCK SUCCESSFULLY ADDED " << (is_pos_bl ? "[PoS]" : "[PoW]") << "["<< static_cast<uint64_t>(bei.bl.major_version) << "." << static_cast<uint64_t>(bei.bl.minor_version) << "] "<< " Sq: " << sequence_factor
|
||||
<< ENDL << "id:\t" << id << timestamp_str_entry.str()
|
||||
<< ENDL << powpos_str_entry.str()
|
||||
<< ENDL << "HEIGHT " << bei.height << ", difficulty: " << current_diffic << ", cumul_diff_precise: " << bei.cumulative_diff_precise << ", cumul_diff_adj: " << bei.cumulative_diff_adjusted << " (+" << cumulative_diff_delta << ")"
|
||||
<< ENDL << "HEIGHT " << bei.height << ", difficulty: " << current_diffic << ", cumul_diff_precise: " << bei.cumulative_diff_precise << ", cumul_diff_precise_adj: " << bei.cumulative_diff_precise_adjusted << " (+" << cumulative_diff_delta << ")"
|
||||
<< ENDL << "block reward: " << print_money_brief(base_reward + fee_summary) << " (" << print_money_brief(base_reward) << " + " << print_money_brief(fee_summary)
|
||||
<< ")" << ", coinbase_blob_size: " << coinbase_blob_size << ", cumulative size: " << cumulative_block_size << ", tx_count: " << bei.bl.tx_hashes.size()
|
||||
<< ", timing: " << block_processing_time_0_ms << "ms"
|
||||
<< "(micrsec:" << block_processing_time_1
|
||||
<< "(" << target_calculating_time_2 << "(" << m_performance_data.target_calculating_enum_blocks.get_last_val() << "/" << m_performance_data.target_calculating_calc.get_last_val() << ")"
|
||||
<< "/" << longhash_calculating_time_3
|
||||
<< "/" << longhash_calculating_time_3 << pos_validation_str_entry.str()
|
||||
<< "/" << insert_time_4
|
||||
<< "/" << all_txs_insert_time_5
|
||||
<< "/" << etc_stuff_6
|
||||
<< "/" << tx_total_inputs_processing_time << " of " << tx_total_inputs_count
|
||||
<< "/(" << m_performance_data.validate_miner_transaction_time.get_last_val() << "|"
|
||||
<< m_performance_data.collect_rangeproofs_data_from_tx_time.get_last_val() << "|"
|
||||
<< m_performance_data.verify_multiple_zc_outs_range_proofs_time.get_last_val()
|
||||
<< m_performance_data.verify_multiple_zc_outs_range_proofs_time.get_last_val() << "~"
|
||||
<< range_proofs_agregated.size()
|
||||
<< ")"
|
||||
<< "))");
|
||||
|
||||
{
|
||||
static epee::math_helper::average<uint64_t, 30> blocks_processing_time_avg_pos, blocks_processing_time_avg_pow;
|
||||
(is_pos_bl ? blocks_processing_time_avg_pos : blocks_processing_time_avg_pow).push(block_processing_time_0_ms);
|
||||
|
||||
static std::deque<uint64_t> blocks_processing_time_median_pos, blocks_processing_time_median_pow;
|
||||
std::deque<uint64_t>& d = (is_pos_bl ? blocks_processing_time_median_pos : blocks_processing_time_median_pow);
|
||||
d.push_back(block_processing_time_0_ms);
|
||||
if (d.size() > 200)
|
||||
d.pop_front();
|
||||
|
||||
uint64_t median_pow = epee::misc_utils::median(blocks_processing_time_median_pow);
|
||||
uint64_t median_pos = epee::misc_utils::median(blocks_processing_time_median_pos);
|
||||
|
||||
LOG_PRINT_YELLOW("last 30 blocks of type processing time (ms): PoW: " << std::setw(3) << (uint64_t)blocks_processing_time_avg_pow.get_avg() << ", PoS: " << (uint64_t)blocks_processing_time_avg_pos.get_avg(), LOG_LEVEL_1);
|
||||
LOG_PRINT_YELLOW("last 200 blocks of type processing time (median, ms): PoW: " << std::setw(3) << median_pow << ", PoS: " << median_pos, LOG_LEVEL_1);
|
||||
}
|
||||
|
||||
on_block_added(bei, id, block_summary_kimages);
|
||||
|
||||
bvc.m_added_to_main_chain = true;
|
||||
|
|
@ -7023,8 +7351,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
|
|||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
bool r = false;
|
||||
|
||||
if (p_max_related_block_height != nullptr)
|
||||
*p_max_related_block_height = 0;
|
||||
uint64_t max_related_block_height = 0;
|
||||
|
||||
CHECK_AND_ASSERT_MES(input_index < input_tx.vin.size(), false, "invalid input index: " << input_index);
|
||||
|
||||
|
|
@ -7271,7 +7598,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
|
|||
const txout_to_key& out_tk = boost::get<txout_to_key>(t);
|
||||
pk = out_tk.key;
|
||||
|
||||
bool mixattr_ok = is_mixattr_applicable_for_fake_outs_counter(out_tk.mix_attr, abs_key_offsets.size() - 1);
|
||||
bool mixattr_ok = is_mixattr_applicable_for_fake_outs_counter(p->tx.version, out_tk.mix_attr, abs_key_offsets.size() - 1, this->get_core_runtime_config());
|
||||
CHECK_AND_ASSERT_MES(mixattr_ok, false, "input offset #" << pk_n << " violates mixin restrictions: mix_attr = " << static_cast<uint32_t>(out_tk.mix_attr) << ", input's key_offsets.size = " << abs_key_offsets.size());
|
||||
|
||||
}
|
||||
|
|
@ -7285,8 +7612,8 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
|
|||
// case b4 (make sure source tx in the main chain is preceding split point, otherwise this referece is invalid)
|
||||
CHECK_AND_ASSERT_MES(p->m_keeper_block_height < split_height, false, "input offset #" << pk_n << " refers to main chain tx " << tx_id << " at height " << p->m_keeper_block_height << " while split height is " << split_height);
|
||||
|
||||
if (p_max_related_block_height != nullptr && *p_max_related_block_height < p->m_keeper_block_height)
|
||||
*p_max_related_block_height = p->m_keeper_block_height;
|
||||
if (max_related_block_height < p->m_keeper_block_height)
|
||||
max_related_block_height = p->m_keeper_block_height;
|
||||
|
||||
// TODO: consider checking p->tx for unlock time validity as it's checked in get_output_keys_for_input_with_checks()
|
||||
// make sure it was actually found
|
||||
|
|
@ -7332,6 +7659,20 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
|
|||
VARIANT_SWITCH_END();
|
||||
|
||||
|
||||
if (p_max_related_block_height != nullptr)
|
||||
*p_max_related_block_height = max_related_block_height;
|
||||
|
||||
uint64_t alt_bl_h = split_height + alt_chain.size() + 1;
|
||||
if (m_core_runtime_config.is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, alt_bl_h))
|
||||
{
|
||||
if (alt_bl_h - max_related_block_height < CURRENCY_HF4_MANDATORY_MIN_COINAGE)
|
||||
{
|
||||
LOG_ERROR("Coinage rule broken(altblock): h = " << alt_bl_h << ", max_related_block_height=" << max_related_block_height << ", tx: " << input_tx_hash);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: consider checking input_tx for valid extra attachment info as it's checked in check_tx_inputs()
|
||||
return true;
|
||||
}
|
||||
|
|
@ -7648,6 +7989,7 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha
|
|||
|
||||
CHECK_AND_ASSERT_MES(validate_tx_for_hardfork_specific_terms(b.miner_tx, null_hash, height), false, "miner tx hardfork-specific validation failed");
|
||||
|
||||
std::vector<uint64_t> fees;
|
||||
for (auto tx_id : b.tx_hashes)
|
||||
{
|
||||
std::shared_ptr<transaction> tx_ptr;
|
||||
|
|
@ -7659,6 +8001,9 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha
|
|||
const transaction& tx = it == abei.onboard_transactions.end() ? *tx_ptr : it->second;
|
||||
|
||||
CHECK_AND_ASSERT_MES(tx.signatures.size() == tx.vin.size(), false, "invalid tx: signatures.size() == " << tx.signatures.size() << ", tx.vin.size() == " << tx.vin.size());
|
||||
|
||||
fees.push_back(get_tx_fee(tx));
|
||||
|
||||
for (size_t n = 0; n < tx.vin.size(); ++n)
|
||||
{
|
||||
if (tx.vin[n].type() == typeid(txin_to_key) || tx.vin[n].type() == typeid(txin_htlc) || tx.vin[n].type() == typeid(txin_zc_input))
|
||||
|
|
@ -7691,6 +8036,7 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha
|
|||
update_alt_out_indexes_for_tx_in_block(tx, abei);
|
||||
}
|
||||
|
||||
abei.this_block_tx_fee_median = epee::misc_utils::median(fees);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,11 @@ namespace currency
|
|||
epee::math_helper::average<uint64_t, 5> target_calculating_enum_blocks;
|
||||
epee::math_helper::average<uint64_t, 5> target_calculating_calc;
|
||||
|
||||
//longhash_calculating_time_3
|
||||
epee::math_helper::average<uint64_t, 1> pos_validate_ki_search;
|
||||
epee::math_helper::average<uint64_t, 1> pos_validate_get_out_keys_for_inputs;
|
||||
epee::math_helper::average<uint64_t, 1> pos_validate_zvp;
|
||||
|
||||
//tx processing zone
|
||||
epee::math_helper::average<uint64_t, 1> tx_check_inputs_time;
|
||||
epee::math_helper::average<uint64_t, 1> tx_add_one_tx_time;
|
||||
|
|
@ -281,6 +286,7 @@ namespace currency
|
|||
bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp)const;
|
||||
bool handle_get_objects(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res)const;
|
||||
bool get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res)const;
|
||||
bool get_random_outs_for_amounts2(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res)const;
|
||||
bool get_backward_blocks_sizes(size_t from_height, std::vector<size_t>& sz, size_t count)const;
|
||||
bool get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<uint64_t>& indexs)const;
|
||||
bool get_alias_info(const std::string& alias, extra_alias_entry_base& info)const;
|
||||
|
|
@ -298,7 +304,7 @@ namespace currency
|
|||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_zc_input& zc_in, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, bool& tx_has_explicit_asset_ids_in_all_ins) const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_zc_input& zc_in, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, bool& all_tx_ins_have_explicit_native_asset_ids) const;
|
||||
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height)const;
|
||||
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash) const;
|
||||
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height, crypto::hash& max_used_block_id)const;
|
||||
|
|
@ -324,6 +330,7 @@ namespace currency
|
|||
boost::multiprecision::uint128_t total_coins()const;
|
||||
bool is_pos_allowed()const;
|
||||
uint64_t get_tx_fee_median()const;
|
||||
uint64_t get_tx_fee_window_value_median() const;
|
||||
uint64_t get_tx_expiration_median() const;
|
||||
uint64_t validate_alias_reward(const transaction& tx, const std::string& ai)const;
|
||||
void set_event_handler(i_core_event_handler* event_handler) const;
|
||||
|
|
@ -584,8 +591,8 @@ namespace currency
|
|||
mutable std::atomic<bool> m_deinit_is_done;
|
||||
mutable uint64_t m_blockchain_launch_timestamp;
|
||||
|
||||
bool init_tx_fee_median();
|
||||
bool update_tx_fee_median();
|
||||
//bool init_tx_fee_median();
|
||||
//bool update_tx_fee_median();
|
||||
void store_db_solo_options_values();
|
||||
bool set_lost_tx_unmixable();
|
||||
bool set_lost_tx_unmixable_for_height(uint64_t height);
|
||||
|
|
@ -636,6 +643,8 @@ namespace currency
|
|||
bool push_transaction_to_global_outs_index(const transaction& tx, const crypto::hash& tx_id, std::vector<uint64_t>& global_indexes);
|
||||
bool pop_transaction_from_global_index(const transaction& tx, const crypto::hash& tx_id);
|
||||
bool add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, uint64_t amount, size_t i, uint64_t mix_count, bool use_only_forced_to_mix = false, uint64_t height_upper_limit = 0) const;
|
||||
bool get_target_outs_for_amount_prezarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const;
|
||||
bool get_target_outs_for_postzarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const;
|
||||
bool add_block_as_invalid(const block& bl, const crypto::hash& h);
|
||||
bool add_block_as_invalid(const block_extended_info& bei, const crypto::hash& h);
|
||||
size_t find_end_of_allowed_index(uint64_t amount)const;
|
||||
|
|
@ -650,6 +659,7 @@ namespace currency
|
|||
uint64_t get_tx_fee_median_effective_index(uint64_t h) const;
|
||||
void on_abort_transaction();
|
||||
void load_targetdata_cache(bool is_pos) const;
|
||||
|
||||
|
||||
|
||||
uint64_t get_adjusted_time()const;
|
||||
|
|
@ -732,6 +742,8 @@ namespace currency
|
|||
template<class visitor_t>
|
||||
bool blockchain_storage::scan_outputkeys_for_indexes(const transaction &validated_tx, const txin_v& verified_input, visitor_t& vis, uint64_t& max_related_block_height, scan_for_keys_context& scan_context) const
|
||||
{
|
||||
bool hf4 = this->is_hardfork_active(ZANO_HARDFORK_04_ZARCANUM);
|
||||
|
||||
uint64_t amount = get_amount_from_variant(verified_input);
|
||||
const std::vector<txout_ref_v>& key_offsets = get_key_offsets_from_txin_v(verified_input);
|
||||
|
||||
|
|
@ -747,7 +759,7 @@ namespace currency
|
|||
TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_relative_to_absolute);
|
||||
TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop);
|
||||
size_t output_index = 0;
|
||||
for(const txout_ref_v& o : absolute_offsets)
|
||||
for (const txout_ref_v& o : absolute_offsets)
|
||||
{
|
||||
crypto::hash tx_id = null_hash;
|
||||
size_t n = 0;
|
||||
|
|
@ -802,8 +814,13 @@ namespace currency
|
|||
//fix for burned money
|
||||
patch_out_if_needed(const_cast<txout_to_key&>(outtk), tx_id, n);
|
||||
|
||||
bool mixattr_ok = is_mixattr_applicable_for_fake_outs_counter(outtk.mix_attr, key_offsets.size() - 1);
|
||||
CHECK_AND_ASSERT_MES(mixattr_ok, false, "tx input ref #" << output_index << " violates mixin restrictions: mix_attr = " << static_cast<uint32_t>(outtk.mix_attr) << ", key_offsets.size = " << key_offsets.size());
|
||||
bool mixattr_ok = is_mixattr_applicable_for_fake_outs_counter(tx_ptr->tx.version, outtk.mix_attr, key_offsets.size() - 1, this->get_core_runtime_config());
|
||||
CHECK_AND_ASSERT_MES(mixattr_ok, false, "tx input ref #" << output_index << " violates mixin restrictions: tx.version = " << tx_ptr->tx.version << ", mix_attr = " << static_cast<uint32_t>(outtk.mix_attr) << ", key_offsets.size = " << key_offsets.size());
|
||||
if (hf4)
|
||||
{
|
||||
bool legit_output_key = validate_output_key_legit(outtk.key);
|
||||
CHECK_AND_ASSERT_MES(legit_output_key, false, "tx input ref #" << output_index << " violates public key restrictions: tx.version = " << tx_ptr->tx.version << ", outtk.key = " << outtk.key);
|
||||
}
|
||||
}
|
||||
else if (o.target.type() == typeid(txout_htlc))
|
||||
{
|
||||
|
|
@ -823,6 +840,12 @@ namespace currency
|
|||
//HTLC IS expired, can be used ONLY by pkey_after_expiration and ONLY by to_key input
|
||||
scan_context.htlc_is_expired = true;
|
||||
}
|
||||
if (hf4)
|
||||
{
|
||||
bool legit_output_key = validate_output_key_legit(scan_context.htlc_is_expired ? htlc_out.pkey_refund : htlc_out.pkey_redeem);
|
||||
CHECK_AND_ASSERT_MES(legit_output_key, false, "tx input ref #" << output_index << " violates public key restrictions: tx.version = " << tx_ptr->tx.version << ", outtk.key = " << static_cast<const crypto::public_key&>(scan_context.htlc_is_expired ? htlc_out.pkey_refund : htlc_out.pkey_redeem));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -842,19 +865,23 @@ namespace currency
|
|||
}
|
||||
VARIANT_CASE_CONST(tx_out_zarcanum, out_zc)
|
||||
bool r = is_output_allowed_for_input(out_zc, verified_input);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Input and output are incompatible");
|
||||
CHECK_AND_ASSERT_MES(r, false, "Input and output are incompatible");
|
||||
|
||||
r = is_mixattr_applicable_for_fake_outs_counter(out_zc.mix_attr, key_offsets.size() - 1);
|
||||
CHECK_AND_ASSERT_MES(r, false, "tx input ref #" << output_index << " violates mixin restrictions: mix_attr = " << static_cast<uint32_t>(out_zc.mix_attr) << ", key_offsets.size = " << key_offsets.size());
|
||||
r = is_mixattr_applicable_for_fake_outs_counter(tx_ptr->tx.version, out_zc.mix_attr, key_offsets.size() - 1, this->get_core_runtime_config());
|
||||
CHECK_AND_ASSERT_MES(r, false, "tx input ref #" << output_index << " violates mixin restrictions: tx.version = " << tx_ptr->tx.version << ", mix_attr = " << static_cast<uint32_t>(out_zc.mix_attr) << ", key_offsets.size = " << key_offsets.size());
|
||||
|
||||
TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output);
|
||||
if (!vis.handle_output(tx_ptr->tx, validated_tx, out_zc, n))
|
||||
{
|
||||
size_t verified_input_index = std::find(validated_tx.vin.begin(), validated_tx.vin.end(), verified_input) - validated_tx.vin.begin();
|
||||
LOG_PRINT_RED_L0("handle_output failed for output #" << n << " in " << tx_id << " referenced by input #" << verified_input_index << " in tx " << get_transaction_hash(validated_tx));
|
||||
return false;
|
||||
}
|
||||
TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output);
|
||||
bool legit_output_key = validate_output_key_legit(out_zc.stealth_address);
|
||||
CHECK_AND_ASSERT_MES(legit_output_key, false, "tx input ref #" << output_index << " violates public key restrictions: tx.version = " << tx_ptr->tx.version << ", outtk.key = " << out_zc.stealth_address);
|
||||
|
||||
|
||||
TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output);
|
||||
if (!vis.handle_output(tx_ptr->tx, validated_tx, out_zc, n))
|
||||
{
|
||||
size_t verified_input_index = std::find(validated_tx.vin.begin(), validated_tx.vin.end(), verified_input) - validated_tx.vin.begin();
|
||||
LOG_PRINT_RED_L0("handle_output failed for output #" << n << " in " << tx_id << " referenced by input #" << verified_input_index << " in tx " << get_transaction_hash(validated_tx));
|
||||
return false;
|
||||
}
|
||||
TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output);
|
||||
VARIANT_CASE_THROW_ON_OTHER();
|
||||
VARIANT_SWITCH_END();
|
||||
|
||||
|
|
@ -862,9 +889,22 @@ namespace currency
|
|||
|
||||
if (max_related_block_height < tx_ptr->m_keeper_block_height)
|
||||
max_related_block_height = tx_ptr->m_keeper_block_height;
|
||||
|
||||
|
||||
++output_index;
|
||||
}
|
||||
|
||||
if (m_core_runtime_config.is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, this->get_current_blockchain_size()))
|
||||
{
|
||||
//with hard fork 4 make it network rule to have at least 10 confirmations
|
||||
|
||||
if (this->get_current_blockchain_size() - max_related_block_height < CURRENCY_HF4_MANDATORY_MIN_COINAGE)
|
||||
{
|
||||
LOG_ERROR("Coinage rule broken(mainblock): h = " << this->get_current_blockchain_size() << ", max_related_block_height=" << max_related_block_height << ", tx: " << get_transaction_hash(validated_tx));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,9 +48,9 @@ namespace currency
|
|||
block bl;
|
||||
uint64_t height;
|
||||
uint64_t block_cumulative_size;
|
||||
wide_difficulty_type cumulative_diff_adjusted;
|
||||
wide_difficulty_type cumulative_diff_adjusted; // used only before hardfork 1
|
||||
wide_difficulty_type cumulative_diff_precise;
|
||||
wide_difficulty_type cumulative_diff_precise_adjusted;
|
||||
wide_difficulty_type cumulative_diff_precise_adjusted; //used after hardfork 1 (cumulative difficulty adjusted only by sequence factor)
|
||||
wide_difficulty_type difficulty;
|
||||
boost::multiprecision::uint128_t already_generated_coins;
|
||||
crypto::hash stake_hash; //TODO: unused field for PoW blocks, subject for refactoring
|
||||
|
|
@ -148,6 +148,7 @@ namespace currency
|
|||
uint64_t height;
|
||||
tx_generation_context miner_tx_tgc; // bad design, a lot of copying, consider redesign -- sowle
|
||||
uint64_t block_reward_without_fee;
|
||||
uint64_t block_reward; // == block_reward_without_fee + txs_fee if fees are given to the miner, OR block_reward_without_fee if fees are burnt
|
||||
uint64_t txs_fee; // sum of transactions' fee if any
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ namespace currency
|
|||
ADD_CHECKPOINT(1161000, "96990d851b484e30190678756ba2a4d3a2f92b987e2470728ac1e38b2bf35908");
|
||||
ADD_CHECKPOINT(1480000, "5dd3381eec35e8b4eba4518bfd8eec682a4292761d92218fd59b9f0ffedad3fe");
|
||||
ADD_CHECKPOINT(2000000, "7b6698a8cc279aa78d6263f01fef186bd16f5b1ea263a7f4714abc1d506b9cb3");
|
||||
ADD_CHECKPOINT(2390000, "10797d34349d0ef1d1ab4b41ada6f8f2c2f86a7f7eebe44dd2ba06067cb47e0a");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ namespace currency
|
|||
uint64_t max_alt_blocks;
|
||||
crypto::public_key alias_validation_pubkey;
|
||||
core_time_func_t get_core_time;
|
||||
uint64_t hf4_minimum_mixins;
|
||||
|
||||
hard_forks_descriptor hard_forks;
|
||||
|
||||
|
|
@ -127,6 +128,7 @@ namespace currency
|
|||
pc.tx_pool_min_fee = TX_MINIMUM_FEE;
|
||||
pc.tx_default_fee = TX_DEFAULT_FEE;
|
||||
pc.max_alt_blocks = CURRENCY_ALT_BLOCK_MAX_COUNT;
|
||||
pc.hf4_minimum_mixins = CURRENCY_HF4_MANDATORY_DECOY_SET_SIZE;
|
||||
|
||||
// TODO: refactor the following
|
||||
pc.hard_forks.set_hardfork_height(1, ZANO_HARDFORK_01_AFTER_HEIGHT);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2023 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Copyright (c) 2014-2015 The Boolberry developers
|
||||
|
|
@ -60,7 +60,7 @@ namespace currency
|
|||
// Using C++17 extended aggregate initialization (P0017R1). C++17, finally! -- sowle
|
||||
const static crypto::public_key native_coin_asset_id = {{'\xd6', '\x32', '\x9b', '\x5b', '\x1f', '\x7c', '\x08', '\x05', '\xb5', '\xc3', '\x45', '\xf4', '\x95', '\x75', '\x54', '\x00', '\x2a', '\x2f', '\x55', '\x78', '\x45', '\xf6', '\x4d', '\x76', '\x45', '\xda', '\xe0', '\xe0', '\x51', '\xa6', '\x49', '\x8a'}}; // == crypto::c_point_H, checked in crypto_constants
|
||||
const static crypto::public_key native_coin_asset_id_1div8 = {{'\x74', '\xc3', '\x2d', '\x3e', '\xaa', '\xfa', '\xfc', '\x62', '\x3b', '\xf4', '\x83', '\xe8', '\x58', '\xd4', '\x2e', '\x8b', '\xf4', '\xec', '\x7d', '\xf0', '\x64', '\xad', '\xa2', '\xe3', '\x49', '\x34', '\x46', '\x9c', '\xff', '\x6b', '\x62', '\x68'}}; // == 1/8 * crypto::c_point_H, checked in crypto_constants
|
||||
const static crypto::point_t native_coin_asset_id_pt = crypto::c_point_H;
|
||||
const static crypto::point_t native_coin_asset_id_pt {{ 20574939, 16670001, -29137604, 14614582, 24883426, 3503293, 2667523, 420631, 2267646, -4769165, -11764015, -12206428, -14187565, -2328122, -16242653, -788308, -12595746, -8251557, -10110987, 853396, -4982135, 6035602, -21214320, 16156349, 977218, 2807645, 31002271, 5694305, -16054128, 5644146, -15047429, -568775, -22568195, -8089957, -27721961, -10101877, -29459620, -13359100, -31515170, -6994674 }}; // c_point_H
|
||||
|
||||
const static wide_difficulty_type global_difficulty_pow_starter = DIFFICULTY_POW_STARTER;
|
||||
const static wide_difficulty_type global_difficulty_pos_starter = DIFFICULTY_POS_STARTER;
|
||||
|
|
@ -315,51 +315,6 @@ namespace currency
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Zarcanum structures
|
||||
//
|
||||
//#pragma pack(push, 1)
|
||||
/*
|
||||
struct zarcanum_input : public referring_input
|
||||
{
|
||||
zarcanum_input() {}
|
||||
// Boost's Assignable concept
|
||||
zarcanum_input(const zarcanum_input&) = default;
|
||||
zarcanum_input& operator=(const zarcanum_input&)= default;
|
||||
|
||||
crypto::key_image k_image;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(k_image)
|
||||
FIELD(key_offsets) // referring_input
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(k_image)
|
||||
BOOST_SERIALIZE(key_offsets) // referring_input
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
// txin_zarcanum_inputs contains several zarcanum_input instances and corresponds to one ZC_sig
|
||||
struct txin_zarcanum_inputs
|
||||
{
|
||||
txin_zarcanum_inputs() {}
|
||||
|
||||
// Boost's Assignable concept
|
||||
txin_zarcanum_inputs(const txin_zarcanum_inputs&) = default;
|
||||
txin_zarcanum_inputs& operator=(const txin_zarcanum_inputs&) = default;
|
||||
|
||||
std::vector<zarcanum_input> elements;
|
||||
std::vector<txin_etc_details_v> etc_details;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(elements)
|
||||
FIELD(etc_details)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(elements)
|
||||
BOOST_SERIALIZE(etc_details)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
*/
|
||||
|
||||
struct txin_zc_input : public referring_input
|
||||
{
|
||||
|
|
@ -816,15 +771,15 @@ namespace currency
|
|||
{
|
||||
uint8_t operation_type = ASSET_DESCRIPTOR_OPERATION_UNDEFINED;
|
||||
asset_descriptor_base descriptor;
|
||||
boost::optional<crypto::public_key> opt_amount_commitment; // premultiplied by 1/8
|
||||
boost::optional<crypto::signature> opt_proof; // operation proof - for update/emit
|
||||
boost::optional<crypto::public_key> opt_asset_id; // target asset_id - for update/emit
|
||||
crypto::public_key amount_commitment; // premultiplied by 1/8
|
||||
boost::optional<crypto::signature> opt_proof; // operation proof - for update/emit
|
||||
boost::optional<crypto::public_key> opt_asset_id; // target asset_id - for update/emit
|
||||
uint8_t verion = ASSET_DESCRIPTOR_OPERATION_STRUCTURE_VER;
|
||||
|
||||
BEGIN_VERSIONED_SERIALIZE(ASSET_DESCRIPTOR_OPERATION_STRUCTURE_VER, verion)
|
||||
FIELD(operation_type)
|
||||
FIELD(descriptor)
|
||||
FIELD(opt_amount_commitment)
|
||||
FIELD(amount_commitment)
|
||||
END_VERSION_UNDER(1)
|
||||
FIELD(opt_proof)
|
||||
FIELD(opt_asset_id)
|
||||
|
|
@ -833,7 +788,7 @@ namespace currency
|
|||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(operation_type)
|
||||
BOOST_SERIALIZE(descriptor)
|
||||
BOOST_SERIALIZE(opt_amount_commitment)
|
||||
BOOST_SERIALIZE(amount_commitment)
|
||||
BOOST_END_VERSION_UNDER(1)
|
||||
BOOST_SERIALIZE(opt_proof)
|
||||
BOOST_SERIALIZE(opt_asset_id)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#ifndef TESTNET
|
||||
#define CURRENCY_FORMATION_VERSION 84
|
||||
#else
|
||||
#define CURRENCY_FORMATION_VERSION 89
|
||||
#define CURRENCY_FORMATION_VERSION 94
|
||||
#endif
|
||||
|
||||
#define CURRENCY_GENESIS_NONCE (CURRENCY_FORMATION_VERSION + 101011010121) //bender's nightmare
|
||||
|
|
@ -37,6 +37,8 @@
|
|||
#define CURRENT_BLOCK_MAJOR_VERSION 3
|
||||
|
||||
#define CURRENCY_DEFAULT_DECOY_SET_SIZE 10
|
||||
#define CURRENCY_HF4_MANDATORY_DECOY_SET_SIZE 15
|
||||
#define CURRENCY_HF4_MANDATORY_MIN_COINAGE 10
|
||||
|
||||
#define CURRENT_BLOCK_MINOR_VERSION 0
|
||||
#define CURRENCY_BLOCK_FUTURE_TIME_LIMIT 60*60*2
|
||||
|
|
@ -164,6 +166,8 @@
|
|||
#define BLOCK_POS_STRICT_SEQUENCE_LIMIT 20 // the highest allowed sequence factor for a PoS block (i.e., the max total number of sequential PoS blocks is BLOCK_POS_STRICT_SEQUENCE_LIMIT + 1)
|
||||
|
||||
|
||||
#define CORE_FEE_BLOCKS_LOOKUP_WINDOW 60 //number of blocks used to check if transaction flow is big enought to rise default fee
|
||||
|
||||
#define WALLET_FILE_SIGNATURE_OLD 0x1111012101101011LL // Bender's nightmare
|
||||
#define WALLET_FILE_SIGNATURE_V2 0x1111011201101011LL // another Bender's nightmare
|
||||
#define WALLET_FILE_BINARY_HEADER_VERSION_INITAL 1000
|
||||
|
|
@ -246,8 +250,8 @@
|
|||
#define BC_OFFERS_CURRENCY_MARKET_FILENAME "market.bin"
|
||||
|
||||
#ifndef TESTNET
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION 160
|
||||
#define WALLET_FILE_LAST_SUPPORTED_VERSION 160
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION 161
|
||||
#define WALLET_FILE_LAST_SUPPORTED_VERSION 161
|
||||
#else
|
||||
#define WALLET_FILE_LAST_SUPPORTED_VERSION (CURRENCY_FORMATION_VERSION+76)
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION (CURRENCY_FORMATION_VERSION+76)
|
||||
|
|
@ -265,11 +269,11 @@
|
|||
#define ZANO_HARDFORK_03_AFTER_HEIGHT 1082577
|
||||
#define ZANO_HARDFORK_04_AFTER_HEIGHT 999999999
|
||||
#else
|
||||
/////// Zarcanum Testnet Pre-Alpha //////////////////////////////
|
||||
/////// Zarcanum Testnet //////////////////////////////
|
||||
#define ZANO_HARDFORK_01_AFTER_HEIGHT 0
|
||||
#define ZANO_HARDFORK_02_AFTER_HEIGHT 0
|
||||
#define ZANO_HARDFORK_03_AFTER_HEIGHT 0
|
||||
#define ZANO_HARDFORK_04_AFTER_HEIGHT 1440
|
||||
#define ZANO_HARDFORK_04_AFTER_HEIGHT 2440
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ namespace currency
|
|||
secret_index = ring.size() - 1;
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(secret_index != SIZE_MAX, false, "out #" << j << ": can't find a corresponding asset id in inputs");
|
||||
CHECK_AND_ASSERT_MES(secret_index != SIZE_MAX, false, "out #" << j << ": can't find a corresponding asset id in inputs, asset id: " << H);
|
||||
|
||||
result.bge_proofs.emplace_back(crypto::BGE_proof_s{});
|
||||
uint8_t err = 0;
|
||||
|
|
@ -129,7 +129,6 @@ namespace currency
|
|||
//--------------------------------------------------------------------------------
|
||||
bool verify_asset_surjection_proof(const transaction& tx, const crypto::hash& tx_id)
|
||||
{
|
||||
bool r = false;
|
||||
if (tx.version <= TRANSACTION_VERSION_PRE_HF4)
|
||||
return true;
|
||||
|
||||
|
|
@ -362,15 +361,19 @@ namespace currency
|
|||
const account_public_address &stakeholder_address,
|
||||
transaction& tx,
|
||||
uint64_t& block_reward_without_fee,
|
||||
uint64_t& block_reward,
|
||||
uint64_t tx_version,
|
||||
const blobdata& extra_nonce /* = blobdata() */,
|
||||
size_t max_outs /* = CURRENCY_MINER_TX_MAX_OUTS */,
|
||||
bool pos /* = false */,
|
||||
const pos_entry& pe /* = pos_entry() */, // only pe.stake_unlock_time and pe.stake_amount are used now, TODO: consider refactoring -- sowle
|
||||
tx_generation_context* ogc_ptr /* = nullptr */,
|
||||
const keypair* tx_one_time_key_to_use /* = nullptr */
|
||||
const keypair* tx_one_time_key_to_use /* = nullptr */,
|
||||
const std::vector<tx_destination_entry>& destinations_ /* = std::vector<tx_destination_entry>() */
|
||||
)
|
||||
{
|
||||
std::vector<tx_destination_entry> destinations = destinations_;
|
||||
|
||||
bool r = false;
|
||||
|
||||
if (!get_block_reward(pos, median_size, current_block_size, already_generated_coins, block_reward_without_fee, height))
|
||||
|
|
@ -378,45 +381,56 @@ namespace currency
|
|||
LOG_ERROR("Block is too big");
|
||||
return false;
|
||||
}
|
||||
uint64_t block_reward = block_reward_without_fee + fee;
|
||||
|
||||
block_reward = block_reward_without_fee;
|
||||
// before HF4: add tx fee to the block reward; after HF4: burn it
|
||||
if (tx_version < TRANSACTION_VERSION_POST_HF4)
|
||||
{
|
||||
block_reward += fee;
|
||||
}
|
||||
|
||||
//
|
||||
// prepare destinations
|
||||
//
|
||||
// 1. split block_reward into out_amounts
|
||||
std::vector<uint64_t> out_amounts;
|
||||
if (tx_version > TRANSACTION_VERSION_PRE_HF4)
|
||||
if (!destinations.size())
|
||||
{
|
||||
// randomly split into CURRENCY_TX_MIN_ALLOWED_OUTS outputs
|
||||
decompose_amount_randomly(block_reward, [&](uint64_t a){ out_amounts.push_back(a); }, CURRENCY_TX_MIN_ALLOWED_OUTS);
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-hidden outs: split into digits
|
||||
decompose_amount_into_digits(block_reward, DEFAULT_DUST_THRESHOLD,
|
||||
[&out_amounts](uint64_t a_chunk) { out_amounts.push_back(a_chunk); },
|
||||
[&out_amounts](uint64_t a_dust) { out_amounts.push_back(a_dust); });
|
||||
CHECK_AND_ASSERT_MES(1 <= max_outs, false, "max_out must be non-zero");
|
||||
while (max_outs < out_amounts.size())
|
||||
//
|
||||
// prepare destinations
|
||||
//
|
||||
// 1. split block_reward into out_amounts
|
||||
std::vector<uint64_t> out_amounts;
|
||||
if (tx_version > TRANSACTION_VERSION_PRE_HF4)
|
||||
{
|
||||
out_amounts[out_amounts.size() - 2] += out_amounts.back();
|
||||
out_amounts.resize(out_amounts.size() - 1);
|
||||
// randomly split into CURRENCY_TX_MIN_ALLOWED_OUTS outputs for PoW block, or for PoS block only if the stakeholder address differs
|
||||
// (otherwise for PoS miner tx there will be ONE output with amount = stake_amount + reward)
|
||||
if (!pos || miner_address != stakeholder_address)
|
||||
decompose_amount_randomly(block_reward, [&](uint64_t a) { out_amounts.push_back(a); }, CURRENCY_TX_MIN_ALLOWED_OUTS);
|
||||
}
|
||||
}
|
||||
// 2. construct destinations using out_amounts
|
||||
std::vector<tx_destination_entry> destinations;
|
||||
for (auto a : out_amounts)
|
||||
{
|
||||
tx_destination_entry de = AUTO_VAL_INIT(de);
|
||||
de.addr.push_back(miner_address);
|
||||
de.amount = a;
|
||||
de.flags |= tx_destination_entry_flags::tdef_explicit_native_asset_id; // don't use asset id blinding as it's obvious which asset it is
|
||||
if (pe.stake_unlock_time && pe.stake_unlock_time > height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW)
|
||||
else
|
||||
{
|
||||
//this means that block is creating after hardfork_1 and unlock_time is needed to set for every destination separately
|
||||
de.unlock_time = height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW;
|
||||
// non-hidden outs: split into digits
|
||||
decompose_amount_into_digits(block_reward, DEFAULT_DUST_THRESHOLD,
|
||||
[&out_amounts](uint64_t a_chunk) { out_amounts.push_back(a_chunk); },
|
||||
[&out_amounts](uint64_t a_dust) { out_amounts.push_back(a_dust); });
|
||||
CHECK_AND_ASSERT_MES(1 <= max_outs, false, "max_out must be non-zero");
|
||||
while (max_outs < out_amounts.size())
|
||||
{
|
||||
out_amounts[out_amounts.size() - 2] += out_amounts.back();
|
||||
out_amounts.resize(out_amounts.size() - 1);
|
||||
}
|
||||
}
|
||||
// 2. construct destinations using out_amounts
|
||||
|
||||
for (auto a : out_amounts)
|
||||
{
|
||||
tx_destination_entry de = AUTO_VAL_INIT(de);
|
||||
de.addr.push_back(miner_address);
|
||||
de.amount = a;
|
||||
de.flags |= tx_destination_entry_flags::tdef_explicit_native_asset_id; // don't use asset id blinding as it's obvious which asset it is
|
||||
if (pe.stake_unlock_time && pe.stake_unlock_time > height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW)
|
||||
{
|
||||
//this means that block is creating after hardfork_1 and unlock_time is needed to set for every destination separately
|
||||
de.unlock_time = height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW;
|
||||
}
|
||||
destinations.push_back(de);
|
||||
}
|
||||
destinations.push_back(de);
|
||||
}
|
||||
|
||||
if (pos)
|
||||
|
|
@ -424,7 +438,8 @@ namespace currency
|
|||
uint64_t stake_lock_time = 0;
|
||||
if (pe.stake_unlock_time && pe.stake_unlock_time > height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW)
|
||||
stake_lock_time = pe.stake_unlock_time;
|
||||
destinations.push_back(tx_destination_entry(pe.amount, stakeholder_address, stake_lock_time));
|
||||
uint64_t amount = destinations.empty() ? pe.amount + block_reward : pe.amount; // combine stake and reward into one output if no destinations were generated above
|
||||
destinations.push_back(tx_destination_entry(amount, stakeholder_address, stake_lock_time));
|
||||
destinations.back().flags |= tx_destination_entry_flags::tdef_explicit_native_asset_id; // don't use asset id blinding as it's obvious which asset it is
|
||||
}
|
||||
|
||||
|
|
@ -547,16 +562,16 @@ namespace currency
|
|||
if (additional_inputs_amount_and_fees_for_mining_tx == 0)
|
||||
{
|
||||
// normal tx
|
||||
CHECK_AND_ASSERT_MES(bare_inputs_sum >= bare_outputs_sum, false, "tx balance error: sum of inputs (" << print_money_brief(bare_inputs_sum)
|
||||
<< ") is less than or equal to sum of outputs(" << print_money_brief(bare_outputs_sum) << ")");
|
||||
CHECK_AND_ASSERT_MES(bare_inputs_sum >= bare_outputs_sum, false, "tx balance error: the sum of inputs (" << print_money_brief(bare_inputs_sum)
|
||||
<< ") is less than or equal to the sum of outputs (" << print_money_brief(bare_outputs_sum) << ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
// miner tx
|
||||
CHECK_AND_ASSERT_MES(bare_inputs_sum + additional_inputs_amount_and_fees_for_mining_tx == bare_outputs_sum, false,
|
||||
"tx balance error: sum of inputs (" << print_money_brief(bare_inputs_sum) <<
|
||||
"tx balance error: the sum of inputs (" << print_money_brief(bare_inputs_sum) <<
|
||||
") + additional inputs and fees (" << print_money_brief(additional_inputs_amount_and_fees_for_mining_tx) <<
|
||||
") is less than or equal to sum of outputs(" << print_money_brief(bare_outputs_sum) << ")");
|
||||
") is less than or equal to the sum of outputs (" << print_money_brief(bare_outputs_sum) << ")");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -575,9 +590,8 @@ namespace currency
|
|||
else
|
||||
{
|
||||
// make sure that amount commitment corresponds to opt_amount_commitment_g_proof
|
||||
CHECK_AND_ASSERT_MES(context.ado.opt_amount_commitment.has_value(), false, "opt_amount_commitment is absent");
|
||||
CHECK_AND_ASSERT_MES(aop.opt_amount_commitment_g_proof.has_value(), false, "opt_amount_commitment_g_proof is absent");
|
||||
crypto::point_t A = crypto::point_t(context.ado.opt_amount_commitment.get()).modify_mul8() - context.amount_to_validate * context.asset_id_pt;
|
||||
crypto::point_t A = crypto::point_t(context.ado.amount_commitment).modify_mul8() - context.amount_to_validate * context.asset_id_pt;
|
||||
|
||||
bool r = crypto::check_signature(context.tx_id, A.to_public_key(), aop.opt_amount_commitment_g_proof.get());
|
||||
CHECK_AND_ASSERT_MES(r, false, "opt_amount_commitment_g_proof check failed");
|
||||
|
|
@ -632,13 +646,11 @@ namespace currency
|
|||
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER || ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT)
|
||||
{
|
||||
// opt_amount_commitment supposed to be validated earlier in validate_asset_operation()
|
||||
CHECK_AND_ASSERT_MES(ado.opt_amount_commitment.has_value(), false, "opt_amount_commitment is not set");
|
||||
sum_of_pseudo_out_amount_commitments += crypto::point_t(ado.opt_amount_commitment.get()); // *1/8
|
||||
sum_of_pseudo_out_amount_commitments += crypto::point_t(ado.amount_commitment); // *1/8
|
||||
}
|
||||
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(ado.opt_amount_commitment.has_value(), false, "opt_amount_commitment is not set");
|
||||
outs_commitments_sum += crypto::point_t(ado.opt_amount_commitment.get()); // *1/8
|
||||
outs_commitments_sum += crypto::point_t(ado.amount_commitment); // *1/8
|
||||
}
|
||||
}
|
||||
size_t zc_sigs_count = 0;
|
||||
|
|
@ -725,14 +737,24 @@ namespace currency
|
|||
return total;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool is_mixattr_applicable_for_fake_outs_counter(uint8_t mix_attr, uint64_t fake_outputs_count)
|
||||
bool is_mixattr_applicable_for_fake_outs_counter(uint64_t out_tx_version, uint8_t mix_attr, uint64_t fake_outputs_count, const core_runtime_config& rtc)
|
||||
{
|
||||
if (mix_attr >= CURRENCY_TO_KEY_OUT_FORCED_MIX_LOWER_BOUND)
|
||||
return fake_outputs_count + 1 >= mix_attr;
|
||||
else if (mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX)
|
||||
return fake_outputs_count == 0;
|
||||
if (out_tx_version >= TRANSACTION_VERSION_POST_HF4)
|
||||
{
|
||||
if (mix_attr != CURRENCY_TO_KEY_OUT_FORCED_NO_MIX)
|
||||
return fake_outputs_count >= rtc.hf4_minimum_mixins;
|
||||
else
|
||||
return fake_outputs_count == 0; // CURRENCY_TO_KEY_OUT_FORCED_NO_MIX
|
||||
}
|
||||
else
|
||||
return true;
|
||||
{
|
||||
if (mix_attr >= CURRENCY_TO_KEY_OUT_FORCED_MIX_LOWER_BOUND)
|
||||
return fake_outputs_count + 1 >= mix_attr;
|
||||
else if (mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX)
|
||||
return fake_outputs_count == 0;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool parse_amount(uint64_t& amount, const std::string& str_amount_)
|
||||
|
|
@ -2093,7 +2115,7 @@ namespace currency
|
|||
{
|
||||
crypto::hash h = get_hash_from_POD_objects(CRYPTO_HDS_ASSET_ID, asset_owner);
|
||||
|
||||
// this hash function needs to be computationally expensive (s.e. the whitepaper)
|
||||
// this hash function needs to be computationally expensive (s.a. the whitepaper)
|
||||
for(uint64_t i = 0; i < CRYPTO_HASH_ASSET_ID_ITERATIONS; ++i)
|
||||
h = get_hash_from_POD_objects(CRYPTO_HDS_ASSET_ID, h, i);
|
||||
|
||||
|
|
@ -2127,21 +2149,20 @@ namespace currency
|
|||
bool construct_tx_handle_ado(const account_keys& sender_account_keys,
|
||||
const finalize_tx_param& ftp,
|
||||
asset_descriptor_operation& ado,
|
||||
tx_generation_context& gen_context,
|
||||
const crypto::secret_key& one_time_tx_secret_key,
|
||||
tx_generation_context& gen_context,
|
||||
const keypair& tx_key,
|
||||
std::vector<tx_destination_entry>& shuffled_dsts)
|
||||
{
|
||||
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER)
|
||||
{
|
||||
//CHECK_AND_ASSERT_MES(ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER, false, "unsupported asset operation: " << (int)ado.operation_type);
|
||||
crypto::secret_key asset_control_key{};
|
||||
bool r = derive_key_pair_from_key_pair(sender_account_keys.account_address.spend_public_key, one_time_tx_secret_key, asset_control_key, ado.descriptor.owner, CRYPTO_HDS_ASSET_CONTROL_KEY);
|
||||
bool r = derive_key_pair_from_key_pair(sender_account_keys.account_address.spend_public_key, tx_key.sec, asset_control_key, ado.descriptor.owner, CRYPTO_HDS_ASSET_CONTROL_KEY);
|
||||
CHECK_AND_ASSERT_MES(r, false, "derive_key_pair_from_key_pair failed");
|
||||
|
||||
calculate_asset_id(ado.descriptor.owner, &gen_context.ao_asset_id_pt, &gen_context.ao_asset_id);
|
||||
|
||||
// calculate amount blinding mask
|
||||
gen_context.ao_amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_ASSET_CONTROL_ABM, asset_control_key);
|
||||
gen_context.ao_amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_ASSET_CONTROL_ABM, asset_control_key, tx_key.pub);
|
||||
|
||||
// set correct asset_id to the corresponding destination entries
|
||||
uint64_t amount_of_emitted_asset = 0;
|
||||
|
|
@ -2156,23 +2177,18 @@ namespace currency
|
|||
ado.descriptor.current_supply = amount_of_emitted_asset; // TODO: consider setting current_supply beforehand, not setting it hear in ad-hoc manner -- sowle
|
||||
|
||||
gen_context.ao_amount_commitment = amount_of_emitted_asset * gen_context.ao_asset_id_pt + gen_context.ao_amount_blinding_mask * crypto::c_point_G;
|
||||
ado.opt_amount_commitment = (crypto::c_scalar_1div8 * gen_context.ao_amount_commitment).to_public_key();
|
||||
|
||||
ado.amount_commitment = (crypto::c_scalar_1div8 * gen_context.ao_amount_commitment).to_public_key();
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT)
|
||||
{
|
||||
|
||||
//bool r = derive_key_pair_from_key_pair(sender_account_keys.account_address.spend_public_key, one_time_tx_secret_key, asset_control_key, ado.descriptor.owner, CRYPTO_HDS_ASSET_CONTROL_KEY);
|
||||
//CHECK_AND_ASSERT_MES(r, false, "derive_key_pair_from_key_pair failed");
|
||||
|
||||
//calculate_asset_id(ado.descriptor.owner, &gen_context.ao_asset_id_pt, &gen_context.ao_asset_id);
|
||||
CHECK_AND_ASSERT_MES(ado.opt_asset_id, false, "ado.opt_asset_id is not found at ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT/UPDATE");
|
||||
CHECK_AND_ASSERT_MES(ado.opt_asset_id, false, "ado.opt_asset_id is not found at ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT");
|
||||
|
||||
gen_context.ao_asset_id = *ado.opt_asset_id;
|
||||
gen_context.ao_asset_id_pt.from_public_key(gen_context.ao_asset_id);
|
||||
// calculate amount blinding mask
|
||||
gen_context.ao_amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_ASSET_CONTROL_ABM, ftp.asset_control_key);
|
||||
gen_context.ao_amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_ASSET_CONTROL_ABM, ftp.asset_control_key, tx_key.pub);
|
||||
|
||||
// set correct asset_id to the corresponding destination entries
|
||||
uint64_t amount_of_emitted_asset = 0;
|
||||
|
|
@ -2184,30 +2200,27 @@ namespace currency
|
|||
item.asset_id = gen_context.ao_asset_id;
|
||||
}
|
||||
}
|
||||
ado.descriptor.current_supply += amount_of_emitted_asset; // TODO: consider setting current_supply beforehand, not setting it hear in ad-hoc manner -- sowle
|
||||
ado.descriptor.current_supply += amount_of_emitted_asset;
|
||||
|
||||
gen_context.ao_amount_commitment = amount_of_emitted_asset * gen_context.ao_asset_id_pt + gen_context.ao_amount_blinding_mask * crypto::c_point_G;
|
||||
ado.opt_amount_commitment = (crypto::c_scalar_1div8 * gen_context.ao_amount_commitment).to_public_key();
|
||||
ado.amount_commitment = (crypto::c_scalar_1div8 * gen_context.ao_amount_commitment).to_public_key();
|
||||
|
||||
}
|
||||
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(ado.opt_asset_id, false, "ado.opt_asset_id is not found at ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT/UPDATE");
|
||||
//CHECK_AND_ASSERT_MES(ado.opt_proof, false, "ado.opt_asset_id is not found at ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMMIT/UPDATE");
|
||||
CHECK_AND_ASSERT_MES(!ado.opt_amount_commitment, false, "ado.opt_asset_id is not found at ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT/UPDATE");
|
||||
CHECK_AND_ASSERT_MES(ado.opt_asset_id, false, "ado.opt_asset_id is not found at ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE");
|
||||
//CHECK_AND_ASSERT_MES(ado.opt_proof, false, "ado.opt_asset_id is not found at ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE");
|
||||
|
||||
//fields that not supposed to be changed?
|
||||
}
|
||||
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN)
|
||||
{
|
||||
|
||||
//calculate_asset_id(ado.descriptor.owner, &gen_context.ao_asset_id_pt, &gen_context.ao_asset_id);
|
||||
CHECK_AND_ASSERT_MES(ado.opt_asset_id, false, "ado.opt_asset_id is not found at ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT/UPDATE");
|
||||
CHECK_AND_ASSERT_MES(ado.opt_asset_id, false, "ado.opt_asset_id is not found at ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN");
|
||||
|
||||
gen_context.ao_asset_id = *ado.opt_asset_id;
|
||||
gen_context.ao_asset_id_pt.from_public_key(gen_context.ao_asset_id);
|
||||
// calculate amount blinding mask
|
||||
gen_context.ao_amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_ASSET_CONTROL_ABM, ftp.asset_control_key);
|
||||
gen_context.ao_amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_ASSET_CONTROL_ABM, ftp.asset_control_key, tx_key.pub);
|
||||
gen_context.ao_commitment_in_outputs = true;
|
||||
|
||||
// set correct asset_id to the corresponding destination entries
|
||||
|
|
@ -2227,10 +2240,10 @@ namespace currency
|
|||
amount_of_burned_assets -= item.amount;
|
||||
}
|
||||
}
|
||||
ado.descriptor.current_supply -= amount_of_burned_assets; // TODO: consider setting current_supply beforehand, not setting it hear in ad-hoc manner -- sowle
|
||||
ado.descriptor.current_supply -= amount_of_burned_assets;
|
||||
|
||||
gen_context.ao_amount_commitment = amount_of_burned_assets * gen_context.ao_asset_id_pt + gen_context.ao_amount_blinding_mask * crypto::c_point_G;
|
||||
ado.opt_amount_commitment = (crypto::c_scalar_1div8 * gen_context.ao_amount_commitment).to_public_key();
|
||||
ado.amount_commitment = (crypto::c_scalar_1div8 * gen_context.ao_amount_commitment).to_public_key();
|
||||
}
|
||||
|
||||
if (ftp.pevents_dispatcher) ftp.pevents_dispatcher->RAISE_DEBUG_EVENT(wde_construct_tx_handle_asset_descriptor_operation_before_seal{ &ado });
|
||||
|
|
@ -2497,7 +2510,7 @@ namespace currency
|
|||
pado = get_type_in_variant_container<asset_descriptor_operation>(tx.extra);
|
||||
if (pado)
|
||||
{
|
||||
bool r = construct_tx_handle_ado(sender_account_keys, ftp, *pado, gen_context, one_time_tx_secret_key, shuffled_dsts);
|
||||
bool r = construct_tx_handle_ado(sender_account_keys, ftp, *pado, gen_context, txkey, shuffled_dsts);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construct_tx_handle_ado()");
|
||||
if (ftp.pevents_dispatcher) ftp.pevents_dispatcher->RAISE_DEBUG_EVENT(wde_construct_tx_handle_asset_descriptor_operation{ pado });
|
||||
}
|
||||
|
|
@ -3317,9 +3330,15 @@ namespace currency
|
|||
att.push_back(tsa);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
bool validate_output_key_legit(const crypto::public_key& k)
|
||||
{
|
||||
if (currency::null_pkey == k)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
std::string print_money_brief(uint64_t amount, size_t decimal_point /* = CURRENCY_DISPLAY_DECIMAL_POINT */)
|
||||
{
|
||||
|
|
@ -4041,11 +4060,7 @@ namespace currency
|
|||
//-----------------------------------------------------------------------
|
||||
bool is_pos_coinbase(const transaction& tx)
|
||||
{
|
||||
bool pos = false;
|
||||
if (!is_coinbase(tx, pos) || !pos)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return is_pos_miner_tx(tx);
|
||||
}
|
||||
//-----------------------------------------------------------------------
|
||||
bool is_coinbase(const transaction& tx, bool& pos_coinbase)
|
||||
|
|
@ -4053,7 +4068,7 @@ namespace currency
|
|||
if (!is_coinbase(tx))
|
||||
return false;
|
||||
|
||||
pos_coinbase = (tx.vin.size() == 2 && tx.vin[1].type() == typeid(txin_to_key));
|
||||
pos_coinbase = is_pos_coinbase(tx);
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------
|
||||
|
|
@ -4429,8 +4444,6 @@ namespace currency
|
|||
a.k_image == b.k_image;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
boost::multiprecision::uint1024_t get_a_to_b_relative_cumulative_difficulty(const wide_difficulty_type& difficulty_pos_at_split_point,
|
||||
const wide_difficulty_type& difficulty_pow_at_split_point,
|
||||
const difficulties& a_diff,
|
||||
|
|
@ -4463,6 +4476,51 @@ namespace currency
|
|||
return res;
|
||||
CATCH_ENTRY_WITH_FORWARDING_EXCEPTION();
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
// Note: we adjust formula and introduce multiplier,
|
||||
// that let us never dive into floating point calculations (which we can't use in consensus)
|
||||
// this multiplier should be greater than max multiprecision::uint128_t power 2
|
||||
|
||||
boost::multiprecision::uint1024_t get_adjuster_for_fork_choice_rule_hf4()
|
||||
{
|
||||
return boost::multiprecision::uint1024_t(std::numeric_limits<boost::multiprecision::uint128_t>::max()) * 10 * std::numeric_limits<boost::multiprecision::uint128_t>::max();
|
||||
}
|
||||
|
||||
const boost::multiprecision::uint1024_t adjusting_multiplier = get_adjuster_for_fork_choice_rule_hf4();
|
||||
|
||||
boost::multiprecision::uint1024_t get_a_to_b_relative_cumulative_difficulty_hf4(const wide_difficulty_type& difficulty_pos_at_split_point,
|
||||
const wide_difficulty_type& difficulty_pow_at_split_point,
|
||||
const difficulties& a_diff,
|
||||
const difficulties& b_diff)
|
||||
{
|
||||
static const wide_difficulty_type difficulty_pos_starter = DIFFICULTY_POS_STARTER;
|
||||
static const wide_difficulty_type difficulty_pow_starter = DIFFICULTY_POW_STARTER;
|
||||
const wide_difficulty_type& a_pos_cumulative_difficulty = a_diff.pos_diff > 0 ? a_diff.pos_diff : difficulty_pos_starter;
|
||||
const wide_difficulty_type& b_pos_cumulative_difficulty = b_diff.pos_diff > 0 ? b_diff.pos_diff : difficulty_pos_starter;
|
||||
const wide_difficulty_type& a_pow_cumulative_difficulty = a_diff.pow_diff > 0 ? a_diff.pow_diff : difficulty_pow_starter;
|
||||
const wide_difficulty_type& b_pow_cumulative_difficulty = b_diff.pow_diff > 0 ? b_diff.pow_diff : difficulty_pow_starter;
|
||||
|
||||
boost::multiprecision::uint1024_t basic_sum_ = boost::multiprecision::uint1024_t(a_pow_cumulative_difficulty) + (boost::multiprecision::uint1024_t(a_pos_cumulative_difficulty)*difficulty_pow_at_split_point) / difficulty_pos_at_split_point;
|
||||
boost::multiprecision::uint1024_t basic_sum_pow_minus2 = adjusting_multiplier /(basic_sum_ * basic_sum_);
|
||||
boost::multiprecision::uint1024_t res =
|
||||
(basic_sum_pow_minus2 * a_pow_cumulative_difficulty * a_pos_cumulative_difficulty) / (boost::multiprecision::uint1024_t(b_pow_cumulative_difficulty)*b_pos_cumulative_difficulty);
|
||||
|
||||
// if (res > boost::math::tools::max_value<wide_difficulty_type>())
|
||||
// {
|
||||
// ASSERT_MES_AND_THROW("[INTERNAL ERROR]: Failed to get_a_to_b_relative_cumulative_difficulty, res = " << res << ENDL
|
||||
// << ", difficulty_pos_at_split_point: " << difficulty_pos_at_split_point << ENDL
|
||||
// << ", difficulty_pow_at_split_point:" << difficulty_pow_at_split_point << ENDL
|
||||
// << ", a_pos_cumulative_difficulty:" << a_pos_cumulative_difficulty << ENDL
|
||||
// << ", b_pos_cumulative_difficulty:" << b_pos_cumulative_difficulty << ENDL
|
||||
// << ", a_pow_cumulative_difficulty:" << a_pow_cumulative_difficulty << ENDL
|
||||
// << ", b_pow_cumulative_difficulty:" << b_pow_cumulative_difficulty << ENDL
|
||||
// );
|
||||
// }
|
||||
TRY_ENTRY();
|
||||
// wide_difficulty_type short_res = res.convert_to<wide_difficulty_type>();
|
||||
return res;
|
||||
CATCH_ENTRY_WITH_FORWARDING_EXCEPTION();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -274,13 +274,16 @@ namespace currency
|
|||
const account_public_address &stakeholder_address,
|
||||
transaction& tx,
|
||||
uint64_t& block_reward_without_fee,
|
||||
uint64_t& block_reward,
|
||||
uint64_t tx_version,
|
||||
const blobdata& extra_nonce = blobdata(),
|
||||
size_t max_outs = CURRENCY_MINER_TX_MAX_OUTS,
|
||||
bool pos = false,
|
||||
const pos_entry& pe = pos_entry(),
|
||||
tx_generation_context* ogc_ptr = nullptr,
|
||||
const keypair* tx_one_time_key_to_use = nullptr);
|
||||
const keypair* tx_one_time_key_to_use = nullptr,
|
||||
const std::vector<tx_destination_entry>& destinations = std::vector<tx_destination_entry>()
|
||||
);
|
||||
//---------------------------------------------------------------
|
||||
uint64_t get_string_uint64_hash(const std::string& str);
|
||||
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, const account_keys& self, crypto::scalar_t& asset_blinding_mask, crypto::scalar_t& amount_blinding_mask, crypto::point_t& blinded_asset_id, crypto::point_t& amount_commitment, finalized_tx& result, uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED);
|
||||
|
|
@ -362,7 +365,7 @@ namespace currency
|
|||
tx_derivation_hint make_tx_derivation_hint_from_uint16(uint16_t hint);
|
||||
|
||||
std::string short_hash_str(const crypto::hash& h);
|
||||
bool is_mixattr_applicable_for_fake_outs_counter(uint8_t mix_attr, uint64_t fake_attr_count);
|
||||
bool is_mixattr_applicable_for_fake_outs_counter(uint64_t out_tx_version, uint8_t out_mix_attr, uint64_t fake_outputs_count, const core_runtime_config& rtc);
|
||||
bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t current_blockchain_size, uint64_t current_time);
|
||||
crypto::key_derivation get_encryption_key_derivation(bool is_income, const transaction& tx, const account_keys& acc_keys);
|
||||
bool decrypt_payload_items(bool is_income, const transaction& tx, const account_keys& acc_keys, std::vector<payload_items_v>& decrypted_items);
|
||||
|
|
@ -407,7 +410,7 @@ namespace currency
|
|||
std::vector<txout_ref_v> relative_output_offsets_to_absolute(const std::vector<txout_ref_v>& off);
|
||||
bool absolute_sorted_output_offsets_to_relative_in_place(std::vector<txout_ref_v>& offsets) noexcept;
|
||||
|
||||
|
||||
bool validate_output_key_legit(const crypto::public_key& k);
|
||||
|
||||
// prints amount in format "3.14", "0.0"
|
||||
std::string print_money_brief(uint64_t amount, size_t decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT);
|
||||
|
|
@ -421,6 +424,7 @@ namespace currency
|
|||
bool add_padding_to_tx(transaction& tx, size_t count);
|
||||
bool is_service_tx(const transaction& tx);
|
||||
bool does_tx_have_only_mixin_inputs(const transaction& tx);
|
||||
uint64_t get_hf4_inputs_key_offsets_count(const transaction& tx);
|
||||
bool is_showing_sender_addres(const transaction& tx);
|
||||
bool check_native_coins_amount_burnt_in_outs(const transaction& tx, const uint64_t amount, uint64_t* p_amount_burnt = nullptr);
|
||||
std::string print_stake_kernel_info(const stake_kernel& sk);
|
||||
|
|
@ -933,6 +937,13 @@ namespace currency
|
|||
const difficulties& b_diff
|
||||
);
|
||||
|
||||
boost::multiprecision::uint1024_t get_a_to_b_relative_cumulative_difficulty_hf4(const wide_difficulty_type& difficulty_pos_at_split_point,
|
||||
const wide_difficulty_type& difficulty_pow_at_split_point,
|
||||
const difficulties& a_diff,
|
||||
const difficulties& b_diff
|
||||
);
|
||||
|
||||
|
||||
struct rpc_tx_payload_handler : public boost::static_visitor<bool>
|
||||
{
|
||||
tx_extra_rpc_entry& tv;
|
||||
|
|
|
|||
|
|
@ -404,7 +404,7 @@ namespace currency
|
|||
#ifdef TESTNET
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "crypto/hash.h"
|
||||
#include "profile_tools.h"
|
||||
#include "common/db_backend_selector.h"
|
||||
#include "tx_semantic_validation.h"
|
||||
|
||||
DISABLE_VS_WARNINGS(4244 4345 4503) //'boost::foreach_detail_::or_' : decorated name length exceeded, name was truncated
|
||||
|
||||
|
|
@ -92,6 +93,15 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::check_tx_fee(const transaction &tx, uint64_t amount_fee)
|
||||
{
|
||||
if (amount_fee < m_blockchain.get_core_runtime_config().tx_pool_min_fee)
|
||||
return false;
|
||||
|
||||
//m_blockchain.get
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::add_tx(const transaction &tx, const crypto::hash &id, uint64_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool from_core)
|
||||
{
|
||||
bool r = false;
|
||||
|
|
@ -158,20 +168,31 @@ namespace currency
|
|||
//check key images for transaction if it is not kept by block
|
||||
if(!from_core && !kept_by_block)
|
||||
{
|
||||
|
||||
if(!validate_tx_semantic(tx, blob_size))
|
||||
{
|
||||
// tx semantics check failed
|
||||
LOG_PRINT_RED_L0("Transaction " << id << " semantics check failed ");
|
||||
tvc.m_verification_failed = true;
|
||||
tvc.m_should_be_relayed = false;
|
||||
tvc.m_added_to_pool = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
crypto::key_image spent_ki = AUTO_VAL_INIT(spent_ki);
|
||||
r = !have_tx_keyimges_as_spent(tx, &spent_ki);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Transaction " << id << " uses already spent key image " << spent_ki);
|
||||
|
||||
//transaction spam protection, soft rule
|
||||
if (tx_fee < m_blockchain.get_core_runtime_config().tx_pool_min_fee)
|
||||
if (!check_tx_fee(tx, tx_fee))
|
||||
{
|
||||
if (is_valid_contract_finalization_tx(tx))
|
||||
{
|
||||
//if (is_valid_contract_finalization_tx(tx))
|
||||
//{
|
||||
// that means tx has less fee then allowed by current tx pull rules, but this transaction is actually
|
||||
// a finalization of contract, and template of this contract finalization tx was prepared actually before
|
||||
// fee rules had been changed, so it's ok, let it in.
|
||||
}
|
||||
else
|
||||
//}
|
||||
//else
|
||||
{
|
||||
// this tx has no fee
|
||||
LOG_PRINT_RED_L0("Transaction " << id << " has too small fee: " << print_money_brief(tx_fee) << ", minimum fee: " << print_money_brief(m_blockchain.get_core_runtime_config().tx_pool_min_fee));
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ namespace currency
|
|||
bool remove_key_images(const crypto::hash &tx_id, const transaction& tx, bool kept_by_block);
|
||||
bool insert_alias_info(const transaction& tx);
|
||||
bool remove_alias_info(const transaction& tx);
|
||||
bool check_tx_fee(const transaction &tx, uint64_t amount_fee);
|
||||
|
||||
bool is_valid_contract_finalization_tx(const transaction &tx)const;
|
||||
void store_db_solo_options_values();
|
||||
|
|
|
|||
|
|
@ -1939,6 +1939,17 @@ QString MainWindow::restore_wallet(const QString& param)
|
|||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
QString MainWindow::use_whitelisting(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
//return que_call2<view::restore_wallet_request>("restore_wallet", param, [this](const view::restore_wallet_request& owd, view::api_response& ar){
|
||||
PREPARE_ARG_FROM_JSON(view::api_request_t<bool>, owd);
|
||||
PREPARE_RESPONSE(view::api_responce_return_code, ar);
|
||||
ar.error_code = m_backend.use_whitelisting(owd.wallet_id, owd.req_data);
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
QString MainWindow::open_wallet(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ public:
|
|||
QString webkit_launched_script();
|
||||
QString get_smart_wallet_info(const QString& param);
|
||||
QString restore_wallet(const QString& param);
|
||||
QString use_whitelisting(const QString& param);
|
||||
QString is_pos_allowed();
|
||||
QString store_to_file(const QString& path, const QString& buff);
|
||||
QString load_from_file(const QString& path);
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit c5687a8f1a7195f11e707c465419ee9b8d6ebd92
|
||||
Subproject commit 18cb69f348bae38186f3a8da8bc9fc9991d38cd1
|
||||
|
|
@ -117,6 +117,13 @@ namespace currency
|
|||
res.default_fee = m_core.get_blockchain_storage().get_core_runtime_config().tx_default_fee;
|
||||
res.minimum_fee = m_core.get_blockchain_storage().get_core_runtime_config().tx_pool_min_fee;
|
||||
|
||||
auto & hf = m_core.get_blockchain_storage().get_core_runtime_config().hard_forks.m_height_the_hardfork_n_active_after;
|
||||
res.is_hardfok_active.resize(hf.size());
|
||||
for (size_t i = 0; i != hf.size(); i++)
|
||||
{
|
||||
res.is_hardfok_active[i] = m_core.get_blockchain_storage().is_hardfork_active(i);
|
||||
}
|
||||
|
||||
//conditional values
|
||||
if (req.flags&COMMAND_RPC_GET_INFO_FLAG_NET_TIME_DELTA_MEDIAN)
|
||||
{
|
||||
|
|
@ -384,6 +391,18 @@ namespace currency
|
|||
|
||||
return true;
|
||||
}
|
||||
bool core_rpc_server::on_get_random_outs2(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res, connection_context& cntx)
|
||||
{
|
||||
CHECK_CORE_READY();
|
||||
res.status = API_RETURN_CODE_FAIL;
|
||||
if (!m_core.get_blockchain_storage().get_random_outs_for_amounts2(req, res))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
res.status = API_RETURN_CODE_OK;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& res, connection_context& cntx)
|
||||
{
|
||||
|
|
@ -931,6 +950,7 @@ namespace currency
|
|||
res.miner_tx_tgc = resp.miner_tx_tgc;
|
||||
res.height = resp.height;
|
||||
res.block_reward_without_fee = resp.block_reward_without_fee;
|
||||
res.block_reward = resp.block_reward;
|
||||
res.txs_fee = resp.txs_fee;
|
||||
//calculate epoch seed
|
||||
res.seed = currency::ethash_epoch_to_seed(currency::ethash_height_to_epoch(res.height));
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ namespace currency
|
|||
bool on_start_mining(const COMMAND_RPC_START_MINING::request& req, COMMAND_RPC_START_MINING::response& res, connection_context& cntx);
|
||||
bool on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res, connection_context& cntx);
|
||||
bool on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res, connection_context& cntx);
|
||||
bool on_get_random_outs2(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res, connection_context& cntx);
|
||||
bool on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res, connection_context& cntx);
|
||||
bool on_set_maintainers_info(const COMMAND_RPC_SET_MAINTAINERS_INFO::request& req, COMMAND_RPC_SET_MAINTAINERS_INFO::response& res, connection_context& cntx);
|
||||
bool on_get_tx_pool(const COMMAND_RPC_GET_TX_POOL::request& req, COMMAND_RPC_GET_TX_POOL::response& res, connection_context& cntx);
|
||||
|
|
@ -109,6 +110,7 @@ namespace currency
|
|||
MAP_URI_AUTO_BIN2("/getblocks.bin", on_get_blocks, COMMAND_RPC_GET_BLOCKS_FAST)
|
||||
MAP_URI_AUTO_BIN2("/get_o_indexes.bin", on_get_indexes, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES)
|
||||
MAP_URI_AUTO_BIN2("/getrandom_outs.bin", on_get_random_outs, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS)
|
||||
MAP_URI_AUTO_BIN2("/getrandom_outs2.bin", on_get_random_outs2, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2)
|
||||
MAP_URI_AUTO_BIN2("/set_maintainers_info.bin", on_set_maintainers_info, COMMAND_RPC_SET_MAINTAINERS_INFO)
|
||||
MAP_URI_AUTO_BIN2("/get_tx_pool.bin", on_get_tx_pool, COMMAND_RPC_GET_TX_POOL)
|
||||
MAP_URI_AUTO_BIN2("/check_keyimages.bin", on_check_keyimages, COMMAND_RPC_CHECK_KEYIMAGES)
|
||||
|
|
@ -141,6 +143,7 @@ namespace currency
|
|||
MAP_JON_RPC ("get_all_pool_tx_list", on_get_all_pool_tx_list, COMMAND_RPC_GET_ALL_POOL_TX_LIST)
|
||||
MAP_JON_RPC ("get_pool_info", on_get_pool_info, COMMAND_RPC_GET_POOL_INFO)
|
||||
MAP_JON_RPC ("getrandom_outs", on_get_random_outs, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS)
|
||||
MAP_JON_RPC ("getrandom_outs2", on_get_random_outs2, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2)
|
||||
MAP_JON_RPC ("get_votes", on_get_votes, COMMAND_RPC_GET_VOTES)
|
||||
//assets api
|
||||
MAP_JON_RPC ("get_asset_info", on_get_asset_info, COMMAND_RPC_GET_ASSET_INFO)
|
||||
|
|
|
|||
|
|
@ -422,6 +422,42 @@ namespace currency
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------
|
||||
struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2
|
||||
{
|
||||
struct offsets_distribution
|
||||
{
|
||||
uint64_t amount; //if amount is 0 then lookup in post-zarcanum zone only, if not 0 then pre-zarcanum only
|
||||
std::vector<uint64_t> offsets; //[i] = height, estimated location where to pickup output of transaction
|
||||
uint64_t own_global_index; //index to exclude from selection
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(amount)
|
||||
KV_SERIALIZE(offsets)
|
||||
KV_SERIALIZE(own_global_index)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct request
|
||||
{
|
||||
std::vector<offsets_distribution> amounts;
|
||||
uint64_t height_upper_limit; // if nonzero, all the decoy outputs must be either older than, or the same age as this height
|
||||
bool use_forced_mix_outs;
|
||||
uint64_t coinbase_percents; //from 0 to 100, estimate percents of coinbase outputs included in decoy sets
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(amounts)
|
||||
KV_SERIALIZE(height_upper_limit)
|
||||
KV_SERIALIZE(use_forced_mix_outs)
|
||||
KV_SERIALIZE(coinbase_percents)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response response;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------
|
||||
struct COMMAND_RPC_SET_MAINTAINERS_INFO
|
||||
{
|
||||
|
|
@ -757,6 +793,7 @@ namespace currency
|
|||
uint64_t minimum_fee;
|
||||
uint64_t last_block_timestamp;
|
||||
std::string last_block_hash;
|
||||
std::vector<bool> is_hardfok_active;
|
||||
//market
|
||||
uint64_t offers_count;
|
||||
|
||||
|
|
@ -807,6 +844,7 @@ namespace currency
|
|||
KV_SERIALIZE(minimum_fee)
|
||||
KV_SERIALIZE(last_block_timestamp)
|
||||
KV_SERIALIZE(last_block_hash)
|
||||
KV_SERIALIZE(is_hardfok_active)
|
||||
KV_SERIALIZE(offers_count)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
|
@ -889,6 +927,7 @@ namespace currency
|
|||
std::string prev_hash;
|
||||
tx_generation_context miner_tx_tgc;
|
||||
uint64_t block_reward_without_fee;
|
||||
uint64_t block_reward; // == block_reward_without_fee + txs_fee if fees are given to the miner, OR block_reward_without_fee if fees are burnt
|
||||
uint64_t txs_fee;
|
||||
std::string status;
|
||||
|
||||
|
|
@ -900,6 +939,7 @@ namespace currency
|
|||
KV_SERIALIZE(prev_hash)
|
||||
KV_SERIALIZE(miner_tx_tgc)
|
||||
KV_SERIALIZE(block_reward_without_fee)
|
||||
KV_SERIALIZE(block_reward)
|
||||
KV_SERIALIZE(txs_fee)
|
||||
KV_SERIALIZE(status)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ namespace ph = boost::placeholders;
|
|||
fail_msg_writer() << "unknown error"; \
|
||||
} \
|
||||
|
||||
|
||||
#define CONFIRM_WITH_PASSWORD() if(!check_password_for_operation()) return true;
|
||||
|
||||
|
||||
namespace
|
||||
|
|
@ -140,6 +140,7 @@ namespace
|
|||
const command_line::arg_descriptor<bool> arg_disable_tor_relay ( "disable-tor-relay", "Disable TOR relay", false);
|
||||
const command_line::arg_descriptor<unsigned int> arg_set_timeout("set-timeout", "Set timeout for the wallet");
|
||||
const command_line::arg_descriptor<std::string> arg_voting_config_file("voting-config-file", "Set voting config instead of getting if from daemon", "");
|
||||
const command_line::arg_descriptor<bool> arg_no_password_confirmations("no-password-confirmation", "Enable/Disable password confirmation for transactions", false);
|
||||
|
||||
const command_line::arg_descriptor< std::vector<std::string> > arg_command ("command", "");
|
||||
|
||||
|
|
@ -445,6 +446,9 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
|||
m_do_refresh_after_load = false;
|
||||
}
|
||||
|
||||
m_password_salt = crypto::rand<uint64_t>();
|
||||
m_password_hash = get_hash_from_pass_and_salt(pwd_container.password(), m_password_salt);
|
||||
|
||||
bool was_open = false;
|
||||
if (!m_generate_new.empty())
|
||||
{
|
||||
|
|
@ -516,6 +520,12 @@ bool simple_wallet::deinit()
|
|||
return close_wallet();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
crypto::hash simple_wallet::get_hash_from_pass_and_salt(const std::string& pass, uint64_t salt)
|
||||
{
|
||||
std::string pass_and_salt = pass + std::to_string(salt);
|
||||
return crypto::cn_fast_hash(pass_and_salt.data(), pass_and_salt.size());
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void simple_wallet::handle_command_line(const boost::program_options::variables_map& vm)
|
||||
{
|
||||
m_wallet_file = command_line::get_arg(vm, arg_wallet_file);
|
||||
|
|
@ -529,8 +539,36 @@ void simple_wallet::handle_command_line(const boost::program_options::variables_
|
|||
m_restore_wallet = command_line::get_arg(vm, arg_restore_wallet);
|
||||
m_disable_tor = command_line::get_arg(vm, arg_disable_tor_relay);
|
||||
m_voting_config_file = command_line::get_arg(vm, arg_voting_config_file);
|
||||
m_no_password_confirmations = command_line::get_arg(vm, arg_no_password_confirmations);
|
||||
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
#define PASSWORD_CONFIRMATION_ATTEMPTS 3
|
||||
bool simple_wallet::check_password_for_operation()
|
||||
{
|
||||
if (m_no_password_confirmations)
|
||||
return true;
|
||||
for (size_t i = 0; i != PASSWORD_CONFIRMATION_ATTEMPTS; i++)
|
||||
{
|
||||
tools::password_container pass_container;
|
||||
if (!pass_container.read_password("Enter password to confirm operation:\n"))
|
||||
{
|
||||
fail_msg_writer() << "Failed to read password";
|
||||
return false;
|
||||
}
|
||||
if (get_hash_from_pass_and_salt(pass_container.password(), m_password_salt) != m_password_hash)
|
||||
{
|
||||
fail_msg_writer() << "Wrong password";
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fail_msg_writer() << "Confirmation failed with " << PASSWORD_CONFIRMATION_ATTEMPTS << " attempts";
|
||||
return false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::try_connect_to_daemon()
|
||||
{
|
||||
if (!m_wallet->check_connection())
|
||||
|
|
@ -1529,6 +1567,7 @@ bool preprocess_asset_id(std::string& address_arg, crypto::public_key& asset_id)
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::transfer(const std::vector<std::string> &args_)
|
||||
{
|
||||
CONFIRM_WITH_PASSWORD();
|
||||
SIMPLE_WALLET_BEGIN_TRY_ENTRY();
|
||||
if (!try_connect_to_daemon())
|
||||
return true;
|
||||
|
|
@ -1692,6 +1731,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::show_seed(const std::vector<std::string> &args)
|
||||
{
|
||||
CONFIRM_WITH_PASSWORD();
|
||||
success_msg_writer() << "Please enter a password to secure this seed. Securing your seed is HIGHLY recommended. Leave password blank to stay unsecured.";
|
||||
success_msg_writer(true) << "Remember, restoring a wallet from Secured Seed can only be done if you know its password.";
|
||||
|
||||
|
|
@ -1715,6 +1755,7 @@ bool simple_wallet::show_seed(const std::vector<std::string> &args)
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::spendkey(const std::vector<std::string> &args)
|
||||
{
|
||||
CONFIRM_WITH_PASSWORD();
|
||||
message_writer(epee::log_space::console_color_red, true, std::string())
|
||||
<< "WARNING! Anyone who knows the following secret key can access your wallet and spend your coins.";
|
||||
|
||||
|
|
@ -1727,6 +1768,7 @@ bool simple_wallet::spendkey(const std::vector<std::string> &args)
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::viewkey(const std::vector<std::string> &args)
|
||||
{
|
||||
CONFIRM_WITH_PASSWORD();
|
||||
message_writer(epee::log_space::console_color_yellow, false, std::string())
|
||||
<< "WARNING! Anyone who knows the following secret key can view your wallet (but can not spend your coins).";
|
||||
|
||||
|
|
@ -1924,6 +1966,7 @@ bool simple_wallet::list_outputs(const std::vector<std::string> &args)
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::sign_transfer(const std::vector<std::string> &args)
|
||||
{
|
||||
CONFIRM_WITH_PASSWORD();
|
||||
if (m_wallet->is_watch_only())
|
||||
{
|
||||
fail_msg_writer() << "You can't sign transaction in watch-only wallet";
|
||||
|
|
@ -1997,6 +2040,7 @@ bool simple_wallet::tor_disable(const std::vector<std::string> &args)
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::deploy_new_asset(const std::vector<std::string> &args)
|
||||
{
|
||||
CONFIRM_WITH_PASSWORD();
|
||||
SIMPLE_WALLET_BEGIN_TRY_ENTRY();
|
||||
asset_descriptor_base adb = AUTO_VAL_INIT(adb);
|
||||
if (!args.size() || args.size() > 1)
|
||||
|
|
@ -2034,7 +2078,7 @@ bool simple_wallet::deploy_new_asset(const std::vector<std::string> &args)
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::emit_asset(const std::vector<std::string> &args)
|
||||
{
|
||||
|
||||
CONFIRM_WITH_PASSWORD();
|
||||
SIMPLE_WALLET_BEGIN_TRY_ENTRY();
|
||||
if (args.size() != 2)
|
||||
{
|
||||
|
|
@ -2089,6 +2133,7 @@ bool simple_wallet::emit_asset(const std::vector<std::string> &args)
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::burn_asset(const std::vector<std::string> &args)
|
||||
{
|
||||
CONFIRM_WITH_PASSWORD();
|
||||
SIMPLE_WALLET_BEGIN_TRY_ENTRY();
|
||||
if (args.size() != 2)
|
||||
{
|
||||
|
|
@ -2137,6 +2182,7 @@ bool simple_wallet::burn_asset(const std::vector<std::string> &args)
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::update_asset(const std::vector<std::string> &args)
|
||||
{
|
||||
CONFIRM_WITH_PASSWORD();
|
||||
SIMPLE_WALLET_BEGIN_TRY_ENTRY();
|
||||
if (args.size() != 2)
|
||||
{
|
||||
|
|
@ -2186,6 +2232,7 @@ bool simple_wallet::update_asset(const std::vector<std::string> &args)
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::add_custom_asset_id(const std::vector<std::string> &args)
|
||||
{
|
||||
CONFIRM_WITH_PASSWORD();
|
||||
SIMPLE_WALLET_BEGIN_TRY_ENTRY();
|
||||
if (!args.size() || args.size() > 1)
|
||||
{
|
||||
|
|
@ -2221,6 +2268,7 @@ bool simple_wallet::add_custom_asset_id(const std::vector<std::string> &args)
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::generate_ionic_swap_proposal(const std::vector<std::string> &args)
|
||||
{
|
||||
CONFIRM_WITH_PASSWORD();
|
||||
SIMPLE_WALLET_BEGIN_TRY_ENTRY();
|
||||
|
||||
if (args.size() != 2)
|
||||
|
|
@ -2309,6 +2357,7 @@ bool simple_wallet::get_ionic_swap_proposal_info(const std::vector<std::string>
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::accept_ionic_swap_proposal(const std::vector<std::string> &args)
|
||||
{
|
||||
CONFIRM_WITH_PASSWORD();
|
||||
SIMPLE_WALLET_BEGIN_TRY_ENTRY();
|
||||
|
||||
if (args.size() != 1)
|
||||
|
|
@ -2350,6 +2399,7 @@ bool simple_wallet::accept_ionic_swap_proposal(const std::vector<std::string> &a
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::remove_custom_asset_id(const std::vector<std::string> &args)
|
||||
{
|
||||
CONFIRM_WITH_PASSWORD();
|
||||
SIMPLE_WALLET_BEGIN_TRY_ENTRY();
|
||||
if (!args.size() || args.size() > 1)
|
||||
{
|
||||
|
|
@ -2380,6 +2430,7 @@ bool simple_wallet::remove_custom_asset_id(const std::vector<std::string> &args)
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::sweep_below(const std::vector<std::string> &args)
|
||||
{
|
||||
CONFIRM_WITH_PASSWORD();
|
||||
SIMPLE_WALLET_BEGIN_TRY_ENTRY();
|
||||
bool r = false;
|
||||
if (args.size() < 3 || args.size() > 4)
|
||||
|
|
@ -2623,6 +2674,8 @@ int main(int argc, char* argv[])
|
|||
command_line::add_arg(desc_params, arg_disable_tor_relay);
|
||||
command_line::add_arg(desc_params, arg_set_timeout);
|
||||
command_line::add_arg(desc_params, arg_voting_config_file);
|
||||
command_line::add_arg(desc_params, arg_no_password_confirmations);
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -110,6 +110,8 @@ namespace currency
|
|||
bool try_connect_to_daemon();
|
||||
std::string get_tocken_info_string(const crypto::public_key& asset_id, uint64_t& decimal_point);
|
||||
bool print_wti(const tools::wallet_public::wallet_transfer_info& wti);
|
||||
bool check_password_for_operation();
|
||||
crypto::hash get_hash_from_pass_and_salt(const std::string& pass, uint64_t salt);
|
||||
|
||||
//----------------- i_wallet2_callback ---------------------
|
||||
virtual void on_new_block(uint64_t height, const currency::block& block) override;
|
||||
|
|
@ -189,6 +191,10 @@ namespace currency
|
|||
bool m_disable_tor;
|
||||
std::string m_restore_wallet;
|
||||
std::string m_voting_config_file;
|
||||
bool m_no_password_confirmations = false;
|
||||
|
||||
crypto::hash m_password_hash;
|
||||
uint64_t m_password_salt;
|
||||
|
||||
epee::console_handlers_binder m_cmd_binder;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@
|
|||
#define PROJECT_REVISION "0"
|
||||
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
|
||||
|
||||
#define PROJECT_VERSION_BUILD_NO 244
|
||||
#define PROJECT_VERSION_BUILD_NO 253
|
||||
#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 "]"
|
||||
|
|
|
|||
|
|
@ -77,6 +77,11 @@ namespace tools
|
|||
return invoke_http_bin_remote_command2_update_is_disconnect("/getrandom_outs.bin", req, res);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool default_http_core_proxy::call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res)
|
||||
{
|
||||
return invoke_http_bin_remote_command2_update_is_disconnect("/getrandom_outs2.bin", req, res);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool default_http_core_proxy::call_COMMAND_RPC_SEND_RAW_TX(const currency::COMMAND_RPC_SEND_RAW_TX::request& req, currency::COMMAND_RPC_SEND_RAW_TX::response& res)
|
||||
{
|
||||
return invoke_http_json_remote_command2_update_is_disconnect("/sendrawtransaction", req, res);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ namespace tools
|
|||
bool call_COMMAND_RPC_GET_TX_POOL(const currency::COMMAND_RPC_GET_TX_POOL::request& rqt, currency::COMMAND_RPC_GET_TX_POOL::response& rsp) override;
|
||||
bool call_COMMAND_RPC_GET_ALIASES_BY_ADDRESS(const currency::COMMAND_RPC_GET_ALIASES_BY_ADDRESS::request& rqt, currency::COMMAND_RPC_GET_ALIASES_BY_ADDRESS::response& rsp) override;
|
||||
bool call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& rqt, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& rsp) override;
|
||||
bool call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& rqt, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& rsp) override;
|
||||
bool call_COMMAND_RPC_SEND_RAW_TX(const currency::COMMAND_RPC_SEND_RAW_TX::request& rqt, currency::COMMAND_RPC_SEND_RAW_TX::response& rsp) override;
|
||||
bool call_COMMAND_RPC_FORCE_RELAY_RAW_TXS(const currency::COMMAND_RPC_FORCE_RELAY_RAW_TXS::request& rqt, currency::COMMAND_RPC_FORCE_RELAY_RAW_TXS::response& rsp) override;
|
||||
bool call_COMMAND_RPC_GET_ALL_ALIASES(currency::COMMAND_RPC_GET_ALL_ALIASES::response& rsp) override;
|
||||
|
|
|
|||
|
|
@ -58,6 +58,11 @@ namespace tools
|
|||
return m_rpc.on_get_random_outs(req, res, m_cntxt_stub);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res) override
|
||||
{
|
||||
return m_rpc.on_get_random_outs2(req, res, m_cntxt_stub);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool call_COMMAND_RPC_SEND_RAW_TX(const currency::COMMAND_RPC_SEND_RAW_TX::request& req, currency::COMMAND_RPC_SEND_RAW_TX::response& res) override
|
||||
{
|
||||
return m_rpc.on_send_raw_tx(req, res, m_cntxt_stub);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ namespace tools
|
|||
virtual bool call_COMMAND_RPC_GET_TX_POOL(const currency::COMMAND_RPC_GET_TX_POOL::request& rqt, currency::COMMAND_RPC_GET_TX_POOL::response& rsp){ return false; }
|
||||
virtual bool call_COMMAND_RPC_GET_ALIASES_BY_ADDRESS(const currency::COMMAND_RPC_GET_ALIASES_BY_ADDRESS::request& rqt, currency::COMMAND_RPC_GET_ALIASES_BY_ADDRESS::response& rsp){ return false; }
|
||||
virtual bool call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& rqt, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& rsp){ return false; }
|
||||
virtual bool call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& rqt, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& rsp) { return false; }
|
||||
virtual bool call_COMMAND_RPC_SEND_RAW_TX(const currency::COMMAND_RPC_SEND_RAW_TX::request& rqt, currency::COMMAND_RPC_SEND_RAW_TX::response& rsp){ return false; }
|
||||
virtual bool call_COMMAND_RPC_FORCE_RELAY_RAW_TXS(const currency::COMMAND_RPC_FORCE_RELAY_RAW_TXS::request& rqt, currency::COMMAND_RPC_FORCE_RELAY_RAW_TXS::response& rsp){ return false; }
|
||||
virtual bool call_COMMAND_RPC_GET_ALL_ALIASES(currency::COMMAND_RPC_GET_ALL_ALIASES::response& rsp){ return false; }
|
||||
|
|
|
|||
128
src/wallet/decoy_selection.cpp
Normal file
128
src/wallet/decoy_selection.cpp
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright (c) 2014-2023 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "decoy_selection.h"
|
||||
#include "decoy_selection_default_distribution.hpp"
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
bool scaler::config_scale(uint64_t original, uint64_t scale_to)
|
||||
{
|
||||
m_x_m = original;
|
||||
m_y_m = scale_to;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t scaler::scale(uint64_t h)
|
||||
{
|
||||
double k = double(m_x_m) / m_y_m;
|
||||
double e_pow_minus_k = std::exp(-1 * k);
|
||||
double a = e_pow_minus_k / (k - 1 + e_pow_minus_k);
|
||||
double y = h * a + (1 - std::exp(-1 * (double(h) / double(m_y_m)) )) * m_y_m * (1 - a);
|
||||
return static_cast<uint64_t>(std::round(y));
|
||||
}
|
||||
|
||||
void decoy_selection_generator::init(uint64_t max_h)
|
||||
{
|
||||
load_distribution(g_default_distribution, max_h);
|
||||
m_is_initialized = true;
|
||||
|
||||
}
|
||||
bool decoy_selection_generator::load_distribution_from_file(const char* path)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#define TWO63 0x8000000000000000u
|
||||
#define TWO64f (TWO63*2.0)
|
||||
|
||||
double map_uint_to_double(uint64_t u) {
|
||||
double y = (double)u;
|
||||
return y / TWO64f;
|
||||
}
|
||||
|
||||
std::vector<uint64_t> decoy_selection_generator::generate_distribution(uint64_t count)
|
||||
{
|
||||
std::vector<uint64_t> res;
|
||||
for (size_t i = 0; i != count; i++)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
crypto::generate_random_bytes(sizeof(r), &r);
|
||||
double r_ = map_uint_to_double(r);
|
||||
auto it = m_distribution_mapping.upper_bound(r_);
|
||||
if (it == m_distribution_mapping.end())
|
||||
{
|
||||
throw(std::runtime_error(std::string("_r not found in m_distribution_mapping: ") + std::to_string(r_) ));
|
||||
}
|
||||
uint64_t h = it->second;
|
||||
if (it != m_distribution_mapping.begin())
|
||||
{
|
||||
uint64_t h_0 = (--it)->second;
|
||||
crypto::generate_random_bytes(sizeof(r), &r);
|
||||
h = h_0 + r % (h - h_0) + 1;
|
||||
}
|
||||
//scale from nominal to max_h
|
||||
res.push_back(h); }
|
||||
return res;
|
||||
}
|
||||
|
||||
uint64_t get_distance(const std::vector<decoy_selection_generator::distribution_entry> entries, size_t i)
|
||||
{
|
||||
if (i == 0)
|
||||
return 1;
|
||||
return entries[i].h - entries[i - 1].h;
|
||||
}
|
||||
|
||||
bool decoy_selection_generator::load_distribution(const std::vector<decoy_selection_generator::distribution_entry>& original_distribution, uint64_t max_h)
|
||||
{
|
||||
|
||||
//do prescale of distribution
|
||||
std::vector<decoy_selection_generator::distribution_entry> derived_distribution;
|
||||
scaler scl;
|
||||
scl.config_scale(original_distribution.back().h, max_h);
|
||||
|
||||
uint64_t last_scaled_h = 0;
|
||||
std::list<double> last_scaled_array;
|
||||
|
||||
|
||||
for (size_t i = 0; i <= original_distribution.size(); i++)
|
||||
{
|
||||
if (i == original_distribution.size() || (scl.scale(original_distribution[i].h) != last_scaled_h && last_scaled_array.size()))
|
||||
{
|
||||
//put avg to data_scaled
|
||||
double summ = 0;
|
||||
for (auto item: last_scaled_array)
|
||||
{
|
||||
summ += item;
|
||||
}
|
||||
double avg = summ / last_scaled_array.size();
|
||||
uint64_t prev_h = scl.scale(original_distribution[i - 1].h);
|
||||
derived_distribution.push_back(decoy_selection_generator::distribution_entry{ prev_h, avg});
|
||||
last_scaled_array.clear();
|
||||
}
|
||||
if (i == original_distribution.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
last_scaled_array.push_back(original_distribution[i].v);
|
||||
last_scaled_h = scl.scale(original_distribution[i].h);
|
||||
}
|
||||
|
||||
|
||||
double total_v = 0;
|
||||
|
||||
for (size_t i = 0; i != derived_distribution.size(); i++)
|
||||
{
|
||||
total_v += derived_distribution[i].v * get_distance(derived_distribution, i);
|
||||
}
|
||||
|
||||
double summ_current = 0;
|
||||
for (size_t i = 0; i != derived_distribution.size(); i++)
|
||||
{
|
||||
double k = (derived_distribution[i].v * get_distance(derived_distribution, i))/ total_v;
|
||||
summ_current += k;
|
||||
m_distribution_mapping[summ_current] = derived_distribution[i].h;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
53
src/wallet/decoy_selection.h
Normal file
53
src/wallet/decoy_selection.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright (c) 2014-2023 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include <boost/serialization/list.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include <boost/serialization/deque.hpp>
|
||||
#include <boost/serialization/singleton.hpp>
|
||||
#include <boost/serialization/extended_type_info.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/optional.hpp>
|
||||
#include <atomic>
|
||||
|
||||
|
||||
#include "include_base_utils.h"
|
||||
#include "profile_tools.h"
|
||||
#include "sync_locked_object.h"
|
||||
|
||||
|
||||
|
||||
class scaler
|
||||
{
|
||||
public:
|
||||
//See the graph on https://www.desmos.com/calculator/zfx4bolfqx
|
||||
bool config_scale(uint64_t original, uint64_t scale_to);
|
||||
uint64_t scale(uint64_t h);
|
||||
private:
|
||||
uint64_t m_x_m;
|
||||
uint64_t m_y_m;
|
||||
};
|
||||
|
||||
|
||||
class decoy_selection_generator
|
||||
{
|
||||
public:
|
||||
struct distribution_entry
|
||||
{
|
||||
uint64_t h;
|
||||
double v;
|
||||
};
|
||||
|
||||
void init(uint64_t max_h);
|
||||
bool load_distribution_from_file(const char* path);
|
||||
std::vector<uint64_t> generate_distribution(uint64_t count);
|
||||
bool is_initialized() { return m_is_initialized; }
|
||||
|
||||
private:
|
||||
bool load_distribution(const std::vector<decoy_selection_generator::distribution_entry>& entries, uint64_t max_h);
|
||||
bool m_is_initialized = false;
|
||||
std::map<double, uint64_t> m_distribution_mapping;
|
||||
};
|
||||
1826
src/wallet/decoy_selection_default_distribution.hpp
Normal file
1826
src/wallet/decoy_selection_default_distribution.hpp
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -44,6 +44,7 @@ using namespace epee;
|
|||
#include "currency_core/crypto_config.h"
|
||||
#include "crypto/zarcanum.h"
|
||||
#include "wallet_debug_events_definitions.h"
|
||||
#include "decoy_selection.h"
|
||||
|
||||
using namespace currency;
|
||||
|
||||
|
|
@ -639,8 +640,17 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
|
|||
auto it = m_key_images.find(ki);
|
||||
if (it != m_key_images.end())
|
||||
{
|
||||
// Issue that has been discovered by Luke Parker (twitter: @kayabaNerve)
|
||||
// An attacker can quickly issue transaction that use same outputs ephemeral keys + same tx key, as a result both
|
||||
// transaction's outputs would have same key image, so the wallet should have smart approach to this situation, ie
|
||||
// use output that offer biggest output value.(tokens?)
|
||||
|
||||
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it->second < m_transfers.size(), "m_key_images entry has wrong m_transfers index, it->second: " << it->second << ", m_transfers.size(): " << m_transfers.size());
|
||||
const transfer_details& local_td = m_transfers[it->second];
|
||||
|
||||
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "tx " << ptc.tx_hash() << " @ block " << height << " has output #" << o << " with key image " << ki << " that has already been seen in output #" <<
|
||||
local_td.m_internal_output_index << " in tx " << get_transaction_hash(local_td.m_ptx_wallet_info->m_tx) << " @ block " << local_td.m_spent_height <<
|
||||
|
|
@ -698,7 +708,8 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
|
|||
if (ptc.coin_base_tx)
|
||||
{
|
||||
//last out in coinbase tx supposed to be change from coinstake
|
||||
if (!(o == tx.vout.size() - 1 && !ptc.is_derived_from_coinbase)) // TODO: @#@# reconsider this condition
|
||||
//for genesis block we'll count every input as WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER
|
||||
if (td.m_ptx_wallet_info->m_block_height == 0 || !(o == tx.vout.size() - 1 && !ptc.is_derived_from_coinbase)) // TODO: @#@# reconsider this condition
|
||||
{
|
||||
td.m_flags |= WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER;
|
||||
}
|
||||
|
|
@ -3338,7 +3349,16 @@ bool wallet2::balance(std::unordered_map<crypto::public_key, wallet_public::asse
|
|||
if (is_transfer_unlocked(td))
|
||||
e.unlocked += td.amount();
|
||||
if (td.m_flags & WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER)
|
||||
mined += td.amount();
|
||||
{
|
||||
if (td.m_ptx_wallet_info->m_block_height == 0)
|
||||
{
|
||||
//for genesis block we add actual amounts
|
||||
mined += td.amount();
|
||||
}
|
||||
else {
|
||||
mined += CURRENCY_BLOCK_REWARD; //this code would work only for cases where block reward is full. For reduced block rewards might need more flexible code (TODO)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3413,10 +3433,13 @@ bool wallet2::balance(std::list<wallet_public::asset_balance_entry>& balances, u
|
|||
auto it_cust = custom_assets_local.find(item.first);
|
||||
if(it_cust == custom_assets_local.end())
|
||||
{
|
||||
if(!m_use_assets_whitelisting)
|
||||
continue;
|
||||
|
||||
auto it_local = m_whitelisted_assets.find(item.first);
|
||||
if(it_local == m_whitelisted_assets.end())
|
||||
if(it_local == m_whitelisted_assets.end())
|
||||
{
|
||||
WLT_LOG_YELLOW("WARNING: unknown asset " << item.first << " found and skipped; it's NOT included in balance", LOG_LEVEL_0);
|
||||
WLT_LOG_YELLOW("WARNING: unknown asset " << item.first << " found and skipped; it's NOT included in balance", LOG_LEVEL_1);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
|
|
@ -3495,7 +3518,7 @@ bool wallet2::add_custom_asset_id(const crypto::public_key& asset_id, asset_desc
|
|||
req.asset_id = asset_id;
|
||||
|
||||
bool r = m_core_proxy->call_COMMAND_RPC_GET_ASSET_INFO(req, resp);
|
||||
if (resp.status == API_RETURN_CODE_OK)
|
||||
if (r && resp.status == API_RETURN_CODE_OK)
|
||||
{
|
||||
m_custom_assets[asset_id] = resp.asset_descriptor;
|
||||
asset_descriptor = resp.asset_descriptor;
|
||||
|
|
@ -3636,7 +3659,7 @@ std::string wallet2::get_balance_str() const
|
|||
balance(balances, mined);
|
||||
for (const tools::wallet_public::asset_balance_entry& b : balances)
|
||||
{
|
||||
ss << " " << std::setw(20) << print_fixed_decimal_point_with_trailing_spaces(b.unlocked, b.asset_info.decimal_point);
|
||||
ss << " " << std::left << std::setw(20) << print_fixed_decimal_point_with_trailing_spaces(b.unlocked, b.asset_info.decimal_point);
|
||||
if (b.total == b.unlocked)
|
||||
ss << " ";
|
||||
else
|
||||
|
|
@ -4265,7 +4288,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
|
|||
uint64_t secret_index = 0; // index of the real stake output
|
||||
|
||||
// get decoys outputs and construct miner tx
|
||||
static size_t required_decoys_count = 4; // TODO @#@# set them somewhere else
|
||||
const size_t required_decoys_count = m_core_runtime_config.hf4_minimum_mixins == 0 ? 4 /* <-- for tests */ : m_core_runtime_config.hf4_minimum_mixins;
|
||||
static bool use_only_forced_to_mix = false; // TODO @#@# set them somewhere else
|
||||
if (required_decoys_count > 0 && !is_auditable())
|
||||
{
|
||||
|
|
@ -4578,8 +4601,7 @@ bool wallet2::build_minted_block(const mining_context& cxt, const currency::acco
|
|||
set_block_datetime(current_timestamp, b);
|
||||
WLT_LOG_MAGENTA("Applying actual timestamp: " << current_timestamp, LOG_LEVEL_2);
|
||||
|
||||
uint64_t full_block_reward = tmpl_rsp.block_reward_without_fee + tmpl_rsp.txs_fee;
|
||||
res = prepare_and_sign_pos_block(cxt, full_block_reward, tmpl_req.pe, tmpl_rsp.miner_tx_tgc, b);
|
||||
res = prepare_and_sign_pos_block(cxt, tmpl_rsp.block_reward, tmpl_req.pe, tmpl_rsp.miner_tx_tgc, b);
|
||||
WLT_CHECK_AND_ASSERT_MES(res, false, "Failed to prepare_and_sign_pos_block");
|
||||
|
||||
crypto::hash block_hash = get_block_hash(b);
|
||||
|
|
@ -5465,17 +5487,19 @@ bool wallet2::create_ionic_swap_proposal(const wallet_public::ionic_swap_proposa
|
|||
{
|
||||
std::vector<uint64_t> selected_transfers_for_template;
|
||||
|
||||
build_ionic_swap_template(proposal_details, destination_addr, proposal, selected_transfers_for_template);
|
||||
return build_ionic_swap_template(proposal_details, destination_addr, proposal, selected_transfers_for_template);
|
||||
|
||||
//const uint32_t mask_to_mark_escrow_template_locked_transfers = WALLET_TRANSFER_DETAIL_FLAG_BLOCKED | WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION;
|
||||
//mark_transfers_with_flag(selected_transfers_for_template, mask_to_mark_escrow_template_locked_transfers, "preparing ionic_swap");
|
||||
return true;
|
||||
//return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::build_ionic_swap_template(const wallet_public::ionic_swap_proposal_info& proposal_detais, const currency::account_public_address& destination_addr,
|
||||
wallet_public::ionic_swap_proposal& proposal,
|
||||
std::vector<uint64_t>& selected_transfers)
|
||||
{
|
||||
WLT_THROW_IF_FALSE_WITH_CODE(proposal_detais.fee_paid_by_a >= get_current_minimum_network_fee(), "Error at build_ionic_swap_template, ", API_RETURN_CODE_WALLET_FEE_TOO_LOW);
|
||||
|
||||
construct_tx_param ctp = get_default_construct_tx_param();
|
||||
|
||||
ctp.fake_outputs_count = proposal_detais.mixins;
|
||||
|
|
@ -5856,43 +5880,102 @@ void wallet2::prefetch_global_indicies_if_needed(const std::vector<uint64_t>& se
|
|||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vector<currency::tx_source_entry>& sources, const std::vector<uint64_t>& selected_indicies)
|
||||
bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector<currency::tx_source_entry>& sources, const std::vector<uint64_t>& selected_indicies)
|
||||
{
|
||||
typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry out_entry;
|
||||
typedef currency::tx_source_entry::output_entry tx_output_entry;
|
||||
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response daemon_resp = AUTO_VAL_INIT(daemon_resp);
|
||||
if (fake_outputs_count)
|
||||
//we should request even of fake_outputs_count == 0, since for for postzarcanum this era this param is redefined
|
||||
//todo: remove if(true) block later if this code will be settled
|
||||
if (true)
|
||||
{
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request req = AUTO_VAL_INIT(req);
|
||||
size_t fake_outputs_count = fake_outputs_count_;
|
||||
uint64_t zarcanum_start_from = m_core_runtime_config.hard_forks.m_height_the_hardfork_n_active_after[ZANO_HARDFORK_04_ZARCANUM];
|
||||
uint64_t current_size = m_chain.get_blockchain_current_size();
|
||||
decoy_selection_generator zarcanum_decoy_set_generator;
|
||||
if (current_size - 1 >= zarcanum_start_from)
|
||||
{
|
||||
//in Zarcanum era
|
||||
const uint64_t test_scale_size = current_size - 1 - zarcanum_start_from;
|
||||
zarcanum_decoy_set_generator.init(test_scale_size - 1);
|
||||
}
|
||||
|
||||
bool need_to_request = fake_outputs_count != 0;
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request req = AUTO_VAL_INIT(req);
|
||||
req.height_upper_limit = m_last_pow_block_h; // request decoys to be either older than, or the same age as stake output's height
|
||||
req.use_forced_mix_outs = false; // TODO: add this feature to UI later
|
||||
req.decoys_count = fake_outputs_count + 1; // one more to be able to skip a decoy in case it hits the real output
|
||||
//req.decoys_count = fake_outputs_count + 1; // one more to be able to skip a decoy in case it hits the real output
|
||||
for (uint64_t i: selected_indicies)
|
||||
{
|
||||
req.amounts.push_back(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution());
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& rdisttib = req.amounts.back();
|
||||
|
||||
auto it = m_transfers.begin() + i;
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it->m_ptx_wallet_info->m_tx.vout.size() > it->m_internal_output_index,
|
||||
"m_internal_output_index = " << it->m_internal_output_index <<
|
||||
" is greater or equal to outputs count = " << it->m_ptx_wallet_info->m_tx.vout.size());
|
||||
req.amounts.push_back(it->is_zc() ? 0 : it->m_amount);
|
||||
}
|
||||
|
||||
bool r = m_core_proxy->call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS(req, daemon_resp);
|
||||
THROW_IF_FALSE_WALLET_EX(r, error::no_connection_to_daemon, "getrandom_outs.bin");
|
||||
THROW_IF_FALSE_WALLET_EX(daemon_resp.status != API_RETURN_CODE_BUSY, error::daemon_busy, "getrandom_outs.bin");
|
||||
THROW_IF_FALSE_WALLET_EX(daemon_resp.status == API_RETURN_CODE_OK, error::get_random_outs_error, daemon_resp.status);
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(daemon_resp.outs.size() == selected_indicies.size(),
|
||||
"daemon returned wrong response for getrandom_outs.bin, wrong amounts count = " << daemon_resp.outs.size() << ", expected: " << selected_indicies.size());
|
||||
|
||||
std::vector<COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount> scanty_outs;
|
||||
for(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& amount_outs : daemon_resp.outs)
|
||||
{
|
||||
if (amount_outs.outs.size() < req.decoys_count)
|
||||
|
||||
rdisttib.own_global_index = it->m_global_output_index;
|
||||
//check if we have Zarcanum era output of pre-Zarcanum
|
||||
if (it->is_zc())
|
||||
{
|
||||
scanty_outs.push_back(amount_outs);
|
||||
if(this->is_auditable())
|
||||
continue;
|
||||
//Zarcanum era
|
||||
rdisttib.amount = 0;
|
||||
//generate distribution in Zarcanum hardfork
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(zarcanum_decoy_set_generator.is_initialized(), "zarcanum_decoy_set_generator are not initialized");
|
||||
rdisttib.offsets = zarcanum_decoy_set_generator.generate_distribution(m_core_runtime_config.hf4_minimum_mixins);
|
||||
need_to_request = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//for prezarcanum era use flat distribution
|
||||
rdisttib.amount = it->m_amount;
|
||||
rdisttib.offsets.resize(fake_outputs_count, 0);
|
||||
}
|
||||
}
|
||||
THROW_IF_FALSE_WALLET_EX(scanty_outs.empty(), error::not_enough_outs_to_mix, scanty_outs, fake_outputs_count);
|
||||
if (need_to_request)
|
||||
{
|
||||
size_t attempt_count = 0;
|
||||
while (true)
|
||||
{
|
||||
daemon_resp = COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response();
|
||||
bool r = m_core_proxy->call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2(req, daemon_resp);
|
||||
THROW_IF_FALSE_WALLET_EX(r, error::no_connection_to_daemon, "getrandom_outs2.bin");
|
||||
if (daemon_resp.status == API_RETURN_CODE_FAIL)
|
||||
{
|
||||
if (attempt_count < 10)
|
||||
{
|
||||
attempt_count++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(daemon_resp.outs.size() == selected_indicies.size(),
|
||||
"unable to exacute getrandom_outs.bin after 10 attempts with code API_RETURN_CODE_FAIL, there must be problems with mixins");
|
||||
}
|
||||
}
|
||||
THROW_IF_FALSE_WALLET_EX(daemon_resp.status != API_RETURN_CODE_BUSY, error::daemon_busy, "getrandom_outs.bin");
|
||||
THROW_IF_FALSE_WALLET_EX(daemon_resp.status == API_RETURN_CODE_OK, error::get_random_outs_error, daemon_resp.status);
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(daemon_resp.outs.size() == selected_indicies.size(),
|
||||
"daemon returned wrong response for getrandom_outs.bin, wrong amounts count = " << daemon_resp.outs.size() << ", expected: " << selected_indicies.size());
|
||||
break;
|
||||
}
|
||||
|
||||
std::vector<COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount> scanty_outs;
|
||||
THROW_IF_FALSE_WALLET_EX(daemon_resp.outs.size() == req.amounts.size(), error::not_enough_outs_to_mix, scanty_outs, fake_outputs_count);
|
||||
//for (COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& amount_outs : daemon_resp.outs)
|
||||
for(size_t i = 0; i != daemon_resp.outs.size(); i++)
|
||||
{
|
||||
if (daemon_resp.outs[i].outs.size() != req.amounts[i].offsets.size())
|
||||
{
|
||||
scanty_outs.push_back(daemon_resp.outs[i]);
|
||||
}
|
||||
}
|
||||
THROW_IF_FALSE_WALLET_EX(scanty_outs.empty(), error::not_enough_outs_to_mix, scanty_outs, fake_outputs_count);
|
||||
}
|
||||
}
|
||||
|
||||
//lets prefetch m_global_output_index for selected_indicies
|
||||
|
|
@ -5910,6 +5993,12 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vector<currency
|
|||
src.transfer_index = it - m_transfers.begin();
|
||||
src.amount = td.amount();
|
||||
src.asset_id = td.get_asset_id();
|
||||
size_t fake_outputs_count = fake_outputs_count_;
|
||||
//redefine for hardfork
|
||||
if (td.is_zc() && !this->is_auditable())
|
||||
fake_outputs_count = m_core_runtime_config.hf4_minimum_mixins;
|
||||
|
||||
|
||||
//paste mixin transaction
|
||||
if (daemon_resp.outs.size())
|
||||
{
|
||||
|
|
@ -6431,9 +6520,9 @@ bool wallet2::select_indices_for_transfer(assets_selection_context& needed_money
|
|||
return res;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet2::select_indices_for_transfer(std::vector<uint64_t>& selected_indexes, free_amounts_cache_type& found_free_amounts, uint64_t needed_money, uint64_t fake_outputs_count)
|
||||
uint64_t wallet2::select_indices_for_transfer(std::vector<uint64_t>& selected_indexes, free_amounts_cache_type& found_free_amounts, uint64_t needed_money, uint64_t fake_outputs_count_)
|
||||
{
|
||||
WLT_LOG_GREEN("Selecting indices for transfer of " << print_money_brief(needed_money) << " with " << fake_outputs_count << " fake outs, found_free_amounts.size()=" << found_free_amounts.size() << "...", LOG_LEVEL_0);
|
||||
WLT_LOG_GREEN("Selecting indices for transfer of " << print_money_brief(needed_money) << " with " << fake_outputs_count_ << " fake outs, found_free_amounts.size()=" << found_free_amounts.size() << "...", LOG_LEVEL_0);
|
||||
uint64_t found_money = 0;
|
||||
//uint64_t found_zc_input = false;
|
||||
std::string selected_amounts_str;
|
||||
|
|
@ -6445,6 +6534,11 @@ uint64_t wallet2::select_indices_for_transfer(std::vector<uint64_t>& selected_in
|
|||
it = --found_free_amounts.end();
|
||||
WLT_CHECK_AND_ASSERT_MES(it->second.size(), 0, "internal error: empty found_free_amounts map");
|
||||
}
|
||||
uint64_t fake_outputs_count = fake_outputs_count_;
|
||||
if (!this->is_auditable() && m_transfers[*it->second.begin()].is_zc())
|
||||
{
|
||||
fake_outputs_count = m_core_runtime_config.hf4_minimum_mixins;
|
||||
}
|
||||
if (is_transfer_ready_to_go(m_transfers[*it->second.begin()], fake_outputs_count))
|
||||
{
|
||||
found_money += it->first;
|
||||
|
|
@ -6481,7 +6575,7 @@ bool wallet2::is_transfer_able_to_go(const transfer_details& td, uint64_t fake_o
|
|||
uint8_t mix_attr = CURRENCY_TO_KEY_OUT_RELAXED;
|
||||
if (get_mix_attr_from_tx_out_v(out_v, mix_attr))
|
||||
{
|
||||
if (!currency::is_mixattr_applicable_for_fake_outs_counter(mix_attr, fake_outputs_count))
|
||||
if (!currency::is_mixattr_applicable_for_fake_outs_counter(td.m_ptx_wallet_info->m_tx.version, mix_attr, fake_outputs_count, m_core_runtime_config))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -6507,7 +6601,13 @@ bool wallet2::prepare_free_transfers_cache(uint64_t fake_outputs_count)
|
|||
for (size_t i = 0; i < m_transfers.size(); ++i)
|
||||
{
|
||||
const transfer_details& td = m_transfers[i];
|
||||
if (is_transfer_able_to_go(td, fake_outputs_count))
|
||||
uint64_t fake_outputs_count_local = fake_outputs_count;
|
||||
if (td.m_zc_info_ptr)
|
||||
{
|
||||
//zarcanum out, redefine fake_outputs_count
|
||||
fake_outputs_count_local = this->is_auditable() ? 0 : CURRENCY_HF4_MANDATORY_DECOY_SET_SIZE;
|
||||
}
|
||||
if (is_transfer_able_to_go(td, fake_outputs_count_local))
|
||||
{
|
||||
//@#@
|
||||
m_found_free_amounts[td.get_asset_id()][td.amount()].insert(i);
|
||||
|
|
@ -6903,7 +7003,7 @@ bool wallet2::prepare_transaction(construct_tx_param& ctp, currency::finalize_tx
|
|||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::finalize_transaction(const currency::finalize_tx_param& ftp, currency::transaction& tx, crypto::secret_key& tx_key, bool broadcast_tx, bool store_tx_secret_key /* = true */)
|
||||
void wallet2::finalize_transaction(currency::finalize_tx_param& ftp, currency::transaction& tx, crypto::secret_key& tx_key, bool broadcast_tx, bool store_tx_secret_key /* = true */)
|
||||
{
|
||||
currency::finalized_tx result = AUTO_VAL_INIT(result);
|
||||
result.tx = tx;
|
||||
|
|
@ -6913,7 +7013,7 @@ void wallet2::finalize_transaction(const currency::finalize_tx_param& ftp, curre
|
|||
tx_key = result.one_time_key;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::finalize_transaction(const currency::finalize_tx_param& ftp, currency::finalized_tx& result, bool broadcast_tx, bool store_tx_secret_key /* = true */)
|
||||
void wallet2::finalize_transaction(currency::finalize_tx_param& ftp, currency::finalized_tx& result, bool broadcast_tx, bool store_tx_secret_key /* = true */)
|
||||
{
|
||||
// NOTE: if broadcast_tx == true callback rise_on_transfer2() may be called at the end of this function.
|
||||
// That callback may call balance(), so it's important to have all used/spending transfers
|
||||
|
|
@ -6922,7 +7022,10 @@ void wallet2::finalize_transaction(const currency::finalize_tx_param& ftp, curre
|
|||
// broadcasting tx without secret key storing is forbidden to avoid lost key issues
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(!broadcast_tx || store_tx_secret_key, "finalize_tx is requested to broadcast a tx without storing the key");
|
||||
|
||||
//TIME_MEASURE_START_MS(construct_tx_time);
|
||||
//overide mixins count for hardfork 4 outputs
|
||||
if (is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM))
|
||||
ftp.tx_outs_attr = m_core_runtime_config.hf4_minimum_mixins;
|
||||
|
||||
bool r = currency::construct_tx(m_account.get_keys(),
|
||||
ftp, result);
|
||||
//TIME_MEASURE_FINISH_MS(construct_tx_time);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
#include "view_iface.h"
|
||||
#include "wallet2_base.h"
|
||||
|
||||
#define WALLET_DEFAULT_TX_SPENDABLE_AGE 10
|
||||
#define WALLET_DEFAULT_TX_SPENDABLE_AGE CURRENCY_HF4_MANDATORY_MIN_COINAGE
|
||||
#define WALLET_POS_MINT_CHECK_HEIGHT_INTERVAL 1
|
||||
|
||||
|
||||
|
|
@ -153,6 +153,7 @@ namespace tools
|
|||
uint64_t m_height_of_start_sync = 0;
|
||||
std::atomic<uint64_t> m_last_sync_percent = 0;
|
||||
mutable uint64_t m_current_wallet_file_size = 0;
|
||||
bool m_use_assets_whitelisting = true;
|
||||
|
||||
|
||||
//===============================================================
|
||||
|
|
@ -216,6 +217,7 @@ namespace tools
|
|||
a & m_custom_assets;
|
||||
a & m_rollback_events;
|
||||
a & m_whitelisted_assets;
|
||||
a & m_use_assets_whitelisting;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -633,8 +635,8 @@ namespace tools
|
|||
|
||||
bool prepare_transaction(construct_tx_param& ctp, currency::finalize_tx_param& ftp, const mode_separate_context& emode_separate = mode_separate_context());
|
||||
|
||||
void finalize_transaction(const currency::finalize_tx_param& ftp, currency::transaction& tx, crypto::secret_key& tx_key, bool broadcast_tx, bool store_tx_secret_key = true);
|
||||
void finalize_transaction(const currency::finalize_tx_param& ftp, currency::finalized_tx& result, bool broadcast_tx, bool store_tx_secret_key = true );
|
||||
void finalize_transaction(currency::finalize_tx_param& ftp, currency::transaction& tx, crypto::secret_key& tx_key, bool broadcast_tx, bool store_tx_secret_key = true);
|
||||
void finalize_transaction(currency::finalize_tx_param& ftp, currency::finalized_tx& result, bool broadcast_tx, bool store_tx_secret_key = true );
|
||||
|
||||
std::string get_log_prefix() const { return m_log_prefix; }
|
||||
static uint64_t get_max_unlock_time_from_receive_indices(const currency::transaction& tx, const wallet_public::employed_tx_entries& td);
|
||||
|
|
@ -646,6 +648,7 @@ namespace tools
|
|||
construct_tx_param get_default_construct_tx_param_inital();
|
||||
void set_disable_tor_relay(bool disable);
|
||||
uint64_t get_default_fee() {return TX_DEFAULT_FEE;}
|
||||
uint64_t get_current_minimum_network_fee() { return TX_DEFAULT_FEE; }
|
||||
void export_transaction_history(std::ostream& ss, const std::string& format, bool include_pos_transactions = true);
|
||||
|
||||
bool add_custom_asset_id(const crypto::public_key& asset_id, currency::asset_descriptor_base& asset_descriptor);
|
||||
|
|
@ -890,7 +893,6 @@ private:
|
|||
|
||||
bool m_use_deffered_global_outputs;
|
||||
bool m_disable_tor_relay;
|
||||
bool m_use_assets_whitelisting = true;
|
||||
mutable current_operation_context m_current_context;
|
||||
|
||||
std::string m_votes_config_path;
|
||||
|
|
|
|||
|
|
@ -731,7 +731,7 @@ if (!(cond))
|
|||
{ \
|
||||
exception_handler(); \
|
||||
std::stringstream ss; \
|
||||
ss << std::endl << mess; \
|
||||
ss << std::endl << "[" << error_code << "]" << mess ; \
|
||||
LOG_ERROR(#cond << ". THROW EXCEPTION: " << error_code << ss.str()); \
|
||||
tools::error::throw_wallet_ex<tools::error::wallet_error>(std::string(__FILE__ ":" STRINGIZE(__LINE__)), ss.str(), error_code); \
|
||||
}
|
||||
|
|
|
|||
|
|
@ -274,6 +274,21 @@ namespace wallet_public
|
|||
};
|
||||
|
||||
|
||||
struct wallet_transfer_info_old : public wallet_transfer_info
|
||||
{
|
||||
uint64_t amount = 0;
|
||||
bool is_income = false;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(is_income)
|
||||
KV_SERIALIZE(amount)
|
||||
KV_CHAIN_BASE(wallet_transfer_info)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct asset_balance_entry_base
|
||||
{
|
||||
uint64_t total = 0;
|
||||
|
|
@ -486,25 +501,25 @@ namespace wallet_public
|
|||
#define ORDER_FROM_BEGIN_TO_END "FROM_BEGIN_TO_END"
|
||||
#define ORDER_FROM_FROM_END_TO_BEGIN "FROM_END_TO_BEGIN"
|
||||
|
||||
struct COMMAND_RPC_GET_RECENT_TXS_AND_INFO
|
||||
struct COMMAND_RPC_GET_RECENT_TXS_AND_INFO2
|
||||
{
|
||||
struct request
|
||||
{
|
||||
|
||||
/*
|
||||
if offset is 0, then GET_RECENT_TXS_AND_INFO return
|
||||
unconfirmed transactions as the first first items of "transfers",
|
||||
if offset is 0, then GET_RECENT_TXS_AND_INFO return
|
||||
unconfirmed transactions as the first first items of "transfers",
|
||||
this unconfirmed transactions is not counted regarding "count" parameter
|
||||
*/
|
||||
uint64_t offset;
|
||||
uint64_t count;
|
||||
|
||||
/*
|
||||
need_to_get_info - should backend re-calculate balance(could be relatively heavy,
|
||||
and not needed when getting long tx history with multiple calls
|
||||
/*
|
||||
need_to_get_info - should backend re-calculate balance(could be relatively heavy,
|
||||
and not needed when getting long tx history with multiple calls
|
||||
of GET_RECENT_TXS_AND_INFO with offsets)
|
||||
*/
|
||||
bool update_provision_info;
|
||||
bool update_provision_info;
|
||||
bool exclude_mining_txs;
|
||||
bool exclude_unconfirmed;
|
||||
std::string order; // "FROM_BEGIN_TO_END" or "FROM_END_TO_BEGIN"
|
||||
|
|
@ -535,6 +550,30 @@ namespace wallet_public
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
struct COMMAND_RPC_GET_RECENT_TXS_AND_INFO
|
||||
{
|
||||
typedef COMMAND_RPC_GET_RECENT_TXS_AND_INFO2::request request;
|
||||
|
||||
struct response
|
||||
{
|
||||
wallet_provision_info pi;
|
||||
std::vector<wallet_transfer_info_old> transfers;
|
||||
uint64_t total_transfers;
|
||||
uint64_t last_item_index;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(pi)
|
||||
KV_SERIALIZE(transfers)
|
||||
KV_SERIALIZE(total_transfers)
|
||||
KV_SERIALIZE(last_item_index)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
struct COMMAND_RPC_REGISTER_ALIAS
|
||||
{
|
||||
struct request
|
||||
|
|
@ -561,9 +600,9 @@ namespace wallet_public
|
|||
|
||||
struct transfer_destination
|
||||
{
|
||||
uint64_t amount;
|
||||
uint64_t amount = 0;
|
||||
std::string address;
|
||||
crypto::public_key asset_id;
|
||||
crypto::public_key asset_id = currency::native_coin_asset_id;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(amount)
|
||||
KV_SERIALIZE(address)
|
||||
|
|
|
|||
|
|
@ -240,6 +240,7 @@ namespace tools
|
|||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_getwallet_info(const wallet_public::COMMAND_RPC_GET_WALLET_INFO::request& req, wallet_public::COMMAND_RPC_GET_WALLET_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
|
@ -258,6 +259,7 @@ namespace tools
|
|||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_getwallet_restore_info(const wallet_public::COMMAND_RPC_GET_WALLET_RESTORE_INFO::request& req, wallet_public::COMMAND_RPC_GET_WALLET_RESTORE_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
|
@ -265,6 +267,7 @@ namespace tools
|
|||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_get_seed_phrase_info(const wallet_public::COMMAND_RPC_GET_SEED_PHRASE_INFO::request& req, wallet_public::COMMAND_RPC_GET_SEED_PHRASE_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
|
@ -272,7 +275,36 @@ namespace tools
|
|||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_get_recent_txs_and_info(const wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO::request& req, wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
//this is legacy api, should be removed after successful transition to HF4
|
||||
wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO2::response rsp2 = AUTO_VAL_INIT(rsp2);
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
||||
on_get_recent_txs_and_info2(req, rsp2, er, cntx);
|
||||
res.pi = rsp2.pi;
|
||||
res.total_transfers = rsp2.total_transfers;
|
||||
res.last_item_index = rsp2.last_item_index;
|
||||
for (const auto& item : rsp2.transfers)
|
||||
{
|
||||
res.transfers.push_back(wallet_public::wallet_transfer_info_old());
|
||||
*static_cast<wallet_public::wallet_transfer_info*>(&res.transfers.back()) = item;
|
||||
for (const auto& subitem : item.subtransfers)
|
||||
{
|
||||
if (subitem.asset_id == currency::native_coin_asset_id)
|
||||
{
|
||||
res.transfers.back().amount = subitem.amount;
|
||||
res.transfers.back().is_income = subitem.is_income;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_get_recent_txs_and_info2(const wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO2::request& req, wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO2::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
if (req.update_provision_info)
|
||||
|
|
@ -1021,7 +1053,7 @@ namespace tools
|
|||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
std::string buff = epee::string_encoding::base64_decode(req.buff);
|
||||
bool r = w.get_wallet()->encrypt_buffer(buff, res.res_buff);
|
||||
w.get_wallet()->encrypt_buffer(buff, res.res_buff);
|
||||
res.res_buff = epee::string_encoding::base64_encode(res.res_buff);
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
|
|
@ -1031,7 +1063,7 @@ namespace tools
|
|||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
std::string buff = epee::string_encoding::base64_decode(req.buff);
|
||||
bool r = w.get_wallet()->encrypt_buffer(buff, res.res_buff);
|
||||
w.get_wallet()->encrypt_buffer(buff, res.res_buff);
|
||||
res.res_buff = epee::string_encoding::base64_encode(res.res_buff);
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
|
|
|
|||
|
|
@ -94,7 +94,8 @@ namespace tools
|
|||
MAP_JON_RPC_WE("getbalance", on_getbalance, wallet_public::COMMAND_RPC_GET_BALANCE)
|
||||
MAP_JON_RPC_WE("getaddress", on_getaddress, wallet_public::COMMAND_RPC_GET_ADDRESS)
|
||||
MAP_JON_RPC_WE("get_wallet_info", on_getwallet_info, wallet_public::COMMAND_RPC_GET_WALLET_INFO)
|
||||
MAP_JON_RPC_WE("get_recent_txs_and_info", on_get_recent_txs_and_info, wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO)
|
||||
MAP_JON_RPC_WE("get_recent_txs_and_info", on_get_recent_txs_and_info, wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO) //LEGACY
|
||||
MAP_JON_RPC_WE("get_recent_txs_and_info2", on_get_recent_txs_and_info2, wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO2)
|
||||
MAP_JON_RPC_WE("transfer", on_transfer, wallet_public::COMMAND_RPC_TRANSFER)
|
||||
MAP_JON_RPC_WE("store", on_store, wallet_public::COMMAND_RPC_STORE)
|
||||
MAP_JON_RPC_WE("get_payments", on_get_payments, wallet_public::COMMAND_RPC_GET_PAYMENTS)
|
||||
|
|
@ -150,6 +151,7 @@ namespace tools
|
|||
bool on_getwallet_restore_info(const wallet_public::COMMAND_RPC_GET_WALLET_RESTORE_INFO::request& req, wallet_public::COMMAND_RPC_GET_WALLET_RESTORE_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_get_seed_phrase_info(const wallet_public::COMMAND_RPC_GET_SEED_PHRASE_INFO::request& req, wallet_public::COMMAND_RPC_GET_SEED_PHRASE_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_get_recent_txs_and_info(const wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO::request& req, wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_get_recent_txs_and_info2(const wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO2::request& req, wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO2::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_transfer(const wallet_public::COMMAND_RPC_TRANSFER::request& req, wallet_public::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_store(const wallet_public::COMMAND_RPC_STORE::request& req, wallet_public::COMMAND_RPC_STORE::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_get_payments(const wallet_public::COMMAND_RPC_GET_PAYMENTS::request& req, wallet_public::COMMAND_RPC_GET_PAYMENTS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
|
|
|||
|
|
@ -548,7 +548,10 @@ bool wallets_manager::init_local_daemon()
|
|||
|
||||
//chain calls to rpc server
|
||||
m_prpc_chain_handler = &m_wallet_rpc_server;
|
||||
//disable this for main net until we get full support of authentication with network
|
||||
#ifdef TESTNET
|
||||
m_rpc_server.set_rpc_chain_handler(this);
|
||||
#endif
|
||||
|
||||
|
||||
LOG_PRINT_L0("Starting core rpc server...");
|
||||
|
|
@ -1805,6 +1808,12 @@ std::string wallets_manager::reset_wallet_password(uint64_t wallet_id, const std
|
|||
else
|
||||
return API_RETURN_CODE_FAIL;
|
||||
}
|
||||
std::string wallets_manager::use_whitelisting(uint64_t wallet_id, bool use)
|
||||
{
|
||||
GET_WALLET_OPT_BY_ID(wallet_id, w);
|
||||
w.w->get()->set_use_assets_whitelisting(use);
|
||||
return API_RETURN_CODE_OK;
|
||||
}
|
||||
std::string wallets_manager::add_custom_asset_id(uint64_t wallet_id, const crypto::public_key& asset_id, currency::asset_descriptor_base& asset_descriptor)
|
||||
{
|
||||
GET_WALLET_OPT_BY_ID(wallet_id, w);
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ public:
|
|||
std::string get_wallet_restore_info(uint64_t wallet_id, std::string& seed_phrase, const std::string& seed_password);
|
||||
std::string backup_wallet(uint64_t wallet_id, const std::wstring& path);
|
||||
std::string reset_wallet_password(uint64_t wallet_id, const std::string& pass);
|
||||
std::string use_whitelisting(uint64_t wallet_id, bool use);
|
||||
std::string is_wallet_password_valid(uint64_t wallet_id, const std::string& pass);
|
||||
std::string create_ionic_swap_proposal(uint64_t wallet_id, const tools::wallet_public::create_ionic_swap_proposal_request& proposal, std::string& result_proposal_hex);
|
||||
std::string get_ionic_swap_proposal_info(uint64_t wallet_id, std::string&raw_tx_template_hex, tools::wallet_public::ionic_swap_proposal_info& proposal);
|
||||
|
|
|
|||
|
|
@ -1068,7 +1068,7 @@ bool gen_alias_too_small_reward::generate(std::vector<test_event_entry>& events)
|
|||
set_hard_fork_heights_to_generator(generator);
|
||||
DO_CALLBACK(events, "configure_core");
|
||||
DO_CALLBACK(events, "init_runtime_config");
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW+20);
|
||||
|
||||
transaction tx_1 = AUTO_VAL_INIT(tx_1);
|
||||
r = construct_tx_with_many_outputs(m_hardforks, events, blk_0r, miner_acc.get_keys(), miner_acc.get_public_address(), 3 * aliases_count * TESTS_DEFAULT_FEE * 100, 3 * aliases_count, TESTS_DEFAULT_FEE, tx_1);
|
||||
|
|
@ -1271,7 +1271,8 @@ bool gen_alias_switch_and_check_block_template::generate(std::vector<test_event_
|
|||
uint64_t miner_amount = get_outs_money_amount(blk_0r.miner_tx, miner_acc.get_keys()) * 4;
|
||||
// alice get some money
|
||||
MAKE_TX_LIST(events, tx_list, miner_acc, alice, miner_amount / 2, blk_0r); // 2N+3
|
||||
MAKE_NEXT_BLOCK_TX_LIST(events, blk_1, blk_0r, miner_acc, tx_list); // 2N+4
|
||||
MAKE_NEXT_BLOCK_TX_LIST(events, blk_1_, blk_0r, miner_acc, tx_list); // 2N+4
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_1, blk_1_, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1); // 2N = CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 2
|
||||
tx_list.clear();
|
||||
|
||||
// Alice registers an alias
|
||||
|
|
|
|||
|
|
@ -300,6 +300,7 @@ bool test_generator::construct_block(currency::block& blk,
|
|||
size_t target_block_size = txs_size + 0; // zero means no cost for ordinary coinbase
|
||||
tx_generation_context miner_tx_tgc{};
|
||||
uint64_t block_reward_without_fee = 0;
|
||||
uint64_t block_reward = 0;
|
||||
while (true)
|
||||
{
|
||||
r = construct_miner_tx(height, misc_utils::median(block_sizes),
|
||||
|
|
@ -310,6 +311,7 @@ bool test_generator::construct_block(currency::block& blk,
|
|||
miner_acc.get_keys().account_address,
|
||||
blk.miner_tx,
|
||||
block_reward_without_fee,
|
||||
block_reward,
|
||||
get_tx_version(height, m_hardforks),
|
||||
blobdata(),
|
||||
test_generator::get_test_gentime_settings().miner_tx_max_outs,
|
||||
|
|
@ -356,7 +358,7 @@ bool test_generator::construct_block(currency::block& blk,
|
|||
else
|
||||
{
|
||||
//need to build pos block
|
||||
r = sign_block(wallets[won_walled_index].mining_context, pe, block_reward_without_fee + total_fee, *wallets[won_walled_index].wallet, miner_tx_tgc, blk);
|
||||
r = sign_block(wallets[won_walled_index].mining_context, pe, block_reward, *wallets[won_walled_index].wallet, miner_tx_tgc, blk);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to find_kernel_and_sign()");
|
||||
}
|
||||
|
||||
|
|
@ -448,6 +450,16 @@ bool test_generator::build_wallets(const blockchain_vector& blockchain,
|
|||
{
|
||||
for (uint64_t amount : rqt.amounts)
|
||||
{
|
||||
uint64_t height_upper_limit_local = rqt.height_upper_limit;
|
||||
if (amount == 0)
|
||||
{
|
||||
//for hardfork 4 we need to have at least 10 confirmations on hard rule level
|
||||
//rqt.height_upper_limit > - 10
|
||||
if (m_blockchain.size() < CURRENCY_HF4_MANDATORY_MIN_COINAGE)
|
||||
return false;
|
||||
if (height_upper_limit_local > m_blockchain.size() - CURRENCY_HF4_MANDATORY_MIN_COINAGE)
|
||||
height_upper_limit_local = m_blockchain.size() - CURRENCY_HF4_MANDATORY_MIN_COINAGE;
|
||||
}
|
||||
rsp.outs.resize(rsp.outs.size() + 1);
|
||||
auto& rsp_entry = rsp.outs.back();
|
||||
rsp_entry.amount = amount;
|
||||
|
|
@ -463,7 +475,7 @@ bool test_generator::build_wallets(const blockchain_vector& blockchain,
|
|||
for (size_t gindex : random_mapping)
|
||||
{
|
||||
const out_index_info& oii = it->second[gindex];
|
||||
if (rqt.height_upper_limit != 0 && oii.block_height > rqt.height_upper_limit)
|
||||
if (height_upper_limit_local != 0 && oii.block_height > height_upper_limit_local)
|
||||
continue;
|
||||
const transaction& tx = oii.in_block_tx_index == 0 ? m_blockchain[oii.block_height]->b.miner_tx : m_blockchain[oii.block_height]->m_transactions[oii.in_block_tx_index - 1];
|
||||
auto& out_v = tx.vout[oii.in_tx_out_index];
|
||||
|
|
@ -941,9 +953,11 @@ bool test_generator::construct_block(int64_t manual_timestamp_adjustment,
|
|||
else
|
||||
{
|
||||
uint64_t base_block_reward = 0;
|
||||
uint64_t block_reward = 0;
|
||||
size_t current_block_size = txs_sizes + get_object_blobsize(blk.miner_tx);
|
||||
// TODO: This will work, until size of constructed block is less then CURRENCY_BLOCK_GRANTED_FULL_REWARD_ZONE
|
||||
if (!construct_miner_tx(height, misc_utils::median(block_sizes), already_generated_coins, current_block_size, 0, miner_acc.get_public_address(), miner_acc.get_public_address(), blk.miner_tx, base_block_reward, get_tx_version(height, m_hardforks), blobdata(), 1))
|
||||
if (!construct_miner_tx(height, misc_utils::median(block_sizes), already_generated_coins, current_block_size, 0,
|
||||
miner_acc.get_public_address(), miner_acc.get_public_address(), blk.miner_tx, base_block_reward, block_reward, get_tx_version(height, m_hardforks), blobdata(), 1))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1193,8 +1207,6 @@ namespace
|
|||
|
||||
bool init_output_indices(map_output_idx_t& outs, map_output_t& outs_mine, const std::vector<currency::block>& blockchain, const map_hash2tx_t& mtx, const currency::account_keys& acc_keys)
|
||||
{
|
||||
bool r = false;
|
||||
|
||||
for (const block& blk : blockchain)
|
||||
{
|
||||
uint64_t height = get_block_height(blk);
|
||||
|
|
@ -1487,6 +1499,11 @@ bool fill_tx_sources(std::vector<currency::tx_source_entry>& sources, const std:
|
|||
if (unlock_time > head_block_ts + DIFFICULTY_TOTAL_TARGET)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (blk_head.miner_tx.version >= TRANSACTION_VERSION_POST_HF4 && next_block_height - get_block_height(*oi.p_blk) < CURRENCY_HF4_MANDATORY_MIN_COINAGE)
|
||||
{
|
||||
//ignore outs that doesn't fit the HF4 rule
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2338,7 +2355,6 @@ bool shuffle_source_entries(std::vector<tx_source_entry>& sources)
|
|||
// creates destinations.size() + 1 outputs if the total sum of amounts is less than the original premine amount (the last one will have amount = old_premine - sum)
|
||||
bool replace_coinbase_in_genesis_block(const std::vector<currency::tx_destination_entry>& destinations, test_generator& generator, std::vector<test_event_entry>& events, currency::block& genesis_block)
|
||||
{
|
||||
bool r = false;
|
||||
generator.remove_block_info(genesis_block);
|
||||
events.pop_back();
|
||||
|
||||
|
|
@ -2478,6 +2494,7 @@ bool test_chain_unit_enchanced::configure_core(currency::core& c, size_t ev_inde
|
|||
currency::core_runtime_config pc = c.get_blockchain_storage().get_core_runtime_config();
|
||||
pc.min_coinstake_age = TESTS_POS_CONFIG_MIN_COINSTAKE_AGE;
|
||||
pc.pos_minimum_heigh = TESTS_POS_CONFIG_POS_MINIMUM_HEIGH;
|
||||
pc.hf4_minimum_mixins = 0;
|
||||
pc.hard_forks = m_hardforks;
|
||||
c.get_blockchain_storage().set_core_runtime_config(pc);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -585,6 +585,9 @@ public:
|
|||
void set_hardforks(const currency::hard_forks_descriptor& hardforks);
|
||||
const currency::hard_forks_descriptor& get_hardforks() const { return m_hardforks; }
|
||||
|
||||
void load_hardforks_from(const test_chain_unit_base* pthis) { m_hardforks = pthis->get_hardforks(); }
|
||||
template<typename t_type>
|
||||
void load_hardforks_from(const t_type* pthis) {}
|
||||
|
||||
private:
|
||||
bool m_ignore_last_pow_in_wallets;
|
||||
|
|
@ -954,10 +957,11 @@ bool test_generator::construct_block_gentime_with_coinbase_cb(const currency::bl
|
|||
//size_t current_block_size = get_object_blobsize(miner_tx);
|
||||
|
||||
uint64_t block_reward_without_fee = 0;
|
||||
uint64_t block_reward = 0;
|
||||
|
||||
currency::keypair tx_sec_key = currency::keypair::generate();
|
||||
r = construct_miner_tx(height, epee::misc_utils::median(block_sizes), already_generated_coins, 0 /* current_block_size !HACK! */, 0,
|
||||
acc.get_public_address(), acc.get_public_address(), miner_tx, block_reward_without_fee, get_tx_version(height, m_hardforks), currency::blobdata(), /* max outs: */ 1,
|
||||
acc.get_public_address(), acc.get_public_address(), miner_tx, block_reward_without_fee, block_reward, get_tx_version(height, m_hardforks), currency::blobdata(), /* max outs: */ 1,
|
||||
/* pos: */ false, currency::pos_entry(), /* ogc_ptr: */ nullptr, &tx_sec_key);
|
||||
CHECK_AND_ASSERT_MES(r, false, "construct_miner_tx failed");
|
||||
|
||||
|
|
|
|||
|
|
@ -197,7 +197,8 @@ bool generate_and_play(const char* const genclass_name, size_t hardfork_id = SIZ
|
|||
std::vector<test_event_entry> events;
|
||||
bool generated = false;
|
||||
bool result = false;
|
||||
std::cout << ENDL << concolor::bright_white << "#TEST# >>>> " << genclass_name << " <<<<" << ENDL << ENDL;
|
||||
//std::cout << ENDL << concolor::bright_white << "#TEST# >>>> " << genclass_name << " <<<<" << ENDL << ENDL;
|
||||
LOG_PRINT_MAGENTA( "#TEST# >>>> " << genclass_name << " <<<<" << ENDL, LOG_LEVEL_0);
|
||||
|
||||
LOG_PRINT2("get_object_blobsize.log", "#TEST# " << genclass_name, LOG_LEVEL_3);
|
||||
|
||||
|
|
@ -231,16 +232,16 @@ bool generate_and_play(const char* const genclass_name, size_t hardfork_id = SIZ
|
|||
generated = g.generate(events);
|
||||
if (generated)
|
||||
{
|
||||
std::cout << concolor::normal << events.size() << " events generated successfully" << std::endl;
|
||||
LOG_PRINT_MAGENTA( events.size() << " events generated successfully" << std::endl, LOG_LEVEL_0);
|
||||
if (has_non_default_hardforks || g.get_hardforks() != tcub.get_hardforks())
|
||||
{
|
||||
size_t configure_core_events_count = std::count_if(events.begin(), events.end(), [](auto& ev){ return ev.type() == typeid(callback_entry) && boost::get<callback_entry>(ev).callback_name == "configure_core"; });
|
||||
CHECK_AND_ASSERT_THROW_MES(configure_core_events_count != 0, "Test " << genclass_name << " has non-default hardfork settings and therefore must use 'configure_core' callback");
|
||||
}
|
||||
|
||||
std::cout << concolor::bright_white << std::string(100, '=') << std::endl <<
|
||||
LOG_PRINT_MAGENTA(std::string(100, '=') << std::endl <<
|
||||
"#TEST# >>>> " << genclass_name << " <<<< start replaying events" << std::endl <<
|
||||
std::string(100, '=') << concolor::normal << std::endl;
|
||||
std::string(100, '=') << std::endl, LOG_LEVEL_0);
|
||||
|
||||
result = do_replay_events(events, g);
|
||||
}
|
||||
|
|
@ -263,18 +264,18 @@ bool generate_and_play(const char* const genclass_name, size_t hardfork_id = SIZ
|
|||
|
||||
if (result)
|
||||
{
|
||||
std::cout << concolor::green << std::string(100, '=') << std::endl <<
|
||||
LOG_PRINT_GREEN(std::string(100, '=') << std::endl <<
|
||||
"#TEST# >>>> " << genclass_name << " <<<< Succeeded" << std::endl <<
|
||||
std::string(100, '=') << concolor::normal << std::endl;
|
||||
std::string(100, '=') << std::endl, LOG_LEVEL_0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << concolor::red << std::string(100, '=') << std::endl <<
|
||||
LOG_PRINT_RED( std::string(100, '=') << std::endl <<
|
||||
"#TEST# >>>> " << genclass_name << " <<<< FAILED" << std::endl <<
|
||||
std::string(100, '=') << concolor::normal << std::endl;
|
||||
std::string(100, '=') << std::endl, LOG_LEVEL_0);
|
||||
result = false;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
//std::cout << std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -1078,7 +1079,7 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(wallet_outputs_with_same_key_image);
|
||||
GENERATE_AND_PLAY(wallet_unconfirmed_tx_expiration);
|
||||
GENERATE_AND_PLAY(wallet_unconfimed_tx_balance);
|
||||
GENERATE_AND_PLAY_HF(packing_outputs_on_pos_minting_wallet, "3-*");
|
||||
GENERATE_AND_PLAY_HF(packing_outputs_on_pos_minting_wallet, "3");
|
||||
GENERATE_AND_PLAY(wallet_watch_only_and_chain_switch);
|
||||
|
||||
GENERATE_AND_PLAY(wallet_rpc_integrated_address);
|
||||
|
|
@ -1231,7 +1232,7 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(hard_fork_2_tx_payer_in_wallet);
|
||||
GENERATE_AND_PLAY(hard_fork_2_tx_receiver_in_wallet);
|
||||
GENERATE_AND_PLAY(hard_fork_2_tx_extra_alias_entry_in_wallet);
|
||||
GENERATE_AND_PLAY(hard_fork_2_auditable_addresses_basics);
|
||||
GENERATE_AND_PLAY_HF(hard_fork_2_auditable_addresses_basics, "2-*");
|
||||
GENERATE_AND_PLAY(hard_fork_2_no_new_structures_before_hf);
|
||||
GENERATE_AND_PLAY(hard_fork_2_awo_wallets_basic_test<true>);
|
||||
GENERATE_AND_PLAY(hard_fork_2_awo_wallets_basic_test<false>);
|
||||
|
|
@ -1240,13 +1241,16 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(hard_fork_2_incorrect_alias_update<true>);
|
||||
GENERATE_AND_PLAY(hard_fork_2_incorrect_alias_update<false>);
|
||||
|
||||
// HF4
|
||||
// GENERATE_AND_PLAY_HF(hard_fork_4_consolidated_txs, "4"); TODO, doesn't work atm -- sowle
|
||||
|
||||
// atomics
|
||||
GENERATE_AND_PLAY(atomic_simple_test);
|
||||
GENERATE_AND_PLAY(atomic_test_wrong_redeem_wrong_refund);
|
||||
GENERATE_AND_PLAY(atomic_test_altchain_simple);
|
||||
GENERATE_AND_PLAY(atomic_test_check_hardfork_rules);
|
||||
|
||||
GENERATE_AND_PLAY(isolate_auditable_and_proof);
|
||||
GENERATE_AND_PLAY_HF(isolate_auditable_and_proof, "2-*");
|
||||
|
||||
GENERATE_AND_PLAY(zarcanum_basic_test);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2018 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
|
@ -38,9 +38,10 @@
|
|||
#include "hard_fork_1_bad_pos_source.h"
|
||||
#include "hard_fork_1.h"
|
||||
#include "hard_fork_2.h"
|
||||
#include "hard_fork_4.h"
|
||||
#include "atomic_tests.h"
|
||||
#include "isolate_auditable_and_proof.h"
|
||||
#include "zarcanum_test.h"
|
||||
#include "multiassets_test.h"
|
||||
#include "ionic_swap_tests.h"
|
||||
#include "attachment_isolation_encryption_test.h"
|
||||
#include "attachment_isolation_encryption_test.h"
|
||||
|
|
|
|||
|
|
@ -681,6 +681,7 @@ gen_no_attchments_in_coinbase::gen_no_attchments_in_coinbase()
|
|||
|
||||
bool gen_no_attchments_in_coinbase::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
this->on_test_generator_created(generator);
|
||||
uint64_t ts = 1450000000;
|
||||
test_core_time::adjust(ts);
|
||||
|
||||
|
|
@ -704,7 +705,16 @@ bool gen_no_attchments_in_coinbase::init_config_set_cp(currency::core& c, size_t
|
|||
crc.pos_minimum_heigh = 1;
|
||||
c.get_blockchain_storage().set_core_runtime_config(crc);
|
||||
|
||||
m_checkpoints.add_checkpoint(12, "475331fb4a325e722ddbc2d087d32687a58392e5a9314001120de0f2ce7737f2");
|
||||
// different checkpoints due to different block versions for different hardforks -> different hashes
|
||||
if (crc.is_hardfork_active_for_height(ZANO_HARDFORK_03, 11) && !crc.is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, 11))
|
||||
{
|
||||
m_checkpoints.add_checkpoint(12, "4e6055dda442e04b2feb70bc7245584742604e8515b8d2e1c3d46c26f758d59f");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_checkpoints.add_checkpoint(12, "475331fb4a325e722ddbc2d087d32687a58392e5a9314001120de0f2ce7737f2");
|
||||
}
|
||||
|
||||
c.set_checkpoints(currency::checkpoints(m_checkpoints));
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -612,7 +612,6 @@ bool hard_fork_2_tx_extra_alias_entry_in_wallet::c1(currency::core& c, size_t ev
|
|||
//------------------------------------------------------------------------------
|
||||
|
||||
hard_fork_2_auditable_addresses_basics::hard_fork_2_auditable_addresses_basics()
|
||||
: hard_fork_2_base_test(23)
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(hard_fork_2_auditable_addresses_basics, c1);
|
||||
}
|
||||
|
|
@ -644,6 +643,8 @@ bool hard_fork_2_auditable_addresses_basics::generate(std::vector<test_event_ent
|
|||
// make sure all Bob's outputs has mix_attr = 1
|
||||
for (auto& out : tx_1.vout)
|
||||
{
|
||||
if (out.type() != typeid(tx_out_bare))
|
||||
continue; // skip if we're in postzarcanum era
|
||||
if (boost::get<tx_out_bare>(out).amount != MK_TEST_COINS(5))
|
||||
continue; // skip change
|
||||
uint8_t mix_attr = boost::get<txout_to_key>(boost::get<tx_out_bare>(out).target).mix_attr;
|
||||
|
|
@ -677,6 +678,9 @@ bool hard_fork_2_auditable_addresses_basics::c1(currency::core& c, size_t ev_ind
|
|||
// make sure all Bob's outputs has mix_attr = 1
|
||||
for (auto& out : tx.vout)
|
||||
{
|
||||
if (out.type() != typeid(tx_out_bare))
|
||||
continue; // skip if we're in postzarcanum era
|
||||
|
||||
if (boost::get<tx_out_bare>(out).amount != MK_TEST_COINS(1))
|
||||
continue; // skip change
|
||||
uint8_t mix_attr = boost::get<txout_to_key>(boost::get<tx_out_bare>(out).target).mix_attr;
|
||||
|
|
@ -702,6 +706,9 @@ bool hard_fork_2_auditable_addresses_basics::c1(currency::core& c, size_t ev_ind
|
|||
// make sure all Bob's outputs has mix_attr = 1
|
||||
for (auto& out : tx.vout)
|
||||
{
|
||||
if (out.type() != typeid(tx_out_bare))
|
||||
continue; // skip if we're in postzarcanum era
|
||||
|
||||
if (boost::get<tx_out_bare>(out).amount != MK_TEST_COINS(1))
|
||||
continue; // skip change
|
||||
uint8_t mix_attr = boost::get<txout_to_key>(boost::get<tx_out_bare>(out).target).mix_attr;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ struct hard_fork_2_tx_extra_alias_entry_in_wallet : public hard_fork_2_base_test
|
|||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
};
|
||||
|
||||
struct hard_fork_2_auditable_addresses_basics : public hard_fork_2_base_test
|
||||
struct hard_fork_2_auditable_addresses_basics : public wallet_test //hard_fork_2_base_test
|
||||
{
|
||||
hard_fork_2_auditable_addresses_basics();
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
|
|
|
|||
223
tests/core_tests/hard_fork_4.cpp
Normal file
223
tests/core_tests/hard_fork_4.cpp
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
// Copyright (c) 2023-2024 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#include "chaingen.h"
|
||||
#include "hard_fork_4.h"
|
||||
#include "random_helper.h"
|
||||
|
||||
using namespace currency;
|
||||
|
||||
namespace currency
|
||||
{
|
||||
bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources,
|
||||
const std::vector<tx_destination_entry>& destinations,
|
||||
const std::vector<extra_v>& extra,
|
||||
const std::vector<attachment_v>& attachments,
|
||||
transaction& tx,
|
||||
uint64_t tx_version,
|
||||
crypto::secret_key& one_time_secret_key,
|
||||
uint64_t unlock_time,
|
||||
uint64_t expiration_time,
|
||||
uint8_t tx_outs_attr,
|
||||
bool shuffle,
|
||||
uint64_t flags,
|
||||
uint64_t explicit_consolidated_tx_fee,
|
||||
tx_generation_context& gen_context)
|
||||
{
|
||||
//extra copy operation, but creating transaction is not sensitive to this
|
||||
finalize_tx_param ftp{};
|
||||
ftp.tx_version = tx_version;
|
||||
ftp.sources = sources;
|
||||
ftp.prepared_destinations = destinations;
|
||||
ftp.extra = extra;
|
||||
ftp.attachments = attachments;
|
||||
ftp.unlock_time = unlock_time;
|
||||
// ftp.crypt_address = crypt_destination_addr;
|
||||
ftp.expiration_time = expiration_time;
|
||||
ftp.tx_outs_attr = tx_outs_attr;
|
||||
ftp.shuffle = shuffle;
|
||||
ftp.flags = flags;
|
||||
ftp.mode_separate_fee = explicit_consolidated_tx_fee;
|
||||
|
||||
finalized_tx ft = AUTO_VAL_INIT(ft);
|
||||
ft.tx = tx;
|
||||
ft.one_time_key = one_time_secret_key;
|
||||
ftp.gen_context = gen_context; // ftp, not ft here, this is UGLY -- sowle
|
||||
bool r = construct_tx(sender_account_keys, ftp, ft);
|
||||
tx = ft.tx;
|
||||
one_time_secret_key = ft.one_time_key;
|
||||
gen_context = ft.ftp.gen_context;
|
||||
return r;
|
||||
}
|
||||
} // namespace currency
|
||||
|
||||
void add_flags_to_all_destination_entries(const uint64_t flags, std::vector<currency::tx_destination_entry>& destinations)
|
||||
{
|
||||
for(auto& de : destinations)
|
||||
de.flags |= flags;
|
||||
}
|
||||
|
||||
//-------------------------------
|
||||
|
||||
|
||||
hard_fork_4_consolidated_txs::hard_fork_4_consolidated_txs()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(hard_fork_4_consolidated_txs, c1);
|
||||
}
|
||||
|
||||
bool hard_fork_4_consolidated_txs::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
bool r = false;
|
||||
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts);
|
||||
account_base& bob_acc = m_accounts[BOB_ACC_IDX]; bob_acc.generate(); bob_acc.set_createtime(ts);
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
|
||||
DO_CALLBACK(events, "configure_core"); // necessary for the test to be run by GENERATE_AND_PLAY_HF
|
||||
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
m_post_hf4_zarcanum = get_hardforks().get_the_most_recent_hardfork_id_for_height(CURRENCY_MINED_MONEY_UNLOCK_WINDOW) >= ZANO_HARDFORK_04_ZARCANUM;
|
||||
|
||||
uint64_t alice_amount = MK_TEST_COINS(50);
|
||||
MAKE_TX(events, tx_0a, miner_acc, alice_acc, alice_amount, blk_0r);
|
||||
// tx_0b is only needed for decoy outputs with amount = alice_amount (important only for pre-HF4)
|
||||
transaction tx_0b{};
|
||||
construct_tx_with_many_outputs(m_hardforks, events, blk_0r, miner_acc.get_keys(), miner_acc.get_public_address(), alice_amount * 10, 10, TESTS_DEFAULT_FEE, tx_0b);
|
||||
ADD_CUSTOM_EVENT(events, tx_0b);
|
||||
MAKE_NEXT_BLOCK_TX_LIST(events, blk_1, blk_0r, miner_acc, std::list<transaction>({tx_0a, tx_0b}));
|
||||
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
// check Alice's balance
|
||||
std::shared_ptr<tools::wallet2> alice_wlt;
|
||||
r = generator.init_test_wallet(alice_acc, get_block_hash(blk_0), alice_wlt);
|
||||
CHECK_AND_ASSERT_MES(r, false, "init_test_wallet failed");
|
||||
r = generator.refresh_test_wallet(events, alice_wlt.get(), get_block_hash(blk_1r), 2 * CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1);
|
||||
CHECK_AND_ASSERT_MES(r, false, "refresh_test_wallet failed");
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice", alice_amount, 0, alice_amount, 0, 0), false, "");
|
||||
|
||||
uint64_t miner_amount = MK_TEST_COINS(60);
|
||||
uint64_t bob_amount = miner_amount + alice_amount - TX_DEFAULT_FEE;
|
||||
|
||||
// Consolidated tx (TX_FLAG_SIGNATURE_MODE_SEPARATE).
|
||||
|
||||
// this data will be transferred between stage 1 and 2
|
||||
transaction tx_1{};
|
||||
crypto::secret_key one_time_secret_key{};
|
||||
tx_generation_context gen_context{};
|
||||
|
||||
// Part 1/2, miner's inputs
|
||||
{
|
||||
std::vector<tx_source_entry> sources;
|
||||
r = fill_tx_sources(sources, events, blk_1r, miner_acc.get_keys(), miner_amount, 10);
|
||||
CHECK_AND_ASSERT_MES(r, false, "fill_tx_sources failed");
|
||||
uint64_t miner_change = get_sources_total_amount(sources) - miner_amount;
|
||||
|
||||
std::vector<tx_destination_entry> destinations;
|
||||
if (miner_change != 0)
|
||||
destinations.push_back(tx_destination_entry(miner_change, miner_acc.get_public_address()));
|
||||
destinations.push_back(tx_destination_entry(bob_amount, bob_acc.get_public_address()));
|
||||
|
||||
add_flags_to_all_destination_entries(tx_destination_entry_flags::tdef_explicit_native_asset_id, destinations);
|
||||
r = construct_tx(miner_acc.get_keys(), sources, destinations, empty_extra, empty_attachment, tx_1, get_tx_version_from_events(events), one_time_secret_key,
|
||||
0, 0, 0, true, TX_FLAG_SIGNATURE_MODE_SEPARATE, TX_DEFAULT_FEE, gen_context);
|
||||
CHECK_AND_ASSERT_MES(r, false, "construct_tx failed");
|
||||
|
||||
// partially completed tx_1 shouldn't be accepted
|
||||
//DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx_1);
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_2a, blk_1r, miner_acc, tx_1);
|
||||
}
|
||||
|
||||
|
||||
// Part 2/2, Alice's inputs
|
||||
{
|
||||
std::vector<tx_source_entry> sources;
|
||||
r = fill_tx_sources(sources, events, blk_1r, alice_acc.get_keys(), alice_amount, 10);
|
||||
CHECK_AND_ASSERT_MES(r, false, "fill_tx_sources failed");
|
||||
CHECK_AND_ASSERT_MES(get_sources_total_amount(sources) == alice_amount, false, "no change for Alice is expected");
|
||||
sources.back().separately_signed_tx_complete = true;
|
||||
|
||||
std::vector<tx_destination_entry> destinations;
|
||||
|
||||
r = construct_tx(alice_acc.get_keys(), sources, destinations, empty_extra, empty_attachment, tx_1, get_tx_version_from_events(events), one_time_secret_key,
|
||||
0, 0, 0, true, TX_FLAG_SIGNATURE_MODE_SEPARATE, 0 /* note zero fee here */, gen_context);
|
||||
CHECK_AND_ASSERT_MES(r, false, "construct_tx failed");
|
||||
|
||||
ADD_CUSTOM_EVENT(events, tx_1);
|
||||
}
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_2, blk_1r, miner_acc, tx_1);
|
||||
|
||||
//std::shared_ptr<tools::wallet2> bob_wlt;
|
||||
//r = generator.init_test_wallet(bob_acc, get_block_hash(blk_0), bob_wlt);
|
||||
//CHECK_AND_ASSERT_MES(r, false, "init_test_wallet failed");
|
||||
//r = generator.refresh_test_wallet(events, bob_wlt.get(), get_block_hash(blk_2), 2 * CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 2);
|
||||
//CHECK_AND_ASSERT_MES(r, false, "refresh_test_wallet failed");
|
||||
//CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "Bob", bob_amount, 0, 0, 0, 0), false, "");
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hard_fork_4_consolidated_txs::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
hardfork_4_explicit_native_ids_in_outs::hardfork_4_explicit_native_ids_in_outs()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(hardfork_4_explicit_native_ids_in_outs, c1);
|
||||
|
||||
m_hardforks.clear();
|
||||
m_hardforks.set_hardfork_height(ZANO_HARDFORK_04_ZARCANUM, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1);
|
||||
}
|
||||
|
||||
bool hardfork_4_explicit_native_ids_in_outs::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
bool r = false;
|
||||
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts);
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
|
||||
DO_CALLBACK(events, "configure_core"); // necessary to set m_hardforks
|
||||
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
DO_CALLBACK_PARAMS(events, "check_hardfork_inactive", static_cast<size_t>(ZANO_HARDFORK_04_ZARCANUM));
|
||||
|
||||
// tx_0: miner -> Alice
|
||||
// make tx_0 before HF4, so Alice will have only bare outs
|
||||
m_alice_initial_balance = MK_TEST_COINS(1000);
|
||||
MAKE_TX(events, tx_0, miner_acc, alice_acc, m_alice_initial_balance, blk_0r);
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0);
|
||||
|
||||
// make sure HF4 has been activated
|
||||
DO_CALLBACK_PARAMS(events, "check_hardfork_active", static_cast<size_t>(ZANO_HARDFORK_04_ZARCANUM));
|
||||
|
||||
// rewind blocks
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
// check Alice's balance and make sure she cannot deploy an asset
|
||||
DO_CALLBACK(events, "c1_alice_cannot_deploy_asset");
|
||||
|
||||
// tx_1: Alice -> Alice (all coins) : this will convert all Alice outputs to ZC outs
|
||||
MAKE_TX(events, tx_1, alice_acc, alice_acc, m_alice_initial_balance - TESTS_DEFAULT_FEE, blk_1r);
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hardfork_4_explicit_native_ids_in_outs::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
26
tests/core_tests/hard_fork_4.h
Normal file
26
tests/core_tests/hard_fork_4.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) 2023-2024 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#pragma once
|
||||
#include "chaingen.h"
|
||||
#include "wallet_tests_basic.h"
|
||||
|
||||
|
||||
struct hard_fork_4_consolidated_txs : public wallet_test
|
||||
{
|
||||
hard_fork_4_consolidated_txs();
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
|
||||
mutable bool m_post_hf4_zarcanum = false;
|
||||
};
|
||||
|
||||
|
||||
struct hardfork_4_explicit_native_ids_in_outs : public wallet_test
|
||||
{
|
||||
hardfork_4_explicit_native_ids_in_outs();
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
|
||||
mutable uint64_t m_alice_initial_balance = 0;
|
||||
};
|
||||
|
|
@ -178,7 +178,7 @@ bool ionic_swap_basic_test::c1(currency::core& c, size_t ev_index, const std::ve
|
|||
// Alice wants to trade with Bob, to exchange 10.0 TCT to 0.5 ZANO
|
||||
view::ionic_swap_proposal_info proposal_details = AUTO_VAL_INIT(proposal_details);
|
||||
proposal_details.fee_paid_by_a = TESTS_DEFAULT_FEE;
|
||||
proposal_details.mixins = 10;
|
||||
proposal_details.mixins = c.get_blockchain_storage().get_core_runtime_config().hf4_minimum_mixins;
|
||||
proposal_details.to_finalizer.push_back(view::asset_funds{ asset_id , assets_to_exchange });
|
||||
proposal_details.to_initiator.push_back(view::asset_funds{ currency::native_coin_asset_id , native_coins_to_exchange });
|
||||
|
||||
|
|
@ -233,7 +233,7 @@ bool ionic_swap_basic_test::c1(currency::core& c, size_t ev_index, const std::ve
|
|||
//now Alice want to trade with Bob, to send 0.5 ZANO and get 10.0 TCT in exchange
|
||||
view::ionic_swap_proposal_info proposal_details = AUTO_VAL_INIT(proposal_details);
|
||||
proposal_details.fee_paid_by_a = TESTS_DEFAULT_FEE;
|
||||
proposal_details.mixins = 10;
|
||||
proposal_details.mixins = c.get_blockchain_storage().get_core_runtime_config().hf4_minimum_mixins;
|
||||
proposal_details.to_finalizer.push_back(view::asset_funds{ currency::native_coin_asset_id , native_coins_to_exchange });
|
||||
proposal_details.to_initiator.push_back(view::asset_funds{ asset_id , assets_to_exchange });
|
||||
|
||||
|
|
@ -375,7 +375,7 @@ bool ionic_swap_exact_amounts_test::c1(currency::core& c, size_t ev_index, const
|
|||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt, "Bob", adb.total_max_supply, 0, adb.total_max_supply, 0, 0, asset_id), false, "");
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*carol_wlt, "Carol", MK_TEST_COINS(21), 0, MK_TEST_COINS(21), 0, 0), false, "");
|
||||
|
||||
size_t current_blockchain_size = c.get_current_blockchain_size();
|
||||
//size_t current_blockchain_size = c.get_current_blockchain_size();
|
||||
|
||||
// Normal ionic swap between Alice and Bob: (Alice has only coins with explicit asset id)
|
||||
// before:
|
||||
|
|
@ -387,7 +387,7 @@ bool ionic_swap_exact_amounts_test::c1(currency::core& c, size_t ev_index, const
|
|||
proposal_details.to_initiator.push_back(view::asset_funds{ asset_id, adb.total_max_supply });
|
||||
proposal_details.to_finalizer.push_back(view::asset_funds{ native_coin_asset_id, MK_TEST_COINS(20) });
|
||||
proposal_details.fee_paid_by_a = MK_TEST_COINS(1);
|
||||
proposal_details.mixins = 2;
|
||||
proposal_details.mixins = c.get_blockchain_storage().get_core_runtime_config().hf4_minimum_mixins;
|
||||
|
||||
tools::wallet_public::ionic_swap_proposal proposal{};
|
||||
alice_wlt->create_ionic_swap_proposal(proposal_details, m_accounts[BOB_ACC_IDX].get_public_address(), proposal);
|
||||
|
|
@ -399,7 +399,9 @@ bool ionic_swap_exact_amounts_test::c1(currency::core& c, size_t ev_index, const
|
|||
proposal_decoded_info.to_initiator == proposal_details.to_initiator &&
|
||||
proposal_decoded_info.fee_paid_by_a == proposal_details.fee_paid_by_a &&
|
||||
proposal_decoded_info.mixins == proposal_details.mixins,
|
||||
false, "actual and decoded proposal mismatch");
|
||||
false, "actual and decoded proposal mismatch \nproposal_decoded_info: "
|
||||
<< epee::serialization::store_t_to_json(proposal_decoded_info) <<
|
||||
"\nproposal_details" << epee::serialization::store_t_to_json(proposal_details));
|
||||
|
||||
currency::transaction tx_is{};
|
||||
r = bob_wlt->accept_ionic_swap_proposal(proposal, tx_is);
|
||||
|
|
@ -427,7 +429,7 @@ bool ionic_swap_exact_amounts_test::c1(currency::core& c, size_t ev_index, const
|
|||
proposal_details.to_initiator.push_back(view::asset_funds{ asset_id, adb.total_max_supply });
|
||||
proposal_details.to_finalizer.push_back(view::asset_funds{ native_coin_asset_id, MK_TEST_COINS(20) });
|
||||
proposal_details.fee_paid_by_a = MK_TEST_COINS(1);
|
||||
proposal_details.mixins = 2;
|
||||
proposal_details.mixins = c.get_blockchain_storage().get_core_runtime_config().hf4_minimum_mixins;
|
||||
|
||||
proposal = tools::wallet_public::ionic_swap_proposal{};
|
||||
carol_wlt->create_ionic_swap_proposal(proposal_details, m_accounts[ALICE_ACC_IDX].get_public_address(), proposal);
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ bool isolate_auditable_and_proof::generate(std::vector<test_event_entry>& events
|
|||
generator.construct_genesis_block(blk_0, genesis_acc, test_core_time::get_time());
|
||||
events.push_back(blk_0);
|
||||
DO_CALLBACK(events, "configure_core");
|
||||
REWIND_BLOCKS_N(events, blk_0r, blk_0, m_mining_accunt, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5);
|
||||
REWIND_BLOCKS_N(events, blk_0r, blk_0, m_mining_accunt, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 15);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
epee::debug::get_set_enable_assert(true, false);
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
|
||||
CHECK_AND_ASSERT_MES(it_asset != balances.end() && it_native != balances.end(), false, "Failed to find needed asset in result balances");
|
||||
CHECK_AND_ASSERT_MES(it_asset->second.total == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC, false, "Failed to find needed asset in result balances");
|
||||
CHECK_AND_ASSERT_MES(it_native->second.total == uint64_t(17517226)*COIN, false, "Failed to find needed asset in result balances");
|
||||
CHECK_AND_ASSERT_MES(it_native->second.total == uint64_t(17517225990000000000), false, "Failed to find needed asset in result balances");
|
||||
|
||||
|
||||
balances.clear();
|
||||
|
|
@ -716,8 +716,6 @@ bool assets_and_pos_mining::generate(std::vector<test_event_entry>& events) cons
|
|||
{
|
||||
// Test idea: ensure that post-HF4 Zarcanum staking functions correctly with outputs that have a nonzero asset id blinding mask (i.e., outputs with a non-explicit asset id)
|
||||
|
||||
bool r = false;
|
||||
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
|
|
|
|||
|
|
@ -167,9 +167,10 @@ void pos_block_builder::step4_generate_coinbase_tx(size_t median_size,
|
|||
|
||||
// generate miner tx using incorrect current_block_size only for size estimation
|
||||
uint64_t block_reward_without_fee = 0;
|
||||
uint64_t block_reward = 0;
|
||||
size_t estimated_block_size = m_txs_total_size;
|
||||
bool r = construct_miner_tx(m_height, median_size, already_generated_coins, estimated_block_size, m_total_fee,
|
||||
reward_receiver_address, stakeholder_address, m_block.miner_tx, block_reward_without_fee, tx_version, extra_nonce, max_outs, true, pe, &m_miner_tx_tgc, tx_one_time_key_to_use);
|
||||
reward_receiver_address, stakeholder_address, m_block.miner_tx, block_reward_without_fee, block_reward, tx_version, extra_nonce, max_outs, true, pe, &m_miner_tx_tgc, tx_one_time_key_to_use);
|
||||
CHECK_AND_ASSERT_THROW_MES(r, "construct_miner_tx failed");
|
||||
|
||||
estimated_block_size = m_txs_total_size + get_object_blobsize(m_block.miner_tx);
|
||||
|
|
@ -177,7 +178,7 @@ void pos_block_builder::step4_generate_coinbase_tx(size_t median_size,
|
|||
for (size_t try_count = 0; try_count != 10; ++try_count)
|
||||
{
|
||||
r = construct_miner_tx(m_height, median_size, already_generated_coins, estimated_block_size, m_total_fee,
|
||||
reward_receiver_address, stakeholder_address, m_block.miner_tx, block_reward_without_fee, tx_version, extra_nonce, max_outs, true, pe, &m_miner_tx_tgc, tx_one_time_key_to_use);
|
||||
reward_receiver_address, stakeholder_address, m_block.miner_tx, block_reward_without_fee, block_reward, tx_version, extra_nonce, max_outs, true, pe, &m_miner_tx_tgc, tx_one_time_key_to_use);
|
||||
CHECK_AND_ASSERT_THROW_MES(r, "construct_homemade_pos_miner_tx failed");
|
||||
|
||||
cumulative_size = m_txs_total_size + get_object_blobsize(m_block.miner_tx);
|
||||
|
|
|
|||
|
|
@ -35,23 +35,24 @@ bool test_transaction_generation_and_ring_signature()
|
|||
std::string add_str = miner_acc3.get_public_address_str();
|
||||
|
||||
uint64_t block_reward_without_fee = 0;
|
||||
uint64_t block_reward = 0;
|
||||
|
||||
account_base rv_acc;
|
||||
rv_acc.generate();
|
||||
account_base rv_acc2;
|
||||
rv_acc2.generate();
|
||||
transaction tx_mine_1;
|
||||
construct_miner_tx(0, 0, 0, 10, 0, miner_acc1.get_keys().account_address, miner_acc1.get_keys().account_address, tx_mine_1, block_reward_without_fee, TRANSACTION_VERSION_PRE_HF4);
|
||||
construct_miner_tx(0, 0, 0, 10, 0, miner_acc1.get_keys().account_address, miner_acc1.get_keys().account_address, tx_mine_1, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4);
|
||||
transaction tx_mine_2;
|
||||
construct_miner_tx(0, 0, 0, 0, 0, miner_acc2.get_keys().account_address, miner_acc2.get_keys().account_address, tx_mine_2, block_reward_without_fee, TRANSACTION_VERSION_PRE_HF4);
|
||||
construct_miner_tx(0, 0, 0, 0, 0, miner_acc2.get_keys().account_address, miner_acc2.get_keys().account_address, tx_mine_2, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4);
|
||||
transaction tx_mine_3;
|
||||
construct_miner_tx(0, 0, 0, 0, 0, miner_acc3.get_keys().account_address, miner_acc3.get_keys().account_address, tx_mine_3, block_reward_without_fee, TRANSACTION_VERSION_PRE_HF4);
|
||||
construct_miner_tx(0, 0, 0, 0, 0, miner_acc3.get_keys().account_address, miner_acc3.get_keys().account_address, tx_mine_3, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4);
|
||||
transaction tx_mine_4;
|
||||
construct_miner_tx(0, 0, 0, 0, 0, miner_acc4.get_keys().account_address, miner_acc4.get_keys().account_address, tx_mine_4, block_reward_without_fee, TRANSACTION_VERSION_PRE_HF4);
|
||||
construct_miner_tx(0, 0, 0, 0, 0, miner_acc4.get_keys().account_address, miner_acc4.get_keys().account_address, tx_mine_4, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4);
|
||||
transaction tx_mine_5;
|
||||
construct_miner_tx(0, 0, 0, 0, 0, miner_acc5.get_keys().account_address, miner_acc5.get_keys().account_address, tx_mine_5, block_reward_without_fee, TRANSACTION_VERSION_PRE_HF4);
|
||||
construct_miner_tx(0, 0, 0, 0, 0, miner_acc5.get_keys().account_address, miner_acc5.get_keys().account_address, tx_mine_5, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4);
|
||||
transaction tx_mine_6;
|
||||
construct_miner_tx(0, 0, 0, 0, 0, miner_acc6.get_keys().account_address, miner_acc6.get_keys().account_address, tx_mine_6, block_reward_without_fee, TRANSACTION_VERSION_PRE_HF4);
|
||||
construct_miner_tx(0, 0, 0, 0, 0, miner_acc6.get_keys().account_address, miner_acc6.get_keys().account_address, tx_mine_6, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4);
|
||||
|
||||
//fill inputs entry
|
||||
typedef tx_source_entry::output_entry tx_output_entry;
|
||||
|
|
@ -136,8 +137,9 @@ bool test_block_creation()
|
|||
bool r = get_account_address_from_str(adr, "ZxDLGBGXbjo5w51tJkvxEPHFRr7Xft4hf33N8EkJPndoGCqocQF1mzpZqYwXByx5gMbfQuPAAB9vj79EFR6Jwkgu1o3aMQPwJ");
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to import");
|
||||
uint64_t block_reward_without_fee = 0;
|
||||
uint64_t block_reward = 0;
|
||||
block b;
|
||||
r = construct_miner_tx(90, epee::misc_utils::median(szs), 3553616528562147, 33094, 10000000, adr, adr, b.miner_tx, block_reward_without_fee, TRANSACTION_VERSION_PRE_HF4);
|
||||
r = construct_miner_tx(90, epee::misc_utils::median(szs), 3553616528562147, 33094, 10000000, adr, adr, b.miner_tx, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1778,9 +1778,6 @@ bool gen_wallet_alias_and_unconfirmed_txs::c3(currency::core& c, size_t ev_index
|
|||
|
||||
gen_wallet_alias_via_special_wallet_funcs::gen_wallet_alias_via_special_wallet_funcs()
|
||||
{
|
||||
// start hardfork from block 0 in order to use extra_alias_entry (allowed only since HF2)
|
||||
m_hardforks.set_hardfork_height(1, 0);
|
||||
m_hardforks.set_hardfork_height(2, 0);
|
||||
REGISTER_CALLBACK_METHOD(gen_wallet_alias_via_special_wallet_funcs, c1);
|
||||
}
|
||||
|
||||
|
|
@ -3452,7 +3449,7 @@ bool packing_outputs_on_pos_minting_wallet::c1(currency::core& c, size_t ev_inde
|
|||
CHECK_AND_ASSERT_MES(blocks_fetched == 1, false, "Incorrect numbers of blocks fetched: " << blocks_fetched);
|
||||
|
||||
// (also make sure that unlocked balance is zero)
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "bob_wlt", m_bob_initial_balance + CURRENCY_BLOCK_REWARD, CURRENCY_BLOCK_REWARD + TESTS_DEFAULT_FEE, 0), false, "");
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "bob_wlt", m_bob_initial_balance + CURRENCY_BLOCK_REWARD, INVALID_BALANCE_VAL, 0), false, "");
|
||||
|
||||
|
||||
// 2. Try to mine a PoS block and defragment some of UTXO
|
||||
|
|
@ -3465,7 +3462,7 @@ bool packing_outputs_on_pos_minting_wallet::c1(currency::core& c, size_t ev_inde
|
|||
CHECK_AND_ASSERT_MES(blocks_fetched == 2, false, "Incorrect numbers of blocks fetched: " << blocks_fetched);
|
||||
|
||||
// (also make sure that only two UTXOs is unlocked)
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", m_alice_initial_balance + CURRENCY_BLOCK_REWARD, CURRENCY_BLOCK_REWARD + TESTS_DEFAULT_FEE, m_single_amount * 2), false, "");
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", m_alice_initial_balance + CURRENCY_BLOCK_REWARD, INVALID_BALANCE_VAL, m_single_amount * 2), false, "");
|
||||
|
||||
|
||||
// 3. Try to mine a PoS block and defragment with huge decoy set. Make sure block is mined successfully without a defragmentation tx
|
||||
|
|
@ -3479,7 +3476,7 @@ bool packing_outputs_on_pos_minting_wallet::c1(currency::core& c, size_t ev_inde
|
|||
CHECK_AND_ASSERT_MES(blocks_fetched == 1, false, "Incorrect numbers of blocks fetched: " << blocks_fetched);
|
||||
|
||||
// Alice's unlocked balance should consist only of one UTXO
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", m_alice_initial_balance + CURRENCY_BLOCK_REWARD * 2, CURRENCY_BLOCK_REWARD * 2 + TESTS_DEFAULT_FEE, m_single_amount), false, "");
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", m_alice_initial_balance + CURRENCY_BLOCK_REWARD * 2, INVALID_BALANCE_VAL, m_single_amount), false, "");
|
||||
|
||||
|
||||
// 4. Finally mine a PoS and defragment the last one unlocked UTXO
|
||||
|
|
@ -3492,7 +3489,7 @@ bool packing_outputs_on_pos_minting_wallet::c1(currency::core& c, size_t ev_inde
|
|||
CHECK_AND_ASSERT_MES(blocks_fetched == 1, false, "Incorrect numbers of blocks fetched: " << blocks_fetched);
|
||||
|
||||
// Alice's unlocked balance should be zero
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", m_alice_initial_balance + CURRENCY_BLOCK_REWARD * 3, CURRENCY_BLOCK_REWARD * 3 + TESTS_DEFAULT_FEE, 0), false, "");
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", m_alice_initial_balance + CURRENCY_BLOCK_REWARD * 3, INVALID_BALANCE_VAL, 0), false, "");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ bool wallet_test::check_balance(currency::core& c, size_t ev_index, const std::v
|
|||
bool has_aliases = false;
|
||||
w->scan_tx_pool(has_aliases);
|
||||
|
||||
if (!check_balance_via_wallet(*w.get(), get_test_account_name_by_id(pcb.account_index).c_str(), pcb.total_balance, pcb.mined_balance, pcb.unlocked_balance, pcb.awaiting_in, pcb.awaiting_out))
|
||||
if (!check_balance_via_wallet(*w.get(), get_test_account_name_by_id(pcb.account_index).c_str(), pcb.total_balance, INVALID_BALANCE_VAL, pcb.unlocked_balance, pcb.awaiting_in, pcb.awaiting_out))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -215,8 +215,8 @@ bool zarcanum_basic_test::c1(currency::core& c, size_t ev_index, const std::vect
|
|||
|
||||
uint64_t mined_amount = (batches_to_Alice_count - 1) * COIN;
|
||||
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*staker_benefeciary_acc_wlt, "staker_benefeciary", mined_amount, mined_amount, mined_amount), false, "");
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*miner_benefeciary_acc_wlt, "miner_benefeciary", mined_amount, mined_amount, mined_amount), false, "");
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*staker_benefeciary_acc_wlt, "staker_benefeciary", mined_amount, INVALID_BALANCE_VAL, mined_amount), false, "");
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*miner_benefeciary_acc_wlt, "miner_benefeciary", mined_amount, INVALID_BALANCE_VAL, mined_amount), false, "");
|
||||
|
||||
|
||||
staker_benefeciary_acc_wlt->transfer(transfer_amount2, bob_wlt->get_account().get_public_address());
|
||||
|
|
@ -234,7 +234,7 @@ bool zarcanum_basic_test::c1(currency::core& c, size_t ev_index, const std::vect
|
|||
|
||||
|
||||
bob_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt, "Bob", transfer_amount2*3, UINT64_MAX, transfer_amount2*3), false, "");
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt, "Bob", transfer_amount2*3, INVALID_BALANCE_VAL, transfer_amount2*3), false, "");
|
||||
|
||||
//try to make pre-zarcanum block after hardfork 4
|
||||
currency::core_runtime_config rc = alice_wlt->get_core_runtime_config();
|
||||
|
|
@ -367,14 +367,16 @@ bool zarcanum_gen_time_balance::generate(std::vector<test_event_entry>& events)
|
|||
uint64_t bob_amount = MK_TEST_COINS(15);
|
||||
|
||||
MAKE_TX(events, tx_1, alice_acc, bob_acc, bob_amount, blk_1r);
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_2, blk_1r, miner_acc, tx_1);
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_2__, blk_1r, miner_acc, tx_1);
|
||||
|
||||
// check Bob's balance in play time...
|
||||
DO_CALLBACK_PARAMS(events, "check_balance", params_check_balance(BOB_ACC_IDX, bob_amount, 0, 0, 0, 0));
|
||||
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_2, blk_2__, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
// ... and in gen time
|
||||
CREATE_TEST_WALLET(bob_wlt, bob_acc, blk_0);
|
||||
REFRESH_TEST_WALLET_AT_GEN_TIME(events, bob_wlt, blk_2, 2 * CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5);
|
||||
REFRESH_TEST_WALLET_AT_GEN_TIME(events, bob_wlt, blk_2, 2 * CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 15);
|
||||
CHECK_TEST_WALLET_BALANCE_AT_GEN_TIME(bob_wlt, bob_amount);
|
||||
|
||||
// try to construct tx with only one output (that is wrong for HF4)
|
||||
|
|
@ -399,14 +401,16 @@ bool zarcanum_gen_time_balance::generate(std::vector<test_event_entry>& events)
|
|||
MAKE_TX_FEE_MIX(events, tx_2, bob_acc, alice_acc, bob_amount - TESTS_DEFAULT_FEE, TESTS_DEFAULT_FEE, nmix, blk_2);
|
||||
CHECK_AND_ASSERT_MES(tx_2.vout.size() != 1, false, "tx_2.vout.size() = " << tx_2.vout.size());
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_3, blk_2, miner_acc, tx_2);
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_4, blk_3, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
REFRESH_TEST_WALLET_AT_GEN_TIME(events, alice_wlt, blk_3, 2);
|
||||
|
||||
REFRESH_TEST_WALLET_AT_GEN_TIME(events, alice_wlt, blk_4, 22);
|
||||
CHECK_TEST_WALLET_BALANCE_AT_GEN_TIME(alice_wlt, alice_amount - 2 * TESTS_DEFAULT_FEE);
|
||||
|
||||
REFRESH_TEST_WALLET_AT_GEN_TIME(events, bob_wlt, blk_3, 1);
|
||||
REFRESH_TEST_WALLET_AT_GEN_TIME(events, bob_wlt, blk_4, 11);
|
||||
CHECK_TEST_WALLET_BALANCE_AT_GEN_TIME(bob_wlt, 0);
|
||||
|
||||
DO_CALLBACK_PARAMS(events, "check_balance", params_check_balance(ALICE_ACC_IDX, alice_amount - 2 * TESTS_DEFAULT_FEE, 0, 0, 0, 0));
|
||||
DO_CALLBACK_PARAMS(events, "check_balance", params_check_balance(ALICE_ACC_IDX, alice_amount - 2 * TESTS_DEFAULT_FEE, alice_amount - 2 * TESTS_DEFAULT_FEE, 0, 0, 0));
|
||||
|
||||
DO_CALLBACK_PARAMS(events, "check_balance", params_check_balance(BOB_ACC_IDX, 0, 0, 0, 0, 0));
|
||||
|
||||
|
|
@ -422,8 +426,6 @@ zarcanum_pos_block_math::zarcanum_pos_block_math()
|
|||
|
||||
bool zarcanum_pos_block_math::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
bool r = false;
|
||||
|
||||
GENERATE_ACCOUNT(miner_acc);
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time());
|
||||
DO_CALLBACK(events, "configure_core"); // necessary to set m_hardforks
|
||||
|
|
@ -602,8 +604,6 @@ zarcanum_in_alt_chain::zarcanum_in_alt_chain()
|
|||
|
||||
bool zarcanum_in_alt_chain::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
bool r = false;
|
||||
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
|
|
@ -628,7 +628,10 @@ bool zarcanum_in_alt_chain::generate(std::vector<test_event_entry>& events) cons
|
|||
|
||||
uint64_t bob_amount = COIN * 100;
|
||||
MAKE_TX(events, tx_1, miner_acc, bob_acc, bob_amount, blk_3);
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_4, blk_3, miner_acc, tx_1);
|
||||
//make another tx just to create more decoys to fit hf4 rules of 16 decoys
|
||||
account_base carol_acc; carol_acc.generate();
|
||||
MAKE_TX(events, tx_1_1, miner_acc, carol_acc, bob_amount, blk_3);
|
||||
MAKE_NEXT_BLOCK_TX_LIST(events, blk_4, blk_3, miner_acc, std::list<transaction>({ tx_1, tx_1_1 }));
|
||||
|
||||
// HF4
|
||||
// |
|
||||
|
|
@ -712,8 +715,13 @@ bool zarcanum_in_alt_chain::c1(currency::core& c, size_t ev_index, const std::ve
|
|||
|
||||
uint64_t transfer_amount = COIN;
|
||||
uint64_t transfer_fee = TESTS_DEFAULT_FEE * 3;
|
||||
size_t nmix = 38;
|
||||
bob_wlt->transfer(transfer_amount, nmix, m_accounts[ALICE_ACC_IDX].get_public_address(), transfer_fee);
|
||||
size_t nmix = 36;
|
||||
try {
|
||||
bob_wlt->transfer(transfer_amount, nmix, m_accounts[ALICE_ACC_IDX].get_public_address(), transfer_fee);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
|
||||
CHECK_AND_FORCE_ASSERT_MES(c.get_pool_transactions_count() == 3, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
|
|
@ -745,8 +753,6 @@ bool zarcanum_block_with_txs::generate(std::vector<test_event_entry>& events) co
|
|||
{
|
||||
// Test idea: make sure Zarcanum PoS block can have txs and the sum of fees is correctly added to the block reward
|
||||
|
||||
bool r = false;
|
||||
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
|
|
@ -788,14 +794,15 @@ bool zarcanum_block_with_txs::generate(std::vector<test_event_entry>& events) co
|
|||
//
|
||||
// after HF4
|
||||
//
|
||||
MAKE_NEXT_BLOCK(events, blk_3, blk_2, miner_acc);
|
||||
MAKE_NEXT_BLOCK(events, blk_3_, blk_2, miner_acc);
|
||||
MAKE_NEXT_BLOCK(events, blk_3, blk_3_, miner_acc);
|
||||
DO_CALLBACK_PARAMS(events, "check_hardfork_active", static_cast<size_t>(ZANO_HARDFORK_04_ZARCANUM));
|
||||
|
||||
MAKE_TX(events, tx_2, miner_acc, alice_acc, MK_TEST_COINS(200), blk_3);
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_4, blk_3, miner_acc, tx_2);
|
||||
m_alice_balance += MK_TEST_COINS(200);
|
||||
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_4r, blk_4, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_4r, blk_4, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW+5);
|
||||
DO_CALLBACK_PARAMS(events, "check_balance", params_check_balance(ALICE_ACC_IDX, m_alice_balance, m_alice_balance, mined_amount, 0, 0));
|
||||
|
||||
// then miner sends few coins to Bob via a tx with a big fee amount
|
||||
|
|
@ -805,8 +812,8 @@ bool zarcanum_block_with_txs::generate(std::vector<test_event_entry>& events) co
|
|||
// and Alice mines a PoS block with this tx -- so Alice is expected to receive the fee
|
||||
MAKE_NEXT_POS_BLOCK_TX1(events, blk_5, blk_4r, alice_acc, alice_stake_sources, tx_3);
|
||||
|
||||
// make sure Alice received both block reward and the fee
|
||||
uint64_t mined_amount_2 = COIN + fee;
|
||||
// make sure Alice received block reward but not received the fee
|
||||
uint64_t mined_amount_2 = COIN /* + fee */;
|
||||
DO_CALLBACK_PARAMS(events, "check_balance", params_check_balance(ALICE_ACC_IDX, m_alice_balance + mined_amount_2, UINT64_MAX, mined_amount + mined_amount_2, 0, 0));
|
||||
m_alice_balance += mined_amount_2;
|
||||
|
||||
|
|
|
|||
|
|
@ -1466,6 +1466,37 @@ TEST(crypto, point_is_zero)
|
|||
|
||||
ASSERT_TRUE(p.is_zero());
|
||||
|
||||
|
||||
memset(&p.m_p3, 0, sizeof p.m_p3);
|
||||
memcpy(&p.m_p3.Y, f_x, sizeof p.m_p3.Y);
|
||||
memcpy(&p.m_p3.Z, f_x, sizeof p.m_p3.Z);
|
||||
memcpy(&p.m_p3.T, fancy_p, sizeof p.m_p3.T);
|
||||
// {0, x, x, P} == {0, 1} (still the identity point)
|
||||
|
||||
ASSERT_TRUE(p.is_zero());
|
||||
|
||||
//
|
||||
// negative tests
|
||||
//
|
||||
|
||||
memset(&p.m_p3, 0, sizeof p.m_p3);
|
||||
// {0, 0, 0, 0} is not a point at all
|
||||
|
||||
ASSERT_FALSE(p.is_zero());
|
||||
|
||||
|
||||
memset(&p.m_p3, 0, sizeof p.m_p3);
|
||||
memcpy(&p.m_p3.Y, f_x, sizeof p.m_p3.Y);
|
||||
memcpy(&p.m_p3.Z, f_x, sizeof p.m_p3.Z);
|
||||
memcpy(&p.m_p3.T, fancy_p_plus_1, sizeof p.m_p3.T);
|
||||
// {0, x, x, !0} is not a valid point (incorrect non-zero T)
|
||||
|
||||
ASSERT_FALSE(p.is_zero());
|
||||
|
||||
memcpy(&p.m_p3.T, f_x, sizeof p.m_p3.T);
|
||||
// {0, x, x, x}, while x != 0 is still incorrect point representation
|
||||
ASSERT_FALSE(p.is_zero());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1588,6 +1619,7 @@ TEST(crypto, schnorr_sig)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
TEST(crypto, point_negation)
|
||||
{
|
||||
ASSERT_EQ(c_point_0, -c_point_0);
|
||||
|
|
@ -1620,6 +1652,252 @@ TEST(crypto, point_negation)
|
|||
}
|
||||
|
||||
|
||||
TEST(crypto, scalar_get_bits)
|
||||
{
|
||||
scalar_t x = scalar_t::random();
|
||||
for(size_t i = 0; i < 256; ++i)
|
||||
ASSERT_EQ(x.get_bits(i, 0), 0);
|
||||
for(size_t i = 0; i < 256; ++i)
|
||||
ASSERT_EQ(x.get_bits(i, std::min((size_t)255, i + 65)), 0);
|
||||
|
||||
ASSERT_EQ(x.get_bits(0, 64), x.m_u64[0]);
|
||||
ASSERT_EQ(x.get_bits(64, 64), x.m_u64[1]);
|
||||
ASSERT_EQ(x.get_bits(128, 64), x.m_u64[2]);
|
||||
ASSERT_EQ(x.get_bits(192, 64), x.m_u64[3]);
|
||||
|
||||
uint64_t high_32_bits = x.m_u64[3] >> 32;
|
||||
ASSERT_EQ(x.get_bits(192+32, 32), high_32_bits);
|
||||
|
||||
for(size_t i = 33; i <= 64; ++i)
|
||||
ASSERT_EQ(x.get_bits(192+32, i), high_32_bits);
|
||||
|
||||
for(size_t i = 0; i < 10000; ++i)
|
||||
{
|
||||
scalar_t b = scalar_t::random();
|
||||
scalar_t x = scalar_t::random();
|
||||
size_t bit_index_from = b.m_s[5];
|
||||
size_t bits_count = b.m_s[6] % 65; // [0; 64] are allowed
|
||||
|
||||
uint64_t extracted_bits = 0;
|
||||
for(size_t j = 0; j < bits_count; ++j)
|
||||
{
|
||||
if (bit_index_from + j <= 255 && x.get_bit(bit_index_from + j))
|
||||
extracted_bits |= 1ull << j;
|
||||
}
|
||||
|
||||
if (extracted_bits != x.get_bits(bit_index_from, bits_count))
|
||||
{
|
||||
std::cout << "i: " << i << ", bit_index_from: " << bit_index_from << ", bits_count: " << bits_count << ENDL
|
||||
<< "extracted_bits: " << extracted_bits << ", get_bits(): " << x.get_bits(bit_index_from, bits_count);
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
TEST(crypto, scalarmult_base_vartime)
|
||||
{
|
||||
auto check_for_x = [&](const scalar_t& x) -> bool {
|
||||
point_t P, P2;
|
||||
ge_scalarmult_base_vartime(&P.m_p3, x.m_s);
|
||||
ge_scalarmult_base(&P2.m_p3, x.m_s);
|
||||
return (P - P2).is_zero();
|
||||
};
|
||||
|
||||
ASSERT_TRUE(check_for_x(c_scalar_0));
|
||||
ASSERT_TRUE(check_for_x(c_scalar_1));
|
||||
ASSERT_TRUE(check_for_x(c_scalar_1div8));
|
||||
ASSERT_TRUE(check_for_x(c_scalar_Lm1));
|
||||
ASSERT_TRUE(check_for_x(c_scalar_L));
|
||||
|
||||
for(size_t i = 0; i < 1000; ++i)
|
||||
{
|
||||
scalar_t x = scalar_t::random();
|
||||
ASSERT_TRUE(check_for_x(x));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename CT>
|
||||
bool crypto_msm_runner(size_t N, size_t low_bits_to_clear, size_t high_bits_to_clear)
|
||||
{
|
||||
scalar_vec_t g_scalars, h_scalars;
|
||||
g_scalars.resize_and_make_random(N);
|
||||
h_scalars.resize_and_make_random(N);
|
||||
if (N > 4)
|
||||
{
|
||||
g_scalars[0] = c_scalar_Lm1; // always include the max and the min
|
||||
h_scalars[0] = c_scalar_Lm1;
|
||||
g_scalars[1] = 0;
|
||||
h_scalars[1] = 0;
|
||||
}
|
||||
|
||||
point_t sum = c_point_0;
|
||||
for(size_t i = 0; i < N; ++i)
|
||||
{
|
||||
for(size_t bit_index = 0; bit_index < low_bits_to_clear; ++bit_index)
|
||||
{
|
||||
g_scalars[i].clear_bit(bit_index);
|
||||
h_scalars[i].clear_bit(bit_index);
|
||||
}
|
||||
for(size_t bit_index = 256 - high_bits_to_clear; bit_index < 256; ++bit_index)
|
||||
{
|
||||
g_scalars[i].clear_bit(bit_index);
|
||||
h_scalars[i].clear_bit(bit_index);
|
||||
}
|
||||
sum += g_scalars[i] * CT::get_generator(false, i) + h_scalars[i] * CT::get_generator(true, i);
|
||||
}
|
||||
|
||||
//TIME_MEASURE_START(t);
|
||||
bool r = msm_and_check_zero<CT>(g_scalars, h_scalars, -sum);
|
||||
//TIME_MEASURE_FINISH(t);
|
||||
return r;
|
||||
}
|
||||
|
||||
TEST(crypto, msm)
|
||||
{
|
||||
// test the default msm_and_check_zero correctness
|
||||
bool r = false;
|
||||
|
||||
for(size_t N = 1; N <= 128; ++N)
|
||||
{
|
||||
std::cout << "N = " << N << ENDL;
|
||||
r = crypto_msm_runner<bpp_crypto_trait_Zarcanum>(N, 0, 0);
|
||||
ASSERT_TRUE(r);
|
||||
r = crypto_msm_runner<bpp_crypto_trait_ZC_out>(N, 0, 0);
|
||||
ASSERT_TRUE(r);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i <= 128; ++i)
|
||||
{
|
||||
std::cout << "i = " << i << ENDL;
|
||||
r = crypto_msm_runner<bpp_crypto_trait_Zarcanum>(128, i, 0);
|
||||
ASSERT_TRUE(r);
|
||||
r = crypto_msm_runner<bpp_crypto_trait_Zarcanum>(128, 0, i);
|
||||
ASSERT_TRUE(r);
|
||||
r = crypto_msm_runner<bpp_crypto_trait_ZC_out>(256, i, 0);
|
||||
ASSERT_TRUE(r);
|
||||
r = crypto_msm_runner<bpp_crypto_trait_ZC_out>(256, 0, i);
|
||||
ASSERT_TRUE(r);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::ge_precomp v)
|
||||
{
|
||||
o << "{{";
|
||||
|
||||
for(size_t i = 0; i < 9; ++i)
|
||||
o << v.yplusx[i] << ", ";
|
||||
|
||||
o << v.yplusx[9] << "}, {";
|
||||
|
||||
for(size_t i = 0; i < 9; ++i)
|
||||
o << v.yminusx[i] << ", ";
|
||||
|
||||
o << v.yminusx[9] << "}, {";
|
||||
|
||||
for(size_t i = 0; i < 9; ++i)
|
||||
o << v.xy2d[i] << ", ";
|
||||
|
||||
o << v.xy2d[9] << "}}";
|
||||
return o;
|
||||
}
|
||||
|
||||
bool calc_and_print_generator_precomp(const point_pc_t& generator, const char* generator_var_name)
|
||||
{
|
||||
precomp_data_t precomp_data = {};
|
||||
construct_precomp_data(precomp_data, generator);
|
||||
|
||||
std::cout << " const precomp_data_t " << generator_var_name << "_precomp_data = {" << ENDL;
|
||||
|
||||
for(size_t i = 0; i < 32; ++i)
|
||||
{
|
||||
std::cout << " {" << ENDL;
|
||||
for(size_t j = 0; j < 8; ++j)
|
||||
std::cout << " " << precomp_data[i][j] << (j != 7 ? "," : "" ) << ENDL;
|
||||
std::cout << " }" << (i != 31 ? "," : "" ) << ENDL;
|
||||
}
|
||||
|
||||
std::cout << " };" << ENDL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(print, generators_precomp)
|
||||
{
|
||||
#define CALC_PRECOMP(G) calc_and_print_generator_precomp(G, #G)
|
||||
|
||||
CALC_PRECOMP(c_point_H);
|
||||
CALC_PRECOMP(c_point_H2);
|
||||
CALC_PRECOMP(c_point_U);
|
||||
CALC_PRECOMP(c_point_X);
|
||||
CALC_PRECOMP(c_point_H_plus_G);
|
||||
CALC_PRECOMP(c_point_H_minus_G);
|
||||
return true;
|
||||
|
||||
#undef CALC_PRECOMP
|
||||
}
|
||||
|
||||
bool check_generator_precomp(const point_pc_t& generator, const char* generator_var_name)
|
||||
{
|
||||
point_t generator_pt = generator; // to avoid using precomputed data in scalar multiplications
|
||||
point_t random_point = hash_helper_t::hp(scalar_t::random());
|
||||
|
||||
point_t A = generator_pt;
|
||||
for(size_t i = 0; i < 32; ++i)
|
||||
{
|
||||
point_t B = c_point_0;
|
||||
for(size_t j = 0; j < 8; ++j)
|
||||
{
|
||||
B += A;
|
||||
|
||||
// restore ge_p3 from ge_precomp using native NaCl functions...
|
||||
point_t restored_pt{};
|
||||
ge_p1p1 p1p1{};
|
||||
ge_madd(&p1p1, &random_point.m_p3, &((*generator.m_precomp_data_p)[i][j]));
|
||||
ge_p1p1_to_p3(&restored_pt.m_p3, &p1p1);
|
||||
restored_pt -= random_point;
|
||||
|
||||
// ...and compare it with the calculated one
|
||||
if (B != restored_pt)
|
||||
{
|
||||
std::cout << "ERROR: " << generator_var_name << ", i: " << i << ", j: " << j << ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (i != 31)
|
||||
A.modify_mul_pow_2(8);
|
||||
}
|
||||
|
||||
std::cout << " " << std::left << std::setw(32) << generator_var_name << " OK" << ENDL;
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(crypto, generators_precomp)
|
||||
{
|
||||
#define CHECK_PRECOMP(G) ASSERT_TRUE(check_generator_precomp(G, #G))
|
||||
|
||||
CHECK_PRECOMP(c_point_H);
|
||||
CHECK_PRECOMP(c_point_H2);
|
||||
CHECK_PRECOMP(c_point_U);
|
||||
CHECK_PRECOMP(c_point_X);
|
||||
CHECK_PRECOMP(c_point_H_plus_G);
|
||||
CHECK_PRECOMP(c_point_H_minus_G);
|
||||
|
||||
return true;
|
||||
|
||||
#undef CHECK_PRECOMP
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// test's runner
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2022 Zano Project (https://zano.org/)
|
||||
// Copyright (c) 2022 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Copyright (c) 2022-2024 Zano Project (https://zano.org/)
|
||||
// Copyright (c) 2022-2024 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#pragma once
|
||||
|
|
@ -166,11 +166,11 @@ TEST(clsag, bad_pub_keys)
|
|||
ASSERT_TRUE(cc.generate());
|
||||
ASSERT_TRUE(cc.verify());
|
||||
|
||||
// torsion component in K1 should not affect protocol
|
||||
// torsion component in K1 should break the protocol
|
||||
cc = cc_orig;
|
||||
ASSERT_TRUE(cc.generate());
|
||||
cc.sig.K1 = (point_t(cc.sig.K1) + tor).to_public_key();
|
||||
ASSERT_TRUE(cc.verify());
|
||||
ASSERT_FALSE(cc.verify());
|
||||
|
||||
// torsion component in stealth_address for secret_index (i.e. for P = xG) must break the protocol
|
||||
// 1
|
||||
|
|
@ -399,9 +399,9 @@ TEST(clsag_ggx, basics)
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CLSAG GGXG
|
||||
// CLSAG GGXG (eventually not used in Zano)
|
||||
//
|
||||
|
||||
/*
|
||||
struct clsag_ggxg_sig_check_t
|
||||
{
|
||||
crypto::hash prefix_hash;
|
||||
|
|
@ -537,7 +537,7 @@ TEST(clsag_ggxg, basics)
|
|||
ASSERT_TRUE(cc.verify());
|
||||
|
||||
return true;
|
||||
}
|
||||
}*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
|
|
|||
|
|
@ -2,8 +2,61 @@
|
|||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#pragma once
|
||||
#include <numeric>
|
||||
|
||||
TEST(crypto, primitives)
|
||||
uint64_t get_bits_v1(const scalar_t& s, uint8_t bit_index_first, uint8_t bits_count)
|
||||
{
|
||||
if (bits_count == 0 || bits_count > 64)
|
||||
return 0;
|
||||
unsigned int bit_index_last = bit_index_first + bits_count - 1;
|
||||
if (bit_index_last > 255)
|
||||
bit_index_last = 255;
|
||||
uint64_t result_mask = ((1ull << (bits_count - 1)) - 1) << 1 | 1; // (just because 1ull << 64 in undefined behaviour, not a 0 as one would expect)
|
||||
|
||||
uint64_t result = s.m_u64[bit_index_first >> 6] >> (bit_index_first & 63);
|
||||
if (bits_count > (bit_index_last & 63) + 1)
|
||||
result |= s.m_u64[bit_index_last >> 6] << (bits_count - (bit_index_last & 63) - 1);
|
||||
return result & result_mask;
|
||||
}
|
||||
|
||||
|
||||
TEST(crypto, ge_precomp)
|
||||
{
|
||||
//precomp_data_t G_precomp = {};
|
||||
//construct_precomp_data(G_precomp, c_point_G);
|
||||
//std::cout << "size of G_precomp: " << sizeof G_precomp << " bytes" << ENDL;
|
||||
//for(size_t i = 0; i < 32; ++i)
|
||||
// for(size_t j = 0; j < 8; ++j)
|
||||
// std::cout << "i: " << i << ", j: " << j << ", precomp: " << ENDL << G_precomp[i][j] << ENDL;
|
||||
|
||||
precomp_data_t H_precomp = {};
|
||||
construct_precomp_data(H_precomp, c_point_H);
|
||||
|
||||
auto check_for_x = [&](const scalar_t& x) -> bool {
|
||||
point_t P;
|
||||
ge_scalarmult_precomp_vartime(&P.m_p3, H_precomp, x.m_s);
|
||||
return P == x * c_point_H;
|
||||
};
|
||||
|
||||
ASSERT_TRUE(check_for_x(c_scalar_0));
|
||||
ASSERT_TRUE(check_for_x(c_scalar_1));
|
||||
ASSERT_TRUE(check_for_x(c_scalar_1div8));
|
||||
ASSERT_TRUE(check_for_x(c_scalar_Lm1));
|
||||
ASSERT_TRUE(check_for_x(c_scalar_L));
|
||||
|
||||
for(size_t i = 0; i < 1000; ++i)
|
||||
{
|
||||
scalar_t x = scalar_t::random();
|
||||
ASSERT_TRUE(check_for_x(x));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TEST(perf, primitives)
|
||||
{
|
||||
struct helper
|
||||
{
|
||||
|
|
@ -46,6 +99,44 @@ TEST(crypto, primitives)
|
|||
|
||||
#define HASH_64_VEC(vec_var_name) hash_64(vec_var_name.data(), vec_var_name.size() * sizeof(vec_var_name[0]))
|
||||
|
||||
LOG_PRINT_L0(ENDL << "hash functions:");
|
||||
|
||||
struct run_cn_fash_hash
|
||||
{
|
||||
static uint64_t run(timer_t& t, size_t rounds, size_t data_size)
|
||||
{
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
struct bytes64
|
||||
{
|
||||
unsigned char b[64];
|
||||
};
|
||||
|
||||
std::vector<bytes64> scalars_64(rounds);
|
||||
for (size_t i = 0; i < scalars_64.size(); ++i)
|
||||
crypto::generate_random_bytes(sizeof(bytes64), scalars_64[i].b);
|
||||
|
||||
std::vector<hash> results(rounds);
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
results[i] = cn_fast_hash(scalars_64[rnd_indecies[i]].b, 64);
|
||||
}
|
||||
t.stop();
|
||||
|
||||
return HASH_64_VEC(results);
|
||||
};
|
||||
};
|
||||
|
||||
run("cn_fast_hash(64 bytes)", 1000, [](timer_t& t, size_t rounds) {
|
||||
return run_cn_fash_hash::run(t, rounds, 64ull);
|
||||
});
|
||||
|
||||
run("cn_fast_hash(2048 bytes)", 1000, [](timer_t& t, size_t rounds) {
|
||||
return run_cn_fash_hash::run(t, rounds, 2048ull);
|
||||
});
|
||||
|
||||
LOG_PRINT_L0(ENDL << "native crypto primitives:");
|
||||
|
||||
run("sc_reduce", 30000, [](timer_t& t, size_t rounds) {
|
||||
|
|
@ -239,7 +330,7 @@ TEST(crypto, primitives)
|
|||
return HASH_64_VEC(points_cached);
|
||||
});
|
||||
|
||||
run("ge_add(p3 + p3)", 50000, [](timer_t& t, size_t rounds) {
|
||||
run("ge_add(p1p1 = p3 + cached)", 50000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
std::vector<ge_cached> points_cached(rounds);
|
||||
|
|
@ -454,7 +545,7 @@ TEST(crypto, primitives)
|
|||
return HASH_64_VEC(points_p3);
|
||||
});
|
||||
|
||||
run("ge_scalarmult_base()", 5000, [](timer_t& t, size_t rounds) {
|
||||
run("ge_scalarmult_base()", 10000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
|
|
@ -479,6 +570,87 @@ TEST(crypto, primitives)
|
|||
return HASH_64_VEC(points_p3);
|
||||
});
|
||||
|
||||
run("construct_precomp_data()", 300, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
unsigned char s[32] = {};
|
||||
std::vector<point_t> random_points(rounds);
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
s[0] = i;
|
||||
ge_p2 p2;
|
||||
ge_fromfe_frombytes_vartime(&p2, s);
|
||||
ge_p2_to_p3(&random_points[i].m_p3, &p2);
|
||||
}
|
||||
|
||||
std::vector<ge_p3> points_p3(rounds);
|
||||
precomp_data_t precomp_data;
|
||||
uint64_t result = 0;
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
construct_precomp_data(precomp_data, random_points[rnd_indecies[i]]);
|
||||
result ^= (precomp_data[1][1].xy2d[1] + precomp_data[31][7].xy2d[9]);
|
||||
}
|
||||
t.stop();
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
run("ge_scalarmult_precomp_vartime()", 10000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
scalar_t x;
|
||||
x.make_random();
|
||||
|
||||
std::vector<crypto::ec_scalar> scalars(rounds);
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
scalar_t x = x + x + x;
|
||||
memcpy(&scalars[i].data, x.data(), 32);
|
||||
}
|
||||
|
||||
precomp_data_t precomp_data;
|
||||
construct_precomp_data(precomp_data, x * c_point_X);
|
||||
|
||||
std::vector<ge_p3> points_p3(rounds);
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
ge_scalarmult_precomp_vartime(&points_p3[i], precomp_data, (const unsigned char*)&scalars[rnd_indecies[i]]);
|
||||
}
|
||||
t.stop();
|
||||
|
||||
return HASH_64_VEC(points_p3);
|
||||
});
|
||||
|
||||
run("ge_scalarmult_base_vartime()", 10000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
scalar_t x;
|
||||
x.make_random();
|
||||
|
||||
std::vector<crypto::ec_scalar> scalars(rounds);
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
scalar_t x = x + x + x;
|
||||
memcpy(&scalars[i].data, x.data(), 32);
|
||||
}
|
||||
|
||||
std::vector<ge_p3> points_p3(rounds);
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
ge_scalarmult_base_vartime(&points_p3[i], (const unsigned char*)&scalars[rnd_indecies[i]]);
|
||||
}
|
||||
t.stop();
|
||||
|
||||
return HASH_64_VEC(points_p3);
|
||||
});
|
||||
|
||||
run("ge_mul8_p3()", 5000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
|
@ -662,5 +834,402 @@ TEST(crypto, primitives)
|
|||
return HASH_64_VEC(result);
|
||||
});
|
||||
|
||||
run("get_bits x 10", 20000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
scalar_vec_t data;
|
||||
data.resize_and_make_random(rounds);
|
||||
|
||||
std::vector<uint64_t> result(rounds);
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
auto& x = data[rnd_indecies[i]];
|
||||
result[i] =
|
||||
x.get_bits(x.m_s[11], x.m_s[21] % 65) ^
|
||||
x.get_bits(x.m_s[12], x.m_s[22] % 65) ^
|
||||
x.get_bits(x.m_s[13], x.m_s[23] % 65) ^
|
||||
x.get_bits(x.m_s[14], x.m_s[24] % 65) ^
|
||||
x.get_bits(x.m_s[15], x.m_s[25] % 65) ^
|
||||
x.get_bits(x.m_s[16], x.m_s[26] % 65) ^
|
||||
x.get_bits(x.m_s[17], x.m_s[27] % 65) ^
|
||||
x.get_bits(x.m_s[18], x.m_s[28] % 65) ^
|
||||
x.get_bits(x.m_s[19], x.m_s[29] % 65) ^
|
||||
x.get_bits(x.m_s[20], x.m_s[30] % 65);
|
||||
}
|
||||
t.stop();
|
||||
|
||||
return HASH_64_VEC(result);
|
||||
});
|
||||
|
||||
return true;
|
||||
} // TEST
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////// v3
|
||||
|
||||
|
||||
|
||||
///////////////// v4
|
||||
|
||||
|
||||
template<typename CT>
|
||||
bool msm_and_check_zero_pippenger_v4(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand, size_t c)
|
||||
{
|
||||
// TODO: with c = 8 and with direct access got much worse result than with c = 7 and get_bits(), consider checking again for bigger datasets (N>256)
|
||||
CHECK_AND_ASSERT_MES(g_scalars.size() <= CT::c_bpp_mn_max, false, "g_scalars oversized");
|
||||
CHECK_AND_ASSERT_MES(h_scalars.size() <= CT::c_bpp_mn_max, false, "h_scalars oversized");
|
||||
CHECK_AND_ASSERT_MES(c < 10, false, "c is too big");
|
||||
|
||||
size_t C = 1ull << c;
|
||||
|
||||
// k_max * c + (c-1) >= max_bit_idx
|
||||
//
|
||||
// max_bit_idx - (c - 1) max_bit_idx - (c - 1) + (c - 1) max_bit_idx
|
||||
// k_max = ceil ( --------------------- ) = floor ( ------------------------------ ) = floor ( ----------- )
|
||||
// c c c
|
||||
const size_t b = 253; // the maximum number of bits in x https://eprint.iacr.org/2022/999.pdf TODO: we may also scan for maximum bit used in all the scalars if all the scalars are small
|
||||
const size_t max_bit_idx = b - 1;
|
||||
const size_t k_max = max_bit_idx / c;
|
||||
const size_t K = k_max + 1;
|
||||
|
||||
std::unique_ptr<point_t[]> buckets( new point_t[C * K] );
|
||||
std::vector<bool> buckets_inited(C * K);
|
||||
|
||||
// first loop, calculate partial bucket sums
|
||||
for (size_t n = 0; n < g_scalars.size(); ++n)
|
||||
{
|
||||
for (size_t k = 0; k < K; ++k)
|
||||
{
|
||||
uint64_t l = g_scalars[n].get_bits(k * c, c); // l in [0; 2^c-1]
|
||||
if (l != 0)
|
||||
{
|
||||
size_t bucket_id = l * K + k;
|
||||
if (buckets_inited[bucket_id])
|
||||
buckets[bucket_id] += CT::get_generator(false, n);
|
||||
else
|
||||
{
|
||||
buckets[bucket_id] = CT::get_generator(false, n);
|
||||
buckets_inited[bucket_id] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t n = 0; n < h_scalars.size(); ++n)
|
||||
{
|
||||
for (size_t k = 0; k < K; ++k)
|
||||
{
|
||||
uint64_t l = h_scalars[n].get_bits(k * c, c); // l in [0; 2^c-1]
|
||||
if (l != 0)
|
||||
{
|
||||
size_t bucket_id = l * K + k;
|
||||
if (buckets_inited[bucket_id])
|
||||
buckets[bucket_id] += CT::get_generator(true, n);
|
||||
else
|
||||
{
|
||||
buckets[bucket_id] = CT::get_generator(true, n);
|
||||
buckets_inited[bucket_id] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the second loop
|
||||
// S[l, k] = S[l-1, k] + B[l, k]
|
||||
// G[k] = sum{1..C-1} S[l, k]
|
||||
std::unique_ptr<point_t[]> Sk( new point_t[K] );
|
||||
std::vector<bool> Sk_inited(K);
|
||||
std::unique_ptr<point_t[]> Gk( new point_t[K] );
|
||||
std::vector<bool> Gk_inited(K);
|
||||
for (size_t l = C - 1; l > 0; --l)
|
||||
{
|
||||
for (size_t k = 0; k < K; ++k)
|
||||
{
|
||||
size_t bucket_id = l * K + k;
|
||||
if (buckets_inited[bucket_id])
|
||||
{
|
||||
if (Sk_inited[k])
|
||||
Sk[k] += buckets[bucket_id];
|
||||
else
|
||||
{
|
||||
Sk[k] = buckets[bucket_id];
|
||||
Sk_inited[k] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (Sk_inited[k])
|
||||
{
|
||||
if (Gk_inited[k])
|
||||
Gk[k] += Sk[k];
|
||||
else
|
||||
{
|
||||
Gk[k] = Sk[k];
|
||||
Gk_inited[k] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the third loop: Horner’s rule
|
||||
point_t result = Gk_inited[K - 1] ? Gk[K - 1] : c_point_0;
|
||||
for (size_t k = K - 2; k != SIZE_MAX; --k)
|
||||
{
|
||||
result.modify_mul_pow_2(c);
|
||||
if (Gk_inited[k])
|
||||
result += Gk[k];
|
||||
}
|
||||
|
||||
result += summand;
|
||||
|
||||
if (!result.is_zero())
|
||||
{
|
||||
LOG_PRINT_L0("msm result is non zero: " << result);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//template<typename CT>
|
||||
//struct mes_msm_and_check_zero_pippenger_v1
|
||||
//{
|
||||
// static bool msm_and_check_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand, size_t c)
|
||||
// {
|
||||
// return msm_and_check_zero_pippenger_v1<CT>(g_scalars, h_scalars, summand, c);
|
||||
// }
|
||||
//};
|
||||
//
|
||||
//template<typename CT>
|
||||
//struct mes_msm_and_check_zero_pippenger_v2
|
||||
//{
|
||||
// static bool msm_and_check_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand, size_t c)
|
||||
// {
|
||||
// return msm_and_check_zero_pippenger_v2<CT>(g_scalars, h_scalars, summand, c);
|
||||
// }
|
||||
//};
|
||||
|
||||
template<typename CT>
|
||||
struct mes_msm_and_check_zero_pippenger_v3
|
||||
{
|
||||
static bool msm_and_check_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand, size_t c)
|
||||
{
|
||||
return msm_and_check_zero_pippenger_v3<CT>(g_scalars, h_scalars, summand, c);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename CT>
|
||||
struct mes_msm_and_check_zero_pippenger_v4
|
||||
{
|
||||
static bool msm_and_check_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand, size_t c)
|
||||
{
|
||||
return msm_and_check_zero_pippenger_v4<CT>(g_scalars, h_scalars, summand, c);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct pme_runner_i
|
||||
{
|
||||
virtual ~pme_runner_i() {}
|
||||
virtual bool iteration(bool warmup) = 0;
|
||||
};
|
||||
|
||||
template<size_t N, typename CT, template<typename> typename selector_t>
|
||||
struct pme_runner_t : public pme_runner_i
|
||||
{
|
||||
pme_runner_t(const char* testname_, size_t pip_partition_bits_c)
|
||||
: testname(testname_)
|
||||
, pip_partition_bits_c(pip_partition_bits_c)
|
||||
{
|
||||
testname += std::string(", ") + std::string(typeid(selector_t<CT>).name()).erase(0, 11) + std::string(", c = ") + epee::string_tools::num_to_string_fast(pip_partition_bits_c);
|
||||
std::cout << testname << ENDL;
|
||||
}
|
||||
virtual ~pme_runner_t()
|
||||
{
|
||||
if (timings.empty())
|
||||
return;
|
||||
|
||||
uint64_t median = 0;
|
||||
auto median_it = timings.begin() + timings.size() / 2;
|
||||
std::nth_element(timings.begin(), median_it, timings.end());
|
||||
median = *median_it;
|
||||
if (timings.size() % 2 == 0)
|
||||
{
|
||||
auto max_it = std::max_element(timings.begin(), median_it);
|
||||
median = (median + *max_it) / 2;
|
||||
}
|
||||
|
||||
uint64_t total_time = std::accumulate(timings.begin(), timings.end(), 0);
|
||||
std::cout << std::left << std::setw(100) << testname << " : " << std::setw(5) << median << " (median), " << std::setw(5) << total_time / timings.size() << " (avg), mcs" << ENDL;
|
||||
}
|
||||
|
||||
virtual bool iteration(bool warmup)
|
||||
{
|
||||
scalar_vec_t g_scalars, h_scalars;
|
||||
g_scalars.resize_and_make_random(N);
|
||||
g_scalars[0] = c_scalar_Lm1;
|
||||
//std::cout << "bit 251: " << g_scalars[0].get_bit(251) << ", bit 252: " << g_scalars[0].get_bit(252) << ENDL;
|
||||
h_scalars.resize_and_make_random(N);
|
||||
point_t sum = c_point_0;
|
||||
for(size_t i = 0; i < N; ++i)
|
||||
{
|
||||
//g_scalars[i].m_u64[3] = 0;
|
||||
//h_scalars[i].m_u64[3] = 0;
|
||||
//g_scalars[i].m_s[31] = 0;
|
||||
//h_scalars[i].m_s[31] = 0;
|
||||
sum += g_scalars[i] * CT::get_generator(false, i) + h_scalars[i] * CT::get_generator(true, i);
|
||||
}
|
||||
|
||||
TIME_MEASURE_START(t);
|
||||
bool r = selector_t<CT>::msm_and_check_zero(g_scalars, h_scalars, -sum, pip_partition_bits_c);
|
||||
TIME_MEASURE_FINISH(t);
|
||||
ASSERT_TRUE(r);
|
||||
|
||||
if (!warmup)
|
||||
timings.push_back(t);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<uint64_t> timings;
|
||||
std::string testname;
|
||||
size_t pip_partition_bits_c;
|
||||
};
|
||||
|
||||
|
||||
TEST(perf, msm)
|
||||
{
|
||||
bool r = false;
|
||||
|
||||
std::deque<std::unique_ptr<pme_runner_i>> runners;
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 1));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 2));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 3));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 4));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 5));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 6));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 7));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 8));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 9));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 1));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 2));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 3));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 4));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 5));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 6));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 7));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 8));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 9));
|
||||
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 1));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 2));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 3));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 4));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 5));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 6));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 7));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 8));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 9));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 1));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 2));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 3));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 4));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 5));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 6));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 7));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 8));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 9));
|
||||
|
||||
|
||||
runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v3> >("Zarcanum, BPPE, 128 +++++++++++", 7));
|
||||
runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v3> >("ZC out, BPP, 256 +++++++++++", 7));
|
||||
|
||||
runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v4> >("Zarcanum, BPPE, 128 ###########", 7));
|
||||
runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v4> >("ZC out, BPP, 256 ###########", 7));
|
||||
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 7));
|
||||
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 7));
|
||||
|
||||
|
||||
std::cout << "warm up..." << ENDL;
|
||||
size_t runs_count = 30;
|
||||
for(size_t k = 0; k < runs_count; ++k)
|
||||
{
|
||||
for(auto& runner : runners)
|
||||
ASSERT_TRUE(runner->iteration(true));
|
||||
}
|
||||
|
||||
runs_count = 200;
|
||||
for(size_t k = 0; k < runs_count; ++k)
|
||||
{
|
||||
for(auto& runner : runners)
|
||||
ASSERT_TRUE(runner->iteration(false));
|
||||
|
||||
size_t done_percent = 100 * k / runs_count;
|
||||
if (100 * (k + 1) / runs_count > done_percent && done_percent % 5 == 0)
|
||||
std::cout << done_percent << " %" << ENDL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool perf_generators_runner(const T& generator, const char* title)
|
||||
{
|
||||
const size_t warmup_rounds = 20;
|
||||
const size_t rounds = 500;
|
||||
const size_t inner_rounds = 128;
|
||||
uint64_t h = 0;
|
||||
std::vector<uint64_t> timings;
|
||||
|
||||
size_t N = 1024;
|
||||
scalar_vec_t scalars;
|
||||
scalars.resize_and_make_random(N);
|
||||
std::vector<point_t> points(N);
|
||||
|
||||
for(size_t i = 0; i < warmup_rounds; ++i)
|
||||
for(size_t j = 0; j < inner_rounds; ++j)
|
||||
points[(i + j) % N] = scalars[(i + j) % N] * generator;
|
||||
|
||||
h = hash_64(points.data(), points.size() * sizeof(point_t));
|
||||
|
||||
for(size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
TIME_MEASURE_START(t);
|
||||
for(size_t j = 0; j < inner_rounds; ++j)
|
||||
points[(i + j) % N] = scalars[(i + j) % N] * generator;
|
||||
TIME_MEASURE_FINISH(t);
|
||||
timings.push_back(t);
|
||||
}
|
||||
|
||||
h ^= hash_64(points.data(), points.size() * sizeof(point_t));
|
||||
|
||||
std::cout << std::left << std::setw(20) << title << " : " << std::setw(5) << std::fixed << std::setprecision(1) << (double)epee::misc_utils::median(timings) / inner_rounds << " mcs, hash = " << h << ENDL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(perf, generators)
|
||||
{
|
||||
#define TEST_GENERATOR(G) ASSERT_TRUE(perf_generators_runner(G, #G))
|
||||
|
||||
TEST_GENERATOR(c_point_0);
|
||||
TEST_GENERATOR(c_point_G);
|
||||
TEST_GENERATOR(c_point_H);
|
||||
TEST_GENERATOR(c_point_H2);
|
||||
TEST_GENERATOR(c_point_U);
|
||||
TEST_GENERATOR(c_point_X);
|
||||
TEST_GENERATOR(c_point_H_plus_G);
|
||||
TEST_GENERATOR(c_point_H_minus_G);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
43
tests/unit_tests/decoy_selection.cpp
Normal file
43
tests/unit_tests/decoy_selection.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) 2019 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#include <algorithm>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "wallet/decoy_selection.h"
|
||||
|
||||
TEST(decoy_selection_test, decoy_selection_test)
|
||||
{
|
||||
const uint64_t test_scale_size = 20000;
|
||||
decoy_selection_generator dsg;
|
||||
dsg.init(test_scale_size - 1);
|
||||
std::map<uint64_t, uint64_t> hits;
|
||||
//std::vector<uint64_t> hits(test_scale_size, 0);
|
||||
|
||||
|
||||
// while (true)
|
||||
// {
|
||||
// std::vector<uint64_t> decoys = dsg.generate_distribution(15);
|
||||
// for (auto d : decoys)
|
||||
// {
|
||||
// hits[d]++;
|
||||
// }
|
||||
//
|
||||
// if (hits[10] > 500)
|
||||
// break;
|
||||
//
|
||||
// }
|
||||
// std::stringstream ss;
|
||||
// for (auto it = hits.begin(); it != hits.end(); it++)
|
||||
// {
|
||||
// //if (hits[i] != 0)
|
||||
// {
|
||||
// ss << it->first << ", " << it->second << ENDL;
|
||||
// }
|
||||
// }
|
||||
// epee::file_io_utils::save_string_to_file("distribution.csv", ss.str());
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -69,8 +69,81 @@ TEST(fork_choice_rule_test, fork_choice_rule_test_1)
|
|||
ASSERT_FALSE(res);
|
||||
res = if_alt_chain_stronger(200000, 14000);
|
||||
ASSERT_TRUE(res);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool if_alt_chain_stronger_hf4(const currency::wide_difficulty_type& pos, const currency::wide_difficulty_type& pow)
|
||||
{
|
||||
currency::difficulties main_cumul_diff;
|
||||
main_cumul_diff.pos_diff.assign("1605973467987652534120344647");
|
||||
main_cumul_diff.pow_diff.assign("3011264554002844981");
|
||||
currency::difficulties alt_cumul_diff;
|
||||
alt_cumul_diff.pow_diff = pow;
|
||||
alt_cumul_diff.pos_diff = pos;
|
||||
currency::wide_difficulty_type difficulty_pos_at_split_point = main_cumul_diff.pos_diff;
|
||||
currency::wide_difficulty_type difficulty_pow_at_split_point = main_cumul_diff.pow_diff;
|
||||
boost::multiprecision::uint1024_t main = currency::get_a_to_b_relative_cumulative_difficulty_hf4(difficulty_pos_at_split_point, difficulty_pow_at_split_point, main_cumul_diff, alt_cumul_diff);
|
||||
boost::multiprecision::uint1024_t alt = currency::get_a_to_b_relative_cumulative_difficulty_hf4(difficulty_pos_at_split_point, difficulty_pow_at_split_point, alt_cumul_diff, main_cumul_diff);
|
||||
if (alt > main)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
TEST(fork_choice_rule_test, fork_choice_rule_test_hf4)
|
||||
{
|
||||
std::stringstream ss;
|
||||
currency::wide_difficulty_type pos_start, pos_end, pos_step, pos_diveder;
|
||||
pos_start.assign("16059734679876525341203446");
|
||||
pos_end.assign ("16059734679876525341203446400");
|
||||
pos_step.assign ("50000000000000000000000000");
|
||||
pos_diveder.assign("100000000000000000000000");
|
||||
|
||||
currency::wide_difficulty_type pow_start, pow_end, pow_step, pow_diveder;
|
||||
pow_start.assign("301126455400284498");
|
||||
pow_end.assign ("30112645540028449810");
|
||||
pow_step.assign ("500000000000000000");
|
||||
pow_diveder.assign("1000000000000000");
|
||||
|
||||
|
||||
for (currency::wide_difficulty_type pos = pos_start; pos < pos_end; pos += pos_step)
|
||||
{
|
||||
for (currency::wide_difficulty_type pow = pow_start; pow < pow_end; pow += pow_step)
|
||||
{
|
||||
bool r = if_alt_chain_stronger_hf4(pos, pow);
|
||||
if(r)
|
||||
ss << pos/ pos_diveder << "\t" << pow / pow_diveder << std::endl;
|
||||
//ss << pos << "\t" << pow << "\t" << (r ? "1" : "0") << std::endl;
|
||||
}
|
||||
}
|
||||
bool r = epee::file_io_utils::save_string_to_file("stat_hf4.txt", ss.str());
|
||||
|
||||
|
||||
bool res = false;
|
||||
res = if_alt_chain_stronger_hf4(1000000, 1000);
|
||||
ASSERT_FALSE(res);
|
||||
res = if_alt_chain_stronger_hf4(1000000, 1500);
|
||||
ASSERT_TRUE(res);
|
||||
res = if_alt_chain_stronger_hf4(800000, 1700);
|
||||
ASSERT_FALSE(res);
|
||||
res = if_alt_chain_stronger_hf4(800000, 2000);
|
||||
ASSERT_TRUE(res);
|
||||
res = if_alt_chain_stronger_hf4(600000, 2200);
|
||||
ASSERT_FALSE(res);
|
||||
res = if_alt_chain_stronger_hf4(600000, 2800);
|
||||
ASSERT_TRUE(res);
|
||||
res = if_alt_chain_stronger_hf4(400000, 3999);
|
||||
ASSERT_FALSE(res);
|
||||
res = if_alt_chain_stronger_hf4(400000, 4001);
|
||||
ASSERT_TRUE(res);
|
||||
res = if_alt_chain_stronger_hf4(200000, 7000);
|
||||
ASSERT_FALSE(res);
|
||||
res = if_alt_chain_stronger_hf4(200000, 7700);
|
||||
ASSERT_TRUE(res);
|
||||
res = if_alt_chain_stronger_hf4(200000, 7000);
|
||||
ASSERT_FALSE(res);
|
||||
res = if_alt_chain_stronger_hf4(200000, 7700);
|
||||
ASSERT_TRUE(res);
|
||||
res = if_alt_chain_stronger_hf4(100000, 10000);
|
||||
ASSERT_FALSE(res);
|
||||
res = if_alt_chain_stronger_hf4(200000, 14000);
|
||||
ASSERT_TRUE(res);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,35 @@
|
|||
|
||||
#include "misc_language.h"
|
||||
|
||||
namespace epee::misc_utils
|
||||
{
|
||||
// old impelementation that uses std::sort
|
||||
template<class type_vec_type>
|
||||
type_vec_type old_median(std::vector<type_vec_type> &v)
|
||||
{
|
||||
//CRITICAL_REGION_LOCAL(m_lock);
|
||||
if(v.empty())
|
||||
return boost::value_initialized<type_vec_type>();
|
||||
if(v.size() == 1)
|
||||
return v[0];
|
||||
|
||||
size_t n = (v.size()) / 2;
|
||||
std::sort(v.begin(), v.end());
|
||||
//nth_element(v.begin(), v.begin()+n-1, v.end());
|
||||
if(v.size()%2)
|
||||
{//1, 3, 5...
|
||||
return v[n];
|
||||
}else
|
||||
{//2, 4, 6...
|
||||
return (v[n-1] + v[n])/2;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace epee::misc_utils
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
bool test_median(const std::vector<uint64_t>& v_)
|
||||
{
|
||||
std::vector<uint64_t> v(v_);
|
||||
|
|
@ -21,8 +50,9 @@ bool test_median(const std::vector<uint64_t>& v_)
|
|||
}
|
||||
uint64_t m1 = epee::misc_utils::median(v);
|
||||
uint64_t m2 = mh.get_median();
|
||||
if (m1 != m2)
|
||||
return false;
|
||||
uint64_t m3 = epee::misc_utils::old_median(v);
|
||||
CHECK_AND_ASSERT_MES(m1 == m2, false, "m1 != m2");
|
||||
CHECK_AND_ASSERT_MES(m2 == m3, false, "m2 != m3");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -100,4 +130,4 @@ TEST(median_helper_test, median_helper_test)
|
|||
|
||||
mh.scan_items(cb, cb_finalizer);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ create_desktop_icon()
|
|||
echo GenericName=Zano | tee -a $target_file_name > /dev/null
|
||||
echo Comment=Privacy blockchain | tee -a $target_file_name > /dev/null
|
||||
echo Icon=${out_dir}/Zano.png | tee -a $target_file_name > /dev/null
|
||||
echo Exec=$APPIMAGE --deeplink-params=%u | tee -a $target_file_name > /dev/null
|
||||
echo Terminal=true | tee -a $target_file_name > /dev/null
|
||||
echo Exec=$APPIMAGE --deeplink-params=\\\"%u\\\" | tee -a $target_file_name > /dev/null
|
||||
echo Terminal=false | tee -a $target_file_name > /dev/null
|
||||
echo Type=Application | tee -a $target_file_name > /dev/null
|
||||
echo "Categories=Qt;Utility;" | tee -a $target_file_name > /dev/null
|
||||
echo "MimeType=x-scheme-handler/zano;" | tee -a $target_file_name > /dev/null
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ fi
|
|||
|
||||
# copy all necessary libs into the bundle in order to workaround El Capitan's SIP restrictions
|
||||
mkdir -p Zano.app/Contents/Frameworks/boost_libs
|
||||
cp -R "$ZANO_BOOST_LIBS_PATH/" Zano.app/Contents/Frameworks/boost_libs/
|
||||
cp -R $ZANO_BOOST_LIBS_PATH/*.dylib Zano.app/Contents/Frameworks/boost_libs/
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to cp workaround to MacOS"
|
||||
exit 1
|
||||
|
|
@ -84,8 +84,7 @@ source ../../../utils/macosx_fix_boost_libs_path.sh
|
|||
fix_boost_libs_in_binary @executable_path/../Frameworks/boost_libs Zano.app/Contents/MacOS/Zano
|
||||
fix_boost_libs_in_binary @executable_path/../Frameworks/boost_libs Zano.app/Contents/MacOS/simplewallet
|
||||
fix_boost_libs_in_binary @executable_path/../Frameworks/boost_libs Zano.app/Contents/MacOS/zanod
|
||||
fix_boost_libs_in_libs @executable_path/../Frameworks/boost_libs Zano.app/Contents/Frameworks/boost_libs
|
||||
|
||||
#fix_boost_libs_in_libs @executable_path/../Frameworks/boost_libs Zano.app/Contents/Frameworks/boost_libs
|
||||
|
||||
|
||||
"$ZANO_QT_PATH/clang_64/bin/macdeployqt" Zano.app
|
||||
|
|
@ -95,6 +94,8 @@ if [ $? -ne 0 ]; then
|
|||
fi
|
||||
|
||||
|
||||
rm -rf Zano.app/Contents/Frameworks/libboost*.dylib
|
||||
|
||||
|
||||
rsync -a ../../../src/gui/qt-daemon/layout/html Zano.app/Contents/MacOS --exclude less --exclude package.json --exclude gulpfile.js
|
||||
if [ $? -ne 0 ]; then
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ rmdir build /s /q
|
|||
mkdir build
|
||||
cd build
|
||||
|
||||
cmake %TESTNET_DEF% -D OPENSSL_ROOT_DIR="%OPENSSL_ROOT_DIR%" -D CMAKE_PREFIX_PATH="%QT_MSVC_PATH%" -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.1" -G "Visual Studio 16 2019" -A x64 -T host=x64 ..
|
||||
cmake %TESTNET_DEF% -D OPENSSL_ROOT_DIR="%OPENSSL_ROOT_DIR%" -D CMAKE_PREFIX_PATH="%QT_MSVC_PATH%" -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 ..
|
||||
IF %ERRORLEVEL% NEQ 0 (
|
||||
goto error
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ set -e
|
|||
|
||||
function rel_path() # $1 - path to a target dir/file, $2 - base dir
|
||||
{
|
||||
python -c "import os.path; print os.path.relpath('$1', os.path.dirname('$2'))"
|
||||
python3 -c "import os.path; print(os.path.relpath('$1', os.path.dirname('$2')))"
|
||||
}
|
||||
|
||||
function abs_path()
|
||||
{
|
||||
python -c "import os.path; print os.path.abspath('$1')"
|
||||
python3 -c "import os.path; print(os.path.abspath('$1'))"
|
||||
}
|
||||
|
||||
function fix_boost_libs_in_binary() # $1 - path to boost libs, $2 - binary to fix
|
||||
|
|
@ -17,23 +17,24 @@ function fix_boost_libs_in_binary() # $1 - path to boost libs, $2 - binary to fi
|
|||
echo "fix_boost_libs_in_binary is called with no or invalid parameters"
|
||||
return 1
|
||||
fi
|
||||
install_name_tool -change libboost_system.dylib $1/libboost_system.dylib $2
|
||||
install_name_tool -change libboost_filesystem.dylib $1/libboost_filesystem.dylib $2
|
||||
install_name_tool -change libboost_thread.dylib $1/libboost_thread.dylib $2
|
||||
install_name_tool -change libboost_date_time.dylib $1/libboost_date_time.dylib $2
|
||||
install_name_tool -change libboost_chrono.dylib $1/libboost_chrono.dylib $2
|
||||
install_name_tool -change libboost_regex.dylib $1/libboost_regex.dylib $2
|
||||
install_name_tool -change libboost_serialization.dylib $1/libboost_serialization.dylib $2
|
||||
install_name_tool -change libboost_atomic.dylib $1/libboost_atomic.dylib $2
|
||||
install_name_tool -change libboost_program_options.dylib $1/libboost_program_options.dylib $2
|
||||
install_name_tool -change libboost_locale.dylib $1/libboost_locale.dylib $2
|
||||
install_name_tool -change libboost_timer.dylib $1/libboost_timer.dylib $2
|
||||
install_name_tool -change libboost_chrono.dylib $1/libboost_chrono.dylib $2
|
||||
install_name_tool -change @rpath/libboost_system.dylib $1/libboost_system.dylib $2
|
||||
install_name_tool -change @rpath/libboost_filesystem.dylib $1/libboost_filesystem.dylib $2
|
||||
install_name_tool -change @rpath/libboost_thread.dylib $1/libboost_thread.dylib $2
|
||||
install_name_tool -change @rpath/libboost_date_time.dylib $1/libboost_date_time.dylib $2
|
||||
install_name_tool -change @rpath/libboost_chrono.dylib $1/libboost_chrono.dylib $2
|
||||
install_name_tool -change @rpath/libboost_regex.dylib $1/libboost_regex.dylib $2
|
||||
install_name_tool -change @rpath/libboost_serialization.dylib $1/libboost_serialization.dylib $2
|
||||
install_name_tool -change @rpath/libboost_atomic.dylib $1/libboost_atomic.dylib $2
|
||||
install_name_tool -change @rpath/libboost_program_options.dylib $1/libboost_program_options.dylib $2
|
||||
install_name_tool -change @rpath/libboost_locale.dylib $1/libboost_locale.dylib $2
|
||||
install_name_tool -change @rpath/libboost_timer.dylib $1/libboost_timer.dylib $2
|
||||
install_name_tool -change @rpath/libboost_chrono.dylib $1/libboost_chrono.dylib $2
|
||||
return 0
|
||||
}
|
||||
|
||||
function fix_boost_libs_in_libs() # $1 - path to boost libs, $2 - path to libs folder
|
||||
{
|
||||
return 0 # temporary disabled -- 2023-11-20, sowle
|
||||
install_name_tool -change libboost_system.dylib $1/libboost_system.dylib $2/libboost_filesystem.dylib
|
||||
install_name_tool -change libboost_system.dylib $1/libboost_system.dylib $2/libboost_thread.dylib
|
||||
install_name_tool -change libboost_system.dylib $1/libboost_system.dylib $2/libboost_chrono.dylib
|
||||
|
|
|
|||
20
utils/test_api_files/transfer.json
Normal file
20
utils/test_api_files/transfer.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 0,
|
||||
"method": "transfer",
|
||||
"params": {
|
||||
"destinations": [
|
||||
{
|
||||
"amount": 1000000000,
|
||||
"address": "ZxCkEgHf3ci8hgBfboZeCENaYrHBYZ1bLFi5cgWvn4WJLaxfgs4kqG6cJi9ai2zrXWSCpsvRXit14gKjeijx6YPC1zT8rneEf"
|
||||
}
|
||||
],
|
||||
"push_payer": true,
|
||||
"hide_receiver": false,
|
||||
"service_entries_permanent": false,
|
||||
"fee": 1000000000000,
|
||||
"mixin": 10,
|
||||
"comment": "",
|
||||
"service_entries": []
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue