1
0
Fork 0
forked from lthn/blockchain

1) zarcanum math moved to separate file; 2) fixed an error in rhs calculation; 3) 2^64 constant + test

This commit is contained in:
sowle 2022-09-13 22:08:46 +02:00
parent c2771a075e
commit af9c53794e
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
7 changed files with 73 additions and 9 deletions

View file

@ -13,6 +13,7 @@ namespace crypto
const point_g_t c_point_G;
const scalar_t c_scalar_1 = { 1 };
const scalar_t c_scalar_2p64 = { 0, 1, 0, 0 };
const scalar_t c_scalar_L = { 0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0x0, 0x1000000000000000 };
const scalar_t c_scalar_Lm1 = { 0x5812631a5cf5d3ec, 0x14def9dea2f79cd6, 0x0, 0x1000000000000000 };
const scalar_t c_scalar_P = { 0xffffffffffffffed, 0xffffffffffffffff, 0xffffffffffffffff, 0x7fffffffffffffff };

View file

@ -456,6 +456,7 @@ namespace crypto
//
extern const scalar_t c_scalar_1;
extern const scalar_t c_scalar_2p64;
extern const scalar_t c_scalar_L;
extern const scalar_t c_scalar_Lm1;
extern const scalar_t c_scalar_P;

33
src/crypto/zarcanum.cpp Normal file
View file

@ -0,0 +1,33 @@
// Copyright (c) 2022 Zano Project
// Copyright (c) 2022 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.
//
// Note: This file originates from tests/functional_tests/crypto_tests.cpp
#include "zarcanum.h"
namespace crypto
{
const scalar_t c_zarcanum_z_coeff_s = c_scalar_2p64;
const mp::uint256_t c_zarcanum_z_coeff_mp = c_zarcanum_z_coeff_s.as_boost_mp_type<mp::uint256_t>();
mp::uint256_t zarcanum_precalculate_l_div_z_D(const mp::uint128_t& pos_difficulty)
{
return c_scalar_L.as_boost_mp_type<mp::uint256_t>() / (c_zarcanum_z_coeff_mp * pos_difficulty); // == floor( l / (z * D) )
}
mp::uint256_t zarcanum_precalculate_z_l_div_z_D(const mp::uint128_t& pos_difficulty)
{
return c_zarcanum_z_coeff_mp * (c_scalar_L.as_boost_mp_type<mp::uint256_t>() / (c_zarcanum_z_coeff_mp * pos_difficulty)); // == z * floor( l / (z * D) )
}
bool zarcanum_check_main_pos_inequality(const hash& kernel_hash, const scalar_t& blinding_mask, const scalar_t& secret_q,
const scalar_t& last_pow_block_id_hashed, const mp::uint256_t& z_l_div_z_D, uint64_t stake_amount, mp::uint256_t& lhs, mp::uint256_t& rhs)
{
scalar_t lhs_s = scalar_t(kernel_hash) * (blinding_mask + secret_q + last_pow_block_id_hashed); // == h * (f + q + f') mod l
lhs = lhs_s.as_boost_mp_type<mp::uint256_t>();
rhs = z_l_div_z_D * stake_amount; // == floor( l / (z * D) ) * z * a
return lhs < rhs; // h * (f + q + f') mod l < floor( l / (z * D) ) * z * a
}
} // namespace crypto

25
src/crypto/zarcanum.h Normal file
View file

@ -0,0 +1,25 @@
// Copyright (c) 2022 Zano Project
// Copyright (c) 2022 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.
//
// Note: This file originates from tests/functional_tests/crypto_tests.cpp
#pragma once
#include "crypto-sugar.h"
#include <boost/multiprecision/cpp_int.hpp>
namespace crypto
{
namespace mp = boost::multiprecision;
extern const mp::uint256_t c_zarcanum_z_coeff_mp;
extern const scalar_t c_zarcanum_z_coeff_s;
mp::uint256_t zarcanum_precalculate_l_div_z_D(const mp::uint128_t& pos_difficulty);
mp::uint256_t zarcanum_precalculate_z_l_div_z_D(const mp::uint128_t& pos_difficulty);
bool zarcanum_check_main_pos_inequality(const hash& kernel_hash, const scalar_t& blinding_mask, const scalar_t& secret_q,
const scalar_t& last_pow_block_id_hashed, const mp::uint256_t& z_l_div_z_D_, uint64_t stake_amount, mp::uint256_t& lhs, mp::uint256_t& rhs);
} // namespace crypto

View file

@ -38,6 +38,7 @@ using namespace epee;
#include "storages/levin_abstract_invoke2.h"
#include "common/variant_helper.h"
#include "currency_core/crypto_config.h"
#include "crypto/zarcanum.h"
using namespace currency;
@ -3636,7 +3637,7 @@ bool wallet2::fill_mining_context(mining_context& ctx)
// Zarcanum (PoS with hidden amounts)
ctx.zarcanum = true;
ctx.last_pow_block_id_hashed = crypto::hash_helper_t::hs(CRYPTO_HDS_ZARCANUM_LAST_POW_HASH, ctx.sk.stake_modifier.last_pow_id);
ctx.l_div_z_D = crypto::c_scalar_L.as_boost_mp_type<boost::multiprecision::uint256_t>() / (ctx.basic_diff);
ctx.z_l_div_z_D = crypto::zarcanum_precalculate_z_l_div_z_D(ctx.basic_diff);
}
ctx.last_block_hash = pos_details_resp.last_block_hash;
@ -3718,12 +3719,13 @@ bool wallet2::do_pos_mining_iteration(mining_context& context, size_t transfer_i
if (context.zarcanum && td.is_zc())
{
PROFILE_FUNC("check_zarcanum");
crypto::scalar_t lhs_s = crypto::scalar_t(kernel_hash) * (*td.m_opt_blinding_mask + context.secret_q + context.last_pow_block_id_hashed); // == h * (f + q + f') mod l
boost::multiprecision::uint256_t lhs = lhs_s.as_boost_mp_type<boost::multiprecision::uint256_t>();
boost::multiprecision::uint256_t rhs = context.l_div_z_D * stake_amount; // == floor( l / (z * D) ) * a
if (lhs < rhs)
crypto::mp::uint256_t lhs, rhs;
{
PROFILE_FUNC("check_zarcanum");
found = crypto::zarcanum_check_main_pos_inequality(kernel_hash, *td.m_opt_blinding_mask, context.secret_q, context.last_pow_block_id_hashed, context.z_l_div_z_D, stake_amount, lhs, rhs);
++context.iterations_processed;
}
if (found)
{
found = true;
LOG_PRINT_GREEN("Found Zarcanum kernel: amount: " << currency::print_money_brief(stake_amount) << ", gindex: " << td.m_global_output_index << ENDL
@ -3736,7 +3738,6 @@ bool wallet2::do_pos_mining_iteration(mining_context& context, size_t transfer_i
, LOG_LEVEL_0);
}
++context.iterations_processed;
}
else
{

View file

@ -463,7 +463,7 @@ namespace tools
crypto::scalar_t last_pow_block_id_hashed; // Zarcanum notation: f'
crypto::scalar_t secret_q; // Zarcanum notation: q
boost::multiprecision::uint256_t l_div_z_D; // Zarcanum notation: floor( l / (z * D) ) (max possible value: 2^252 / (2^64 * 1) ~= 2^188, or 2^252 / (1 * 1) = 2^252)
boost::multiprecision::uint256_t z_l_div_z_D; // Zarcanum notation: z * floor( l / (z * D) ) (max possible value: 2^64 * 2^252 / (2^64 * 1) ~= 2^252, or 2^252 / (1 * 1) = 2^252)
currency::wide_difficulty_type basic_diff;
currency::stake_kernel sk;

View file

@ -863,6 +863,9 @@ TEST(crypto, scalar_basics)
mp::uint256_t mp_p_mod_l = c_scalar_P.as_boost_mp_type<mp::uint256_t>() % c_scalar_L.as_boost_mp_type<mp::uint256_t>();
ASSERT_EQ(p, scalar_t(mp_p_mod_l));
ASSERT_EQ(c_scalar_2p64 - c_scalar_1, scalar_t(UINT64_MAX));
ASSERT_EQ(c_scalar_2p64, scalar_t(UINT64_MAX) + c_scalar_1);
return true;
}