Merge branch 'decoy_selection' into cryptoassets
This commit is contained in:
commit
67b7336a97
57 changed files with 6004 additions and 312 deletions
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -729,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;
|
||||
}
|
||||
|
||||
|
|
@ -745,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;
|
||||
}
|
||||
|
||||
|
|
@ -907,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;
|
||||
}
|
||||
|
||||
|
|
@ -916,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;
|
||||
}
|
||||
|
||||
|
|
@ -925,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
|
||||
//
|
||||
|
|
@ -1082,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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -2043,9 +2043,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
|
||||
|
|
@ -2062,6 +2071,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
|
||||
|
||||
|
|
@ -2657,6 +2681,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);
|
||||
|
|
@ -4093,6 +4326,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");
|
||||
|
||||
|
|
@ -4103,9 +4337,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;
|
||||
|
|
@ -4417,7 +4671,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++)
|
||||
|
|
@ -5584,9 +5838,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))
|
||||
|
|
@ -5611,18 +5868,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;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
@ -5734,6 +6011,7 @@ 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);
|
||||
|
|
@ -5745,6 +6023,18 @@ 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.
|
||||
|
|
@ -5765,6 +6055,8 @@ bool blockchain_storage::validate_pos_block(const block& b,
|
|||
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;
|
||||
|
|
@ -6351,11 +6643,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;
|
||||
|
||||
|
|
@ -6449,7 +6742,7 @@ 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"
|
||||
|
|
@ -6467,6 +6760,23 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
<< ")"
|
||||
<< "))");
|
||||
|
||||
{
|
||||
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;
|
||||
|
|
@ -7031,8 +7341,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);
|
||||
|
||||
|
|
@ -7279,7 +7588,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());
|
||||
|
||||
}
|
||||
|
|
@ -7293,8 +7602,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
|
||||
|
|
@ -7340,6 +7649,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;
|
||||
}
|
||||
|
|
@ -7656,6 +7979,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;
|
||||
|
|
@ -7667,6 +7991,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))
|
||||
|
|
@ -7699,6 +8026,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,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;
|
||||
|
|
@ -329,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;
|
||||
|
|
@ -589,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);
|
||||
|
|
@ -641,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;
|
||||
|
|
@ -655,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;
|
||||
|
|
@ -737,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);
|
||||
|
||||
|
|
@ -752,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;
|
||||
|
|
@ -807,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))
|
||||
{
|
||||
|
|
@ -828,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
|
||||
{
|
||||
|
|
@ -847,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();
|
||||
|
||||
|
|
@ -867,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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
@ -387,8 +386,10 @@ namespace currency
|
|||
std::vector<uint64_t> out_amounts;
|
||||
if (tx_version > TRANSACTION_VERSION_PRE_HF4)
|
||||
{
|
||||
// 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);
|
||||
// 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -424,7 +425,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
|
||||
}
|
||||
|
||||
|
|
@ -725,14 +727,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_)
|
||||
|
|
@ -3317,9 +3329,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 */)
|
||||
{
|
||||
|
|
@ -4425,8 +4443,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,
|
||||
|
|
@ -4459,6 +4475,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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -362,7 +362,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 +407,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 +421,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 +934,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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -384,6 +384,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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
{
|
||||
|
|
@ -5465,17 +5488,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;
|
||||
|
|
@ -5864,30 +5889,80 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vector<currency
|
|||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response daemon_resp = AUTO_VAL_INIT(daemon_resp);
|
||||
if (fake_outputs_count)
|
||||
{
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request req = AUTO_VAL_INIT(req);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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);
|
||||
|
||||
rdisttib.own_global_index = it->m_global_output_index;
|
||||
//check if we have Zarcanum era output of pre-Zarcanum
|
||||
if (it->is_zc())
|
||||
{
|
||||
//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(fake_outputs_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
//for prezarcanum era use flat distribution
|
||||
rdisttib.amount = it->m_amount;
|
||||
rdisttib.offsets.resize(fake_outputs_count, 0);
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
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;
|
||||
for(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& amount_outs : daemon_resp.outs)
|
||||
{
|
||||
if (amount_outs.outs.size() < req.decoys_count)
|
||||
if (amount_outs.outs.size() < fake_outputs_count)
|
||||
{
|
||||
scanty_outs.push_back(amount_outs);
|
||||
}
|
||||
|
|
@ -6481,7 +6556,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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -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,8 @@ bool wallets_manager::init_local_daemon()
|
|||
|
||||
//chain calls to rpc server
|
||||
m_prpc_chain_handler = &m_wallet_rpc_server;
|
||||
m_rpc_server.set_rpc_chain_handler(this);
|
||||
//disable this until we get full support of authentication with network
|
||||
//m_rpc_server.set_rpc_chain_handler(this);
|
||||
|
||||
|
||||
LOG_PRINT_L0("Starting core rpc server...");
|
||||
|
|
@ -1805,6 +1806,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
|
||||
|
|
|
|||
|
|
@ -448,6 +448,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 +473,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];
|
||||
|
|
@ -1193,8 +1203,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 +1495,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 +2351,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 +2490,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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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>);
|
||||
|
|
@ -1249,7 +1250,7 @@ int main(int argc, char* argv[])
|
|||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -3452,7 +3452,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 +3465,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 +3479,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 +3492,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
|
||||
|
|
|
|||
|
|
@ -1658,7 +1658,7 @@ TEST(crypto, scalar_get_bits)
|
|||
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(255ull, i + 65)), 0);
|
||||
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]);
|
||||
|
|
@ -1695,6 +1695,32 @@ TEST(crypto, scalar_get_bits)
|
|||
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)
|
||||
{
|
||||
|
|
@ -1762,6 +1788,116 @@ TEST(crypto, msm)
|
|||
}
|
||||
|
||||
|
||||
|
||||
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,7 +2,7 @@
|
|||
// 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>
|
||||
|
||||
uint64_t get_bits_v1(const scalar_t& s, uint8_t bit_index_first, uint8_t bits_count)
|
||||
{
|
||||
|
|
@ -20,27 +20,42 @@ uint64_t get_bits_v1(const scalar_t& s, uint8_t bit_index_first, uint8_t bits_co
|
|||
}
|
||||
|
||||
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::ge_precomp v)
|
||||
TEST(crypto, ge_precomp)
|
||||
{
|
||||
o << "{{";
|
||||
|
||||
for(size_t i = 0; i < 9; ++i)
|
||||
o << v.yplusx[i] << ", ";
|
||||
//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;
|
||||
|
||||
o << v.yplusx[9] << "},\n {";
|
||||
|
||||
for(size_t i = 0; i < 9; ++i)
|
||||
o << v.yminusx[i] << ", ";
|
||||
|
||||
o << v.yminusx[9] << "},\n {";
|
||||
|
||||
for(size_t i = 0; i < 9; ++i)
|
||||
o << v.xy2d[i] << ", ";
|
||||
|
||||
o << v.xy2d[9] << "}}\n";
|
||||
return o;
|
||||
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
|
||||
|
|
@ -315,7 +330,7 @@ TEST(perf, 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);
|
||||
|
|
@ -530,7 +545,7 @@ TEST(perf, 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);
|
||||
|
||||
|
|
@ -555,6 +570,87 @@ TEST(perf, 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);
|
||||
|
|
@ -738,5 +834,402 @@ TEST(perf, 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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue