diff --git a/src/crypto/zarcanum.cpp b/src/crypto/zarcanum.cpp index 9aa4dc36..fc905029 100644 --- a/src/crypto/zarcanum.cpp +++ b/src/crypto/zarcanum.cpp @@ -4,19 +4,25 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. // // Note: This file originates from tests/functional_tests/crypto_tests.cpp +#include "epee/include/misc_log_ex.h" #include "zarcanum.h" +#include "crypto/range_proofs.h" +#include "../currency_core/crypto_config.h" // TODO: move it to the crypto + namespace crypto { - const scalar_t c_zarcanum_z_coeff_s = c_scalar_2p64; + const scalar_t c_zarcanum_z_coeff_s = { 0, 1, 0, 0 }; // c_scalar_2p64 const mp::uint256_t c_zarcanum_z_coeff_mp = c_zarcanum_z_coeff_s.as_boost_mp_type(); mp::uint256_t zarcanum_precalculate_l_div_z_D(const mp::uint128_t& pos_difficulty) { + //LOG_PRINT_GREEN_L0(ENDL << "floor( l / (z * D) ) = " << c_scalar_L.as_boost_mp_type() / (c_zarcanum_z_coeff_mp * pos_difficulty)); return c_scalar_L.as_boost_mp_type() / (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) { + //LOG_PRINT_GREEN_L0(ENDL << "z * floor( l / (z * D) ) = " << c_zarcanum_z_coeff_mp * (c_scalar_L.as_boost_mp_type() / (c_zarcanum_z_coeff_mp * pos_difficulty))); return c_zarcanum_z_coeff_mp * (c_scalar_L.as_boost_mp_type() / (c_zarcanum_z_coeff_mp * pos_difficulty)); // == z * floor( l / (z * D) ) } @@ -27,7 +33,127 @@ namespace crypto lhs = lhs_s.as_boost_mp_type(); rhs = static_cast(z_l_div_z_D) * stake_amount; // == floor( l / (z * D) ) * z * a + //LOG_PRINT_GREEN_L0(ENDL << + // "z_l_div_z_D = " << z_l_div_z_D << ENDL << + // "stake_amount = " << stake_amount << ENDL << + // "lhs = " << lhs << ENDL << + // "rhs = " << rhs); + return lhs < rhs; // h * (f + q + f') mod l < floor( l / (z * D) ) * z * a } + #define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("zarcanum_generate_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + bool zarcanum_generate_proof(const hash& kernel_hash, const public_key& commitment_1div8, const scalar_t& blinding_mask, const scalar_t& secret_q, + const scalar_t& last_pow_block_id_hashed, uint64_t stake_amount, zarcanum_proof& result, uint8_t* p_err) + { + const scalar_t a = stake_amount; + const scalar_t h = scalar_t(kernel_hash); + const scalar_t f_plus_q = blinding_mask + secret_q; + const scalar_t f_plus_q_plus_fp = f_plus_q + last_pow_block_id_hashed; + const scalar_t lhs = h * f_plus_q_plus_fp; // == h * (f + q + f') mod l + const mp::uint256_t d_mp = lhs.as_boost_mp_type() / (c_zarcanum_z_coeff_mp * stake_amount) + 1; + result.d = scalar_t(d_mp); + + const scalar_t dz = result.d * c_zarcanum_z_coeff_s; + + const scalar_t ba = dz * a - lhs; // b_a = dza - h(f + q + f') + + const scalar_t bf = dz * f_plus_q - h * a; // b_f = dz(f + q) - ha + + const scalar_t x0 = scalar_t::random(), x1 = scalar_t::random(), x2 = scalar_t::random(); + + const scalar_t bx = x2 - h * x1 + dz * x0; // b_x = x'' - hx' + dzx + + point_t C = x0 * c_point_X + a * c_point_H + f_plus_q * c_point_G; + point_t C_prime = x1 * c_point_X + f_plus_q * c_point_H + a * c_point_G; + point_t E = bx * c_point_X + ba * c_point_H + bf * c_point_G; + + result.C = C.to_public_key(); + result.C_prime = C_prime.to_public_key(); + result.E = E.to_public_key(); + + // three proofs with a shared Fiat-Shamir challenge c + // 1) linear composition proof for the fact, that C + C' = lin(X, H + G) = (x + x') X + (a + f + q) (H + G) + // 2) linear composition proof for the fact, that C - C' = lin(X, H - G) = (x - x') X + (a - f - q) (H - G) + // 3) Schnorr proof for the fact, that hC' - dzC + E + f'hH = lin(X) = x'' X + + point_t F = h * C_prime - dz * C + E + last_pow_block_id_hashed * h * c_point_H; + + scalar_t r0 = scalar_t::random(); + scalar_t r1 = scalar_t::random(); + scalar_t r2 = scalar_t::random(); + scalar_t r3 = scalar_t::random(); + scalar_t r4 = scalar_t::random(); + + point_t R_01 = r0 * c_point_X + r1 * c_point_H_plus_G; + point_t R_23 = r2 * c_point_X + r3 * c_point_H_minus_G; + point_t R_4 = r4 * c_point_G; + + hash_helper_t::hs_t hash_calc(3); + hash_calc.add_32_chars(CRYPTO_HDS_ZARCANUM_PROOF_HASH); + hash_calc.add_point(R_01); + hash_calc.add_point(R_23); + hash_calc.add_point(R_4); + hash_calc.add_point(C + C_prime); + hash_calc.add_point(C - C_prime); + hash_calc.add_point(F); + result.c = hash_calc.calc_hash(); + + result.y0 = r0 + result.c * (x0 + x1); // y_0 = r_0 + c (x + x') + result.y1 = r1 + result.c * (a + f_plus_q); // y_1 = r_1 + c (a + f + q) + result.y2 = r2 + result.c * (x0 - x1); // y_2 = r_2 + c (x - x') + result.y3 = r3 + result.c * (a - f_plus_q); // y_3 = r_3 + c (a - f - q) + result.y4 = r4 + result.c * x2; // y_4 = r_4 + c x'' + + // range proof for E + const scalar_vec_t values = { a }; // H component + const scalar_vec_t masks = { bf }; // G component + const scalar_vec_t masks2 = { bx }; // X component + const std::vector commitments_1div8 = { &commitment_1div8 }; + + if (!bppe_gen>(values, masks, masks2, commitments_1div8, result.E_range_proof, p_err)) + { + return false; + } + + // = four-layers ring signature data outline = + // (j in [0, ring_size-1]) + // layer 0 ring + // se.outputs[j].stealth_address; + // layer 0 secret (with respect to G) + // in_contexts[i].in_ephemeral.sec; + // layer 0 linkability + // in.k_image; + // + // layer 1 ring + // crypto::point_t(se.outputs[j].amount_commitment) - pseudo_out_amount_commitment; + // layer 1 secret (with respect to G) + // se.real_out_amount_blinding_mask - blinding_mask; + // + // additional layers for Zarcanum: + // + // layer 2 ring + // C - A[j] - Q[j] + // layer 2 secret (with respect to X) + // x0 + // + // layer 3 ring + // Q[j] + // layer 3 secret (with respect to G) + // secret_q + + return true; + } + + + bool zarcanum_verify_proof(const hash& kernel_hash, const public_key& commitment_1div8, const scalar_t& last_pow_block_id_hashed, const zarcanum_proof& proof, uint8_t* p_err /* = nullptr */) + { + return false; + } + + + } // namespace crypto diff --git a/src/crypto/zarcanum.h b/src/crypto/zarcanum.h index 6f2d83d4..528cdfd9 100644 --- a/src/crypto/zarcanum.h +++ b/src/crypto/zarcanum.h @@ -6,6 +6,8 @@ // Note: This file originates from tests/functional_tests/crypto_tests.cpp #pragma once #include "crypto-sugar.h" +#include "crypto/range_proof_bppe.h" +#include "crypto/clsag.h" #include namespace crypto @@ -22,4 +24,31 @@ namespace crypto 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::uint512_t& rhs); + struct zarcanum_proof + { + scalar_t d = 0; + public_key C; + public_key C_prime; + public_key E; + + scalar_t c; // shared Fiat-Shamir challenge for the following three proofs + scalar_t y0; // 1st linear composition proof + scalar_t y1; // ( C + C' = lin(X, H + G) ) + scalar_t y2; // 2nd linear composition proof + scalar_t y3; // ( C - C' = lin(X, H - G) ) + scalar_t y4; // Schnorr proof (F = lin(X)) + + bppe_signature E_range_proof; + CLSAG_GGXG_signature ring_sig; + }; + + bool zarcanum_generate_proof(const hash& kernel_hash, const public_key& stake_commitment_1div8, const scalar_t& last_pow_block_id_hashed, + const scalar_t& blinding_mask, const scalar_t& secret_q, uint64_t stake_amount, + uint64_t secret_index, + zarcanum_proof& result, uint8_t* p_err = nullptr); + + + + bool zarcanum_verify_proof(const hash& kernel_hash, const public_key& commitment_1div8, const scalar_t& last_pow_block_id_hashed, const zarcanum_proof& proof, uint8_t* p_err = nullptr); + } // namespace crypto diff --git a/src/currency_core/crypto_config.h b/src/currency_core/crypto_config.h index 06eaa3e8..0ca586cf 100644 --- a/src/currency_core/crypto_config.h +++ b/src/currency_core/crypto_config.h @@ -22,3 +22,4 @@ #define CRYPTO_HDS_ZARCANUM_LAST_POW_HASH "ZANO_HDS_ZARCANUM_LAST_POW_HASH" #define CRYPTO_HDS_ZARCANUM_SECRET_Q "ZANO_HDS_ZARCANUM_SECRET_Q_____" +#define CRYPTO_HDS_ZARCANUM_PROOF_HASH "ZANO_HDS_ZARCANUM_PROOF_HASH___" diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h index 6148830b..b25d4900 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -38,6 +38,7 @@ #include "crypto/crypto.h" #include "crypto/hash.h" #include "crypto/range_proofs.h" +#include "crypto/zarcanum.h" #include "misc_language.h" #include "block_flags.h" #include "etc_custom_serialization.h" @@ -482,6 +483,22 @@ namespace currency END_BOOST_SERIALIZATION() }; + + struct zarcanum_sig : public crypto::zarcanum_proof + { + BEGIN_SERIALIZE_OBJECT() + FIELD(d) + FIELD(C) + // TODO + END_SERIALIZE() + + BEGIN_BOOST_SERIALIZATION() + BOOST_SERIALIZE(d) + BOOST_SERIALIZE(C) + // TODO + END_BOOST_SERIALIZATION() + }; + //#pragma pack(pop) typedef boost::variant txin_v; @@ -803,8 +820,7 @@ namespace currency END_BOOST_SERIALIZATION() }; - - typedef boost::variant signature_v; + typedef boost::variant signature_v; @@ -1077,10 +1093,11 @@ SET_VARIANT_TAGS(crypto::bppe_signature_serialized, 41, "bppe_signature_serializ SET_VARIANT_TAGS(currency::NLSAG_sig, 42, "NLSAG_sig"); SET_VARIANT_TAGS(currency::ZC_sig, 43, "ZC_sig"); SET_VARIANT_TAGS(currency::void_sig, 44, "void_sig"); -SET_VARIANT_TAGS(currency::zc_outs_range_proof, 45, "zc_outs_range_proof"); -SET_VARIANT_TAGS(currency::zc_balance_proof, 46, "zc_balance_proof"); +SET_VARIANT_TAGS(currency::zarcanum_sig, 45, "zarcanum_sig"); +SET_VARIANT_TAGS(currency::zc_outs_range_proof, 46, "zc_outs_range_proof"); +SET_VARIANT_TAGS(currency::zc_balance_proof, 47, "zc_balance_proof"); -SET_VARIANT_TAGS(currency::open_asset_id, 47, "asset_id"); +SET_VARIANT_TAGS(currency::open_asset_id, 48, "asset_id"); diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index db667ec0..b9ff5de5 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -3901,7 +3901,12 @@ namespace currency //@#@ TODO return false; } - + //-------------------------------------------------------------------------------- + bool operator ==(const currency::zarcanum_sig& a, const currency::zarcanum_sig& b) + { + //@#@ TODO + return false; + } //-------------------------------------------------------------------------------- bool verify_multiple_zc_outs_range_proofs(const std::vector& range_proofs) { diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index 29966d44..9849d678 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -59,6 +59,7 @@ namespace currency bool operator ==(const currency::NLSAG_sig& a, const currency::NLSAG_sig& b); bool operator ==(const currency::void_sig& a, const currency::void_sig& b); bool operator ==(const currency::ZC_sig& a, const currency::ZC_sig& b); + bool operator ==(const currency::zarcanum_sig& a, const currency::zarcanum_sig& b); typedef boost::multiprecision::uint128_t uint128_tl;