From b931420266d3274c3ad916198a5a59d1ddffae61 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 5 Oct 2022 13:56:17 +0200 Subject: [PATCH 01/16] warning fix --- src/currency_core/currency_format_utils_abstract.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/currency_core/currency_format_utils_abstract.h b/src/currency_core/currency_format_utils_abstract.h index da707683..ccbbf7c8 100644 --- a/src/currency_core/currency_format_utils_abstract.h +++ b/src/currency_core/currency_format_utils_abstract.h @@ -169,7 +169,7 @@ namespace currency } //--------------------------------------------------------------- inline - const bool get_key_image_from_txin_v(const txin_v& in_v, crypto::key_image& result) noexcept + bool get_key_image_from_txin_v(const txin_v& in_v, crypto::key_image& result) noexcept { try { From 8c71ac83b779ea174ba8c60110f96f9dae71d46e Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 5 Oct 2022 14:02:32 +0200 Subject: [PATCH 02/16] zarcanum: main inequality type fixed --- src/crypto/zarcanum.cpp | 4 ++-- src/crypto/zarcanum.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/crypto/zarcanum.cpp b/src/crypto/zarcanum.cpp index f000139f..9aa4dc36 100644 --- a/src/crypto/zarcanum.cpp +++ b/src/crypto/zarcanum.cpp @@ -21,11 +21,11 @@ namespace crypto } 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) + 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) { 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(); - rhs = z_l_div_z_D * stake_amount; // == floor( l / (z * D) ) * z * a + rhs = static_cast(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 } diff --git a/src/crypto/zarcanum.h b/src/crypto/zarcanum.h index daaa1b4e..6f2d83d4 100644 --- a/src/crypto/zarcanum.h +++ b/src/crypto/zarcanum.h @@ -19,7 +19,7 @@ namespace crypto 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); + 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); } // namespace crypto From ea1dbabb9df6ab38a91384d26d4c6b04d5e17746 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 5 Oct 2022 14:54:35 +0200 Subject: [PATCH 03/16] zarcanum: main inequality type fixed (2) --- src/wallet/wallet2.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 8cdb034b..f3e51e5b 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3753,7 +3753,8 @@ bool wallet2::do_pos_mining_iteration(mining_context& context, size_t transfer_i if (context.zarcanum && td.is_zc()) { - crypto::mp::uint256_t lhs, rhs; + crypto::mp::uint256_t lhs; + crypto::mp::uint512_t 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); @@ -3765,7 +3766,7 @@ bool wallet2::do_pos_mining_iteration(mining_context& context, size_t transfer_i LOG_PRINT_GREEN("Found Zarcanum kernel: amount: " << currency::print_money_brief(stake_amount) << ", gindex: " << td.m_global_output_index << ENDL << "difficulty: " << context.basic_diff << ENDL << "kernel info: " << ENDL - << print_stake_kernel_info(context.sk) << ENDL + << print_stake_kernel_info(context.sk) << "kernel_hash: " << kernel_hash << ENDL << "lhs: " << lhs << ENDL << "rhs: " << rhs @@ -3787,7 +3788,7 @@ bool wallet2::do_pos_mining_iteration(mining_context& context, size_t transfer_i LOG_PRINT_GREEN("Found kernel: amount: " << currency::print_money_brief(stake_amount)<< ", gindex: " << td.m_global_output_index << ENDL << "difficulty: " << context.basic_diff << ", final_diff: " << final_diff << ENDL << "kernel info: " << ENDL - << print_stake_kernel_info(context.sk) << ENDL + << print_stake_kernel_info(context.sk) << "kernel_hash(proof): " << kernel_hash, LOG_LEVEL_0); } From 452047cb88dbc6cc7eea26dc999b0cc51836612b Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 5 Oct 2022 20:49:13 +0200 Subject: [PATCH 04/16] KV_ENABLE_POD_SERIALIZATION_AS_HEX fixed --- .../serialization/keyvalue_enable_POD_serialize_as_string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/epee/include/serialization/keyvalue_enable_POD_serialize_as_string.h b/contrib/epee/include/serialization/keyvalue_enable_POD_serialize_as_string.h index 0dbc2d76..9ae9b7f4 100644 --- a/contrib/epee/include/serialization/keyvalue_enable_POD_serialize_as_string.h +++ b/contrib/epee/include/serialization/keyvalue_enable_POD_serialize_as_string.h @@ -47,7 +47,7 @@ namespace epee \ bool r = kv_unserialize(s, stg, hparent_section, pname); \ if (r) \ { \ - d = epee::transform_str_to_t_pod(s); \ + d = epee::transform_str_to_t_pod(s); \ } \ return r; \ } \ From 185ccae95fd52401386fc90f6c683220bd4afe17 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 5 Oct 2022 21:09:27 +0200 Subject: [PATCH 05/16] rpc: removed old deprecated mining API (get_addenum, getjob, submitshare, etc.) --- src/rpc/core_rpc_server.cpp | 151 +---------------------- src/rpc/core_rpc_server.h | 21 ---- src/rpc/core_rpc_server_commands_defs.h | 20 ---- src/rpc/mining_protocol_defs.h | 153 ------------------------ 4 files changed, 6 insertions(+), 339 deletions(-) delete mode 100644 src/rpc/mining_protocol_defs.h diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index a96db023..e4d50928 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2022 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 @@ -35,8 +35,11 @@ namespace currency } //------------------------------------------------------------------------------------------------------------------------------ core_rpc_server::core_rpc_server(core& cr, nodetool::node_server >& p2p, - bc_services::bc_offers_service& of - ) :m_core(cr), m_p2p(p2p), m_of(of), m_session_counter(0), m_ignore_status(false) + bc_services::bc_offers_service& of) + : m_core(cr) + , m_p2p(p2p) + , m_of(of) + , m_ignore_status(false) {} //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::handle_command_line(const boost::program_options::variables_map& vm) @@ -1156,109 +1159,6 @@ namespace currency return true; } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::get_current_hi(mining::height_info& hi) - { - block prev_block = AUTO_VAL_INIT(prev_block); - m_core.get_blockchain_storage().get_top_block(prev_block); - hi.block_id = string_tools::pod_to_hex(currency::get_block_hash(prev_block)); - hi.height = get_block_height(prev_block); - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - void core_rpc_server::set_session_blob(const std::string& session_id, const currency::block& blob) - { - CRITICAL_REGION_LOCAL(m_session_jobs_lock); - m_session_jobs[session_id] = blob; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::get_session_blob(const std::string& session_id, currency::block& blob) - { - CRITICAL_REGION_LOCAL(m_session_jobs_lock); - auto it = m_session_jobs.find(session_id); - if(it == m_session_jobs.end()) - return false; - - blob = it->second; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::get_job(const std::string& job_id, mining::job_details& job, epee::json_rpc::error& err, connection_context& cntx) - { - COMMAND_RPC_GETBLOCKTEMPLATE::request bt_req = AUTO_VAL_INIT(bt_req); - COMMAND_RPC_GETBLOCKTEMPLATE::response bt_res = AUTO_VAL_INIT(bt_res); - - // !!!!!!!! SET YOUR WALLET ADDRESS HERE !!!!!!!! - bt_req.wallet_address = "1HNJjUsofq5LYLoXem119dd491yFAb5g4bCHkecV4sPqigmuxw57Ci9am71fEN4CRmA9jgnvo5PDNfaq8QnprWmS5uLqnbq"; - - if(!on_getblocktemplate(bt_req, bt_res, err, cntx)) - return false; - - //patch block blob if you need(bt_res.blocktemplate_blob), and than load block from blob template - //important: you can't change block size, since it could touch reward and block became invalid - - block b = AUTO_VAL_INIT(b); - std::string bin_buff; - bool r = string_tools::parse_hexstr_to_binbuff(bt_res.blocktemplate_blob, bin_buff); - CHECK_AND_ASSERT_MES(r, false, "internal error, failed to parse hex block"); - r = currency::parse_and_validate_block_from_blob(bin_buff, b); - CHECK_AND_ASSERT_MES(r, false, "internal error, failed to parse block"); - - set_session_blob(job_id, b); - job.blob = string_tools::buff_to_hex_nodelimer(currency::get_block_hashing_blob(b)); - //TODO: set up share difficulty here! - job.difficulty = bt_res.difficulty; //difficulty leaved as string field since it will be refactored into 128 bit format - job.job_id = "SOME_JOB_ID"; - get_current_hi(job.prev_hi); - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_login(const mining::COMMAND_RPC_LOGIN::request& req, mining::COMMAND_RPC_LOGIN::response& res, connection_context& cntx) - { - if(!check_core_ready()) - { - res.status = API_RETURN_CODE_BUSY; - return true; - } - - //TODO: add login information here - - - res.id = std::to_string(m_session_counter++); //session id - - if(req.hi.height) - { - epee::json_rpc::error err = AUTO_VAL_INIT(err); - if(!get_job(res.id, res.job, err, cntx)) - { - res.status = err.message; - return true; - } - } - - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_getjob(const mining::COMMAND_RPC_GETJOB::request& req, mining::COMMAND_RPC_GETJOB::response& res, connection_context& cntx) - { - if(!check_core_ready()) - { - res.status = API_RETURN_CODE_BUSY; - return true; - } - - - - /*epee::json_rpc::error err = AUTO_VAL_INIT(err); - if(!get_job(req.id, res.jd, err, cntx)) - { - res.status = err.message; - return true; - }*/ - - return true; - } //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_alias_reward(const COMMAND_RPC_GET_ALIAS_REWARD::request& req, COMMAND_RPC_GET_ALIAS_REWARD::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) { @@ -1324,45 +1224,6 @@ namespace currency return true; } //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_submit(const mining::COMMAND_RPC_SUBMITSHARE::request& req, mining::COMMAND_RPC_SUBMITSHARE::response& res, connection_context& cntx) - { - if(!check_core_ready()) - { - res.status = API_RETURN_CODE_BUSY; - return true; - } - block b = AUTO_VAL_INIT(b); - if(!get_session_blob(req.id, b)) - { - res.status = "Wrong session id"; - return true; - } - - b.nonce = req.nonce; - - if(!m_core.handle_block_found(b)) - { - res.status = "Block not accepted"; - LOG_ERROR("Submited block not accepted"); - return true; - } - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_addendums(const COMMAND_RPC_GET_ADDENDUMS::request& req, COMMAND_RPC_GET_ADDENDUMS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - if (!check_core_ready()) - { - res.status = API_RETURN_CODE_BUSY; - return true; - } - - - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_reset_transaction_pool(const COMMAND_RPC_RESET_TX_POOL::request& req, COMMAND_RPC_RESET_TX_POOL::response& res, connection_context& cntx) { m_core.get_tx_pool().purge_transactions(); diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 4c2eb123..d27ceada 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -14,7 +14,6 @@ #include "currency_core/currency_core.h" #include "p2p/net_node.h" #include "currency_protocol/currency_protocol_handler.h" -#include "mining_protocol_defs.h" #include "currency_core/bc_offers_service.h" @@ -72,7 +71,6 @@ namespace currency bool on_get_aliases(const COMMAND_RPC_GET_ALIASES::request& req, COMMAND_RPC_GET_ALIASES::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); bool on_aliases_by_address(const COMMAND_RPC_GET_ALIASES_BY_ADDRESS::request& req, COMMAND_RPC_GET_ALIASES_BY_ADDRESS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); bool on_get_alias_reward(const COMMAND_RPC_GET_ALIAS_REWARD::request& req, COMMAND_RPC_GET_ALIAS_REWARD::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_get_addendums(const COMMAND_RPC_GET_ADDENDUMS::request& req, COMMAND_RPC_GET_ADDENDUMS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); bool on_reset_transaction_pool(const COMMAND_RPC_RESET_TX_POOL::request& req, COMMAND_RPC_RESET_TX_POOL::response& res, connection_context& cntx); bool on_get_pos_mining_details(const COMMAND_RPC_GET_POS_MINING_DETAILS::request& req, COMMAND_RPC_GET_POS_MINING_DETAILS::response& res, connection_context& cntx); bool on_get_current_core_tx_expiration_median(const COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::request& req, COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::response& res, connection_context& cntx); @@ -93,15 +91,6 @@ namespace currency - //mining rpc - bool on_login(const mining::COMMAND_RPC_LOGIN::request& req, mining::COMMAND_RPC_LOGIN::response& res, connection_context& cntx); - bool on_getjob(const mining::COMMAND_RPC_GETJOB::request& req, mining::COMMAND_RPC_GETJOB::response& res, connection_context& cntx); - bool on_submit(const mining::COMMAND_RPC_SUBMITSHARE::request& req, mining::COMMAND_RPC_SUBMITSHARE::response& res, connection_context& cntx); - - - - - CHAIN_HTTP_TO_MAP2(connection_context); //forward http requests to uri map BEGIN_URI_MAP2() @@ -157,10 +146,6 @@ namespace currency MAP_JON_RPC ("get_current_core_tx_expiration_median", on_get_current_core_tx_expiration_median, COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN) // MAP_JON_RPC_WE("marketplace_global_get_offers_ex", on_get_offers_ex, COMMAND_RPC_GET_OFFERS_EX) - //remote miner rpc - MAP_JON_RPC_N(on_login, mining::COMMAND_RPC_LOGIN) - MAP_JON_RPC_N(on_getjob, mining::COMMAND_RPC_GETJOB) - MAP_JON_RPC_N(on_submit, mining::COMMAND_RPC_SUBMITSHARE) END_JSON_RPC_MAP() END_URI_MAP2() @@ -169,8 +154,6 @@ namespace currency //----------------------- bool handle_command_line(const boost::program_options::variables_map& vm); bool check_core_ready_(const std::string& calling_method); - bool get_job(const std::string& job_id, mining::job_details& job, epee::json_rpc::error& err, connection_context& cntx); - bool get_current_hi(mining::height_info& hi); //utils uint64_t get_block_reward(const block& blk); @@ -184,10 +167,6 @@ namespace currency std::string m_port; std::string m_bind_ip; bool m_ignore_status; - //mining stuff - epee::critical_section m_session_jobs_lock; - std::map m_session_jobs; //session id -> blob - std::atomic m_session_counter; }; } diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 12a0911f..6f553e1e 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -11,7 +11,6 @@ #include "currency_core/difficulty.h" #include "crypto/hash.h" #include "p2p/p2p_protocol_defs.h" -#include "rpc/mining_protocol_defs.h" #include "storages/portable_storage_base.h" #include "currency_core/offers_service_basics.h" #include "currency_core/basic_api_response_codes.h" @@ -1084,25 +1083,6 @@ namespace currency }; - struct COMMAND_RPC_GET_ADDENDUMS - { - - typedef mining::height_info request; - - struct response - { - std::string status; - std::list addms; - - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(addms) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_RESET_TX_POOL { diff --git a/src/rpc/mining_protocol_defs.h b/src/rpc/mining_protocol_defs.h deleted file mode 100644 index 4a2c0f23..00000000 --- a/src/rpc/mining_protocol_defs.h +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) 2014-2018 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 -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include "currency_protocol/currency_protocol_defs.h" -#include "currency_core/currency_basic.h" -#include "crypto/hash.h" -#include "net/rpc_method_name.h" - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Seems to be obsolete. Consider removing due to stratum support. -// -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -namespace mining -{ - struct height_info - { - uint64_t height; - std::string block_id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(height) - KV_SERIALIZE(block_id) - END_KV_SERIALIZE_MAP() - }; - - - struct addendum - { - height_info hi; - std::string prev_id; - std::string addm; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(hi) - KV_SERIALIZE(prev_id) - KV_SERIALIZE(addm) - END_KV_SERIALIZE_MAP() - }; - - struct job_details - { - std::string blob; - std::string difficulty; - std::string job_id; - height_info prev_hi; - std::list addms; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(blob) - KV_SERIALIZE(difficulty) - KV_SERIALIZE(job_id) - KV_SERIALIZE(prev_hi) - KV_SERIALIZE(addms) - END_KV_SERIALIZE_MAP() - }; - - struct COMMAND_RPC_LOGIN - { - RPC_METHOD_NAME("login"); - - struct request - { - std::string login; - std::string pass; - std::string agent; - height_info hi; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(login) - KV_SERIALIZE(pass) - KV_SERIALIZE(agent) - KV_SERIALIZE(hi) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - std::string id; - job_details job; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(id) - KV_SERIALIZE(job) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_GETJOB - { - RPC_METHOD_NAME("getjob"); - - struct request - { - std::string id; - height_info hi; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(id) - KV_SERIALIZE(hi) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - job_details jd; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_CHAIN_MAP(jd) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_SUBMITSHARE - { - RPC_METHOD_NAME("submit"); - - struct request - { - std::string id; - uint64_t nonce; - std::string job_id; - std::string result; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(id) - KV_SERIALIZE(nonce) - KV_SERIALIZE(job_id) - KV_SERIALIZE(result) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - -} - From 5e0ce8cfb4dea17ee7e6c06351106117ef1b9e3d Mon Sep 17 00:00:00 2001 From: sowle Date: Mon, 10 Oct 2022 23:47:49 +0200 Subject: [PATCH 06/16] crypto: c_point_H_plus_G and c_point_H_minus_G constants added + unittest --- src/crypto/crypto-sugar.cpp | 3 +++ src/crypto/crypto-sugar.h | 2 ++ tests/functional_tests/crypto_tests.cpp | 8 ++++++++ 3 files changed, 13 insertions(+) diff --git a/src/crypto/crypto-sugar.cpp b/src/crypto/crypto-sugar.cpp index 36ccfeae..1823833a 100644 --- a/src/crypto/crypto-sugar.cpp +++ b/src/crypto/crypto-sugar.cpp @@ -28,6 +28,9 @@ namespace crypto const point_t c_point_0 = point_t(point_t::tag_zero()); + const point_t c_point_H_plus_G = c_point_H + c_point_G; // checked in crypto_constants + const point_t c_point_H_minus_G = c_point_H - c_point_G; // checked in crypto_constants + static_assert(sizeof(scalar_t::m_sk) == sizeof(scalar_t::m_u64) && sizeof(scalar_t::m_u64) == sizeof(scalar_t::m_s), "size missmatch"); } // namespace crypto diff --git a/src/crypto/crypto-sugar.h b/src/crypto/crypto-sugar.h index b1ff763e..1f9733dd 100644 --- a/src/crypto/crypto-sugar.h +++ b/src/crypto/crypto-sugar.h @@ -917,6 +917,8 @@ namespace crypto extern const point_t c_point_H2; extern const point_t c_point_X; extern const point_t c_point_0; + extern const point_t c_point_H_plus_G; + extern const point_t c_point_H_minus_G; // // hash functions' helper diff --git a/tests/functional_tests/crypto_tests.cpp b/tests/functional_tests/crypto_tests.cpp index 0b7c5a71..a893b27b 100644 --- a/tests/functional_tests/crypto_tests.cpp +++ b/tests/functional_tests/crypto_tests.cpp @@ -1118,6 +1118,14 @@ TEST(crypto, scalar_arithmetic_assignment) return true; } +TEST(crypto, constants) +{ + ASSERT_EQ(c_point_H_plus_G, c_point_H + c_point_G); + ASSERT_EQ(c_point_H_minus_G, c_point_H - c_point_G); + + return true; +} + TEST(crypto, point_basics) { scalar_t s = 4; From a0bdc0863363b5920be1ce0dc0b19b4216b5339b Mon Sep 17 00:00:00 2001 From: sowle Date: Mon, 10 Oct 2022 23:59:42 +0200 Subject: [PATCH 07/16] blinding mask calculation fix (cherry pick from multiassets) --- src/currency_core/currency_format_utils.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index f25f5d55..cb0abf18 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -1575,7 +1575,7 @@ namespace currency }; //-------------------------------------------------------------------------------- bool generate_ZC_sig(const crypto::hash& tx_hash_for_signature, size_t input_index, const tx_source_entry& se, const input_generation_context_data& in_context, - const account_keys& sender_account_keys, const crypto::scalar_t& blinding_masks_sum, const uint64_t tx_flags, crypto::scalar_t& local_blinding_masks_sum, transaction& tx) + const account_keys& sender_account_keys, const crypto::scalar_t& blinding_masks_sum, const uint64_t tx_flags, crypto::scalar_t& local_blinding_masks_sum, transaction& tx, bool last_output) { bool watch_only_mode = sender_account_keys.spend_secret_key == null_skey; CHECK_AND_ASSERT_MES(se.is_zarcanum(), false, "sources contains a non-zarcanum input"); @@ -1597,7 +1597,7 @@ namespace currency #endif crypto::scalar_t blinding_mask = 0; - if ((tx_flags & TX_FLAG_SIGNATURE_MODE_SEPARATE) == 0 || se.separately_signed_tx_complete) + if ((last_output && (tx_flags & TX_FLAG_SIGNATURE_MODE_SEPARATE) == 0) || se.separately_signed_tx_complete) { // either normal tx or the last signature of consolidated tx -- in both cases we need to calculate non-random blinding mask for pseudo output commitment blinding_mask = blinding_masks_sum + local_blinding_masks_sum; @@ -2034,7 +2034,8 @@ namespace currency { // ZC // blinding_masks_sum is supposed to be sum(mask of all tx output) - sum(masks of all pseudo out commitments) - r = generate_ZC_sig(tx_hash_for_signature, i + input_starter_index, source_entry, in_contexts[i], sender_account_keys, blinding_masks_sum, flags, local_blinding_masks_sum, tx); + r = generate_ZC_sig(tx_hash_for_signature, i + input_starter_index, source_entry, in_contexts[i], sender_account_keys, blinding_masks_sum, flags, + local_blinding_masks_sum, tx, i + 1 == sources.size()); CHECK_AND_ASSERT_MES(r, false, "generate_ZC_sigs failed"); } else From ab268af7b8d9300fd11a1fdb45c1e13768c97fbe Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 12 Oct 2022 17:50:02 +0200 Subject: [PATCH 08/16] get_random_outs_for_amounts adaptation, get_mix_attr_from_tx_out_v implemented --- src/currency_core/blockchain_storage.cpp | 89 +++++++++---------- src/currency_core/blockchain_storage.h | 2 +- src/currency_core/currency_format_utils.cpp | 4 +- .../currency_format_utils_abstract.h | 29 ++++++ 4 files changed, 75 insertions(+), 49 deletions(-) diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 18095d6f..3a65ae65 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -2475,15 +2475,21 @@ size_t blockchain_storage::get_alternative_blocks_count() const return m_alternative_chains.size(); } //------------------------------------------------------------------ -bool blockchain_storage::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) const +bool blockchain_storage::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, uint64_t amount, size_t g_index, uint64_t mix_count, + bool use_only_forced_to_mix, uint64_t height_upper_limit) const { CRITICAL_REGION_LOCAL(m_read_lock); - auto out_ptr = m_db_outputs.get_subitem(amount, i); + auto out_ptr = m_db_outputs.get_subitem(amount, g_index); auto tx_ptr = m_db_transactions.find(out_ptr->tx_id); CHECK_AND_ASSERT_MES(tx_ptr, false, "internal error: transaction with id " << out_ptr->tx_id << ENDL << - ", used in mounts global index for amount=" << amount << ": i=" << i << "not found in transactions index"); + ", used in mounts global index for amount=" << amount << ": g_index=" << g_index << "not found in transactions index"); CHECK_AND_ASSERT_MES(tx_ptr->tx.vout.size() > out_ptr->out_no, false, "internal error: in global outs index, transaction out index=" << out_ptr->out_no << " more than transaction outputs = " << tx_ptr->tx.vout.size() << ", for tx id = " << out_ptr->tx_id); + + CHECK_AND_ASSERT_MES(amount != 0 || height_upper_limit != 0, false, "height_upper_limit must be nonzero for hidden amounts (amount = 0)"); + + if (height_upper_limit != 0 && tx_ptr->m_keeper_block_height > height_upper_limit) + return false; const transaction& tx = tx_ptr->tx; CHECK_AND_ASSERT_MES(tx_ptr->m_spent_flags.size() == tx.vout.size(), false, "internal error: spent_flag.size()=" << tx_ptr->m_spent_flags.size() << ", tx.vout.size()=" << tx.vout.size()); @@ -2495,12 +2501,25 @@ bool blockchain_storage::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPU //check if transaction is unlocked if (!is_tx_spendtime_unlocked(get_tx_unlock_time(tx, out_ptr->out_no))) return false; + + const tx_out_v& out_v = tx.vout[out_ptr->out_no]; // do not use burned coins - if (is_out_burned(tx.vout[out_ptr->out_no])) + if (is_out_burned(out_v)) return false; - VARIANT_SWITCH_BEGIN(tx.vout[out_ptr->out_no]); + // check mix_attr + uint8_t mix_attr = CURRENCY_TO_KEY_OUT_RELAXED; + if (!get_mix_attr_from_tx_out_v(out_v, mix_attr)) + return false; // output has no mix_attr, skip it + if (mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) + return false; //COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS call means that ring signature will have more than one entry. + else if (use_only_forced_to_mix && mix_attr == CURRENCY_TO_KEY_OUT_RELAXED) + return false; //relaxed not allowed + else if (mix_attr != CURRENCY_TO_KEY_OUT_RELAXED && mix_attr > mix_count) + return false; //mix_attr set to specific minimum, and mix_count is less then desired count + + VARIANT_SWITCH_BEGIN(out_v); VARIANT_CASE_CONST(tx_out_bare, o) { if (o.target.type() == typeid(txout_htlc)) @@ -2508,41 +2527,20 @@ bool blockchain_storage::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPU //silently return false, it's ok return false; } - CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key), false, "unknown tx out type"); + CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key), false, "unexpected out target type: " << o.target.type().name()); const txout_to_key& otk = boost::get(o.target); - // TODO #@#@ remove code duplication, make extracting mix_attr in a more generalized way - - //use appropriate mix_attr out - uint8_t mix_attr = otk.mix_attr; - - if (mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) - return false; //COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS call means that ring signature will have more than one entry. - else if (use_only_forced_to_mix && mix_attr == CURRENCY_TO_KEY_OUT_RELAXED) - return false; //relaxed not allowed - else if (mix_attr != CURRENCY_TO_KEY_OUT_RELAXED && mix_attr > mix_count) - return false;//mix_attr set to specific minimum, and mix_count is less then desired count - COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry& oen = *result_outs.outs.insert(result_outs.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry()); - oen.global_amount_index = i; - oen.out_key = otk.key; + oen.global_amount_index = g_index; + oen.stealth_address = otk.key; } VARIANT_CASE_CONST(tx_out_zarcanum, toz) { - //use appropriate mix_attr out - uint8_t mix_attr = toz.mix_attr; - - if (mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) - return false; //COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS call means that ring signature will have more than one entry. - else if (use_only_forced_to_mix && mix_attr == CURRENCY_TO_KEY_OUT_RELAXED) - return false; //relaxed not allowed - else if (mix_attr != CURRENCY_TO_KEY_OUT_RELAXED && mix_attr > mix_count) - return false;//mix_attr set to specific minimum, and mix_count is less then desired count - COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry& oen = *result_outs.outs.insert(result_outs.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry()); - oen.global_amount_index = i; - oen.out_key = toz.amount_commitment; - // TODO @#@# this is certainly not enough + oen.amount_commitment = toz.amount_commitment; + oen.concealing_point = toz.concealing_point; + oen.global_amount_index = g_index; + oen.stealth_address = toz.stealth_address; } VARIANT_SWITCH_END(); @@ -2572,7 +2570,7 @@ size_t blockchain_storage::find_end_of_allowed_index(uint64_t amount) const bool blockchain_storage::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 { CRITICAL_REGION_LOCAL(m_read_lock); - BOOST_FOREACH(uint64_t amount, req.amounts) + for(uint64_t amount : req.amounts) { 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; @@ -2586,31 +2584,32 @@ bool blockchain_storage::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDO //lets find upper bound of not fresh outs size_t up_index_limit = find_end_of_allowed_index(amount); 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 >= req.outs_count) + if (up_index_limit >= req.decoys_count) { std::set used; size_t try_count = 0; - for(uint64_t j = 0; j != req.outs_count && try_count < up_index_limit;) + for(uint64_t j = 0; j != req.decoys_count && try_count < up_index_limit;) { - size_t i = crypto::rand()%up_index_limit; - if(used.count(i)) + size_t g_index = crypto::rand() % up_index_limit; + if(used.count(g_index)) continue; - bool added = add_out_to_get_random_outs(result_outs, amount, i, req.outs_count, req.use_forced_mix_outs); - used.insert(i); + bool added = add_out_to_get_random_outs(result_outs, amount, g_index, req.decoys_count, req.use_forced_mix_outs, req.height_upper_limit); + used.insert(g_index); if(added) ++j; ++try_count; } - if (result_outs.outs.size() < req.outs_count) + if (result_outs.outs.size() < req.decoys_count) { - LOG_PRINT_RED_L0("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << req.outs_count << ", added " << result_outs.outs.size() << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total"); + LOG_PRINT_RED_L0("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << req.decoys_count << ", added " << result_outs.outs.size() << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total"); } - }else + } + 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, req.outs_count, req.use_forced_mix_outs) ? 1 : 0; - LOG_PRINT_RED_L0("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << req.outs_count << ", added " << added << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total - respond with all good outs"); + added += add_out_to_get_random_outs(result_outs, amount, i, req.decoys_count, req.use_forced_mix_outs, req.height_upper_limit) ? 1 : 0; + LOG_PRINT_RED_L0("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << req.decoys_count << ", added " << added << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total - respond with all good outs"); } } return true; diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index 2671e1a6..b8eab01e 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -618,7 +618,7 @@ namespace currency bool add_transaction_from_block(const transaction& tx, const crypto::hash& tx_id, const crypto::hash& bl_id, uint64_t bl_height, uint64_t timestamp); bool push_transaction_to_global_outs_index(const transaction& tx, const crypto::hash& tx_id, std::vector& 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) const; + 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 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; diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index cb0abf18..db667ec0 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -246,10 +246,8 @@ namespace currency } CHECK_AND_ASSERT_MES(destinations.size() <= CURRENCY_TX_MAX_ALLOWED_OUTS || height == 0, false, "Too many outs (" << destinations.size() << ")! Miner tx can't be constructed."); + tx = AUTO_VAL_INIT_T(transaction); tx.version = tx_version; - tx.vin.clear(); - tx.vout.clear(); - tx.extra.clear(); keypair txkey = keypair::generate(); add_tx_pub_key_to_extra(tx, txkey.pub); diff --git a/src/currency_core/currency_format_utils_abstract.h b/src/currency_core/currency_format_utils_abstract.h index ccbbf7c8..d08f266f 100644 --- a/src/currency_core/currency_format_utils_abstract.h +++ b/src/currency_core/currency_format_utils_abstract.h @@ -229,6 +229,35 @@ namespace currency CHECK_AND_ASSERT_THROW_MES(false, "[get_key_offsets_from_txin_v] Wrong type: " << in_v.type().name()); } //--------------------------------------------------------------- + inline + bool get_mix_attr_from_tx_out_v(const tx_out_v& out_v, uint8_t& result) noexcept + { + try + { + if (out_v.type() == typeid(tx_out_bare)) + { + const tx_out_bare& ob = boost::get(out_v); + if (ob.target.type() == typeid(txout_to_key)) + { + result = boost::get(ob.target).mix_attr; + return true; + } + } + + if (out_v.type() == typeid(tx_out_zarcanum)) + { + result = boost::get(out_v).mix_attr; + return true; + } + } + catch(...) + { + // should never go here, just precaution + } + + return false; + } + //--------------------------------------------------------------- //, txin_htlc, txin_zc_input inline bool compare_variant_by_types(const txin_multisig& left, const txin_multisig& right) { From 08fd1d4248225e0809b5c5723ffce79753d8b40c Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 12 Oct 2022 17:51:32 +0200 Subject: [PATCH 09/16] in CATCH_ENTRY_CUSTOM custom_code moved before error logging --- contrib/epee/include/misc_helpers.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/epee/include/misc_helpers.h b/contrib/epee/include/misc_helpers.h index dd3067c8..fb990e8a 100644 --- a/contrib/epee/include/misc_helpers.h +++ b/contrib/epee/include/misc_helpers.h @@ -54,14 +54,14 @@ catch(const std::exception& ex) \ { \ (void)(ex); \ - LOG_ERROR("Exception at [" << location << "], what=" << ex.what()); \ custom_code; \ + LOG_ERROR("Exception at [" << location << "], what=" << ex.what()); \ return return_val; \ } \ catch(...) \ { \ - LOG_ERROR("Exception at [" << location << "], generic exception \"...\""); \ custom_code; \ + LOG_ERROR("Exception at [" << location << "], generic exception \"...\""); \ return return_val; \ } #define CATCH_ENTRY(location, return_val) CATCH_ENTRY_CUSTOM(location, (void)0, return_val) From 642cc94691cdff5b5dd76c3a99dbd77b31eb5235 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 12 Oct 2022 17:54:42 +0200 Subject: [PATCH 10/16] wallet2::is_in_hardfork_zone() made const --- src/wallet/wallet2.cpp | 5 ++--- src/wallet/wallet2.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index f3e51e5b..7174368f 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3589,10 +3589,9 @@ bool wallet2::get_pos_entries(std::vector& entries) return true; } //---------------------------------------------------------------------------------------------------- -bool wallet2::is_in_hardfork_zone(uint64_t hardfork_index) +bool wallet2::is_in_hardfork_zone(uint64_t hardfork_index) const { - const currency::core_runtime_config& rtc = get_core_runtime_config(); - return rtc.is_hardfork_active_for_height(hardfork_index, get_blockchain_current_size()); + return m_core_runtime_config.is_hardfork_active_for_height(hardfork_index, get_blockchain_current_size()); } //---------------------------------------------------------------------------------------------------- bool wallet2::prepare_and_sign_pos_block(currency::block& b, diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 9298ece2..63758b85 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -1043,7 +1043,7 @@ private: uint64_t get_directly_spent_transfer_index_by_input_in_tracking_wallet(uint64_t amount, const std::vector & key_offsets); uint64_t get_directly_spent_transfer_index_by_input_in_tracking_wallet(const currency::txin_to_key& intk); uint64_t get_directly_spent_transfer_index_by_input_in_tracking_wallet(const currency::txin_zc_input& inzc); - bool is_in_hardfork_zone(uint64_t hardfork_index); + bool is_in_hardfork_zone(uint64_t hardfork_index) const; uint8_t out_get_mixin_attr(const currency::tx_out_v& out_t); const crypto::public_key& out_get_pub_key(const currency::tx_out_v& out_t, std::list& htlc_info_list); From f0bbcb5f40ec37235578e10b7e05b763d8a22857 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 12 Oct 2022 18:02:22 +0200 Subject: [PATCH 11/16] wallet2::prepare_and_sign_pos_block() and COMMAND_RPC_GETBLOCKTEMPLATE refactored --- src/rpc/core_rpc_server.cpp | 6 +- src/rpc/core_rpc_server_commands_defs.h | 23 ++++--- src/wallet/wallet2.cpp | 89 +++++++++++++------------ src/wallet/wallet2.h | 10 +-- tests/core_tests/chaingen.cpp | 8 +-- 5 files changed, 65 insertions(+), 71 deletions(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index e4d50928..9402a875 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -833,11 +833,7 @@ namespace currency params.stakeholder_address = stakeholder_address; params.ex_nonce = req.extra_text; params.pos = req.pos_block; - params.pe.amount = req.pos_amount; - params.pe.g_index = req.pos_g_index; - params.pe.tx_id = req.tx_id; - params.pe.tx_out_index = req.tx_out_index; - params.pe.stake_unlock_time = req.stake_unlock_time; + params.pe = req.pe; //params.pe.keyimage key image will be set in the wallet //params.pe.wallet_index is not included in serialization map, TODO: refactoring here params.pcustom_fill_block_template_func = nullptr; diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 6f553e1e..563fd950 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -803,11 +803,13 @@ namespace currency std::string wallet_address; std::string stakeholder_address; bool pos_block; //is pos block - uint64_t pos_amount; //do we still need it? - uint64_t pos_g_index; // - crypto::hash tx_id; - uint64_t tx_out_index; - uint64_t stake_unlock_time; + //uint64_t pos_amount; //do we still need it? + //uint64_t pos_g_index; // + //crypto::hash tx_id; + //uint64_t tx_out_index; + //uint64_t stake_unlock_time; + + pos_entry pe; // for making PoS blocks BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE_BLOB_AS_HEX_STRING(explicit_transaction) @@ -815,11 +817,12 @@ namespace currency KV_SERIALIZE(wallet_address) KV_SERIALIZE(stakeholder_address); KV_SERIALIZE(pos_block) - KV_SERIALIZE(pos_amount) - KV_SERIALIZE(pos_g_index) - KV_SERIALIZE_POD_AS_HEX_STRING(tx_id) - KV_SERIALIZE(tx_out_index) - KV_SERIALIZE(stake_unlock_time) + //KV_SERIALIZE(pos_amount) + //KV_SERIALIZE(pos_g_index) + //KV_SERIALIZE_POD_AS_HEX_STRING(tx_id) + //KV_SERIALIZE(tx_out_index) + //KV_SERIALIZE(stake_unlock_time) + KV_SERIALIZE(pe) END_KV_SERIALIZE_MAP() }; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 7174368f..c541170b 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3594,45 +3594,50 @@ bool wallet2::is_in_hardfork_zone(uint64_t hardfork_index) const return m_core_runtime_config.is_hardfork_active_for_height(hardfork_index, get_blockchain_current_size()); } //---------------------------------------------------------------------------------------------------- -bool wallet2::prepare_and_sign_pos_block(currency::block& b, - const pos_entry& pos_info, - const crypto::public_key& source_tx_pub_key, - uint64_t in_tx_output_index, - const std::vector& keys_ptrs) +bool wallet2::prepare_and_sign_pos_block(currency::block& b, const pos_entry& pe) const { + WLT_CHECK_AND_ASSERT_MES(pe.wallet_index < m_transfers.size(), false, "invalid pe.wallet_index: " << pe.wallet_index); + const transaction& source_tx = m_transfers[pe.wallet_index].m_ptx_wallet_info->m_tx; + if (!is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM)) { // old PoS with non-hidden amounts WLT_CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(currency::txin_gen), false, "Wrong input 0 type in transaction: " << b.miner_tx.vin[0].type().name()); WLT_CHECK_AND_ASSERT_MES(b.miner_tx.vin[1].type() == typeid(currency::txin_to_key), false, "Wrong input 1 type in transaction: " << b.miner_tx.vin[1].type().name()); auto& txin = boost::get(b.miner_tx.vin[1]); - txin.k_image = pos_info.keyimage; + txin.k_image = pe.keyimage; WLT_CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1 && b.miner_tx.signatures[0].type() == typeid(NLSAG_sig) && boost::get(b.miner_tx.signatures[0]).s.size() == txin.key_offsets.size(), false, "Wrong signatures amount in coinbase transacton"); - //derive secret key crypto::key_derivation pos_coin_derivation = AUTO_VAL_INIT(pos_coin_derivation); - bool r = crypto::generate_key_derivation(source_tx_pub_key, + bool r = crypto::generate_key_derivation(get_tx_pub_key_from_extra(source_tx), m_account.get_keys().view_secret_key, pos_coin_derivation); WLT_CHECK_AND_ASSERT_MES(r, false, "internal error: pos coin base generator: failed to generate_key_derivation(" - << source_tx_pub_key + << pe.tx_id << ", view secret key: " << m_account.get_keys().view_secret_key << ")"); crypto::secret_key derived_secret_ephemeral_key = AUTO_VAL_INIT(derived_secret_ephemeral_key); crypto::derive_secret_key(pos_coin_derivation, - in_tx_output_index, + pe.tx_out_index, m_account.get_keys().spend_secret_key, derived_secret_ephemeral_key); // sign block actually in coinbase transaction crypto::hash block_hash = currency::get_block_hash(b); + // get stake output pub key (stealth address) for ring signature generation + std::vector keys_ptrs; + TRY_ENTRY() + const currency::tx_out_v& stake_out_v = source_tx.vout[pe.tx_out_index]; + keys_ptrs.push_back(&boost::get(boost::get(stake_out_v).target).key); + CATCH_ENTRY_CUSTOM("wallet2::prepare_and_sign_pos_block", { LOG_PRINT_RED_L0("unable to get output's pub key because of the exception"); }, false); + crypto::generate_ring_signature(block_hash, txin.k_image, keys_ptrs, @@ -3808,15 +3813,12 @@ bool wallet2::reset_history() return true; } //------------------------------- -bool wallet2::build_minted_block(const mining_context& cxt, - uint64_t new_block_expected_height /* = UINT64_MAX */) +bool wallet2::build_minted_block(const mining_context& cxt) { - return build_minted_block(cxt, m_account.get_public_address(), new_block_expected_height); + return build_minted_block(cxt, m_account.get_public_address()); } -bool wallet2::build_minted_block(const mining_context& cxt, - const currency::account_public_address& miner_address, - uint64_t new_block_expected_height /* UINT64_MAX */) +bool wallet2::build_minted_block(const mining_context& cxt, const currency::account_public_address& miner_address) { //found a block, construct it, sign and push to daemon WLT_LOG_GREEN("Found kernel, constructing block", LOG_LEVEL_0); @@ -3824,21 +3826,30 @@ bool wallet2::build_minted_block(const mining_context& cxt, WLT_CHECK_AND_ASSERT_MES(cxt.index < m_transfers.size(), false, "cxt.index = " << cxt.index << " is out of bounds"); const transfer_details& td = m_transfers[cxt.index]; - pos_entry pe = AUTO_VAL_INIT(pe); - currency::COMMAND_RPC_GETBLOCKTEMPLATE::request tmpl_req = AUTO_VAL_INIT(tmpl_req); currency::COMMAND_RPC_GETBLOCKTEMPLATE::response tmpl_rsp = AUTO_VAL_INIT(tmpl_rsp); tmpl_req.wallet_address = get_account_address_as_str(miner_address); tmpl_req.stakeholder_address = get_account_address_as_str(m_account.get_public_address()); tmpl_req.pos_block = true; - pe.g_index = tmpl_req.pos_g_index = td.m_global_output_index; - pe.amount = tmpl_req.pos_amount = td.amount();// pe.amount; - pe.keyimage = td.m_key_image; - pe.block_timestamp = td.m_ptx_wallet_info->m_block_timestamp; - pe.stake_unlock_time = tmpl_req.stake_unlock_time = cxt.stake_unlock_time; - pe.tx_id = tmpl_req.tx_id = td.tx_hash(); - pe.tx_out_index = tmpl_req.tx_out_index = td.m_internal_output_index; - pe.wallet_index = cxt.index; + + tmpl_req.pe = AUTO_VAL_INIT(tmpl_req.pe); + tmpl_req.pe.amount = td.amount(); + tmpl_req.pe.block_timestamp = td.m_ptx_wallet_info->m_block_timestamp; + tmpl_req.pe.g_index = td.m_global_output_index; + tmpl_req.pe.keyimage = td.m_key_image; + tmpl_req.pe.stake_unlock_time = cxt.stake_unlock_time; + tmpl_req.pe.tx_id = td.tx_hash(); + tmpl_req.pe.tx_out_index = td.m_internal_output_index; + tmpl_req.pe.wallet_index = cxt.index; + + //pe.g_index = tmpl_req.pos_g_index = td.m_global_output_index; + //pe.amount = tmpl_req.pos_amount = td.amount();// pe.amount; + //pe.keyimage = td.m_key_image; + //pe.block_timestamp = td.m_ptx_wallet_info->m_block_timestamp; + //pe.stake_unlock_time = tmpl_req.stake_unlock_time = cxt.stake_unlock_time; + //pe.tx_id = tmpl_req.tx_id = td.tx_hash(); + //pe.tx_out_index = tmpl_req.tx_out_index = td.m_internal_output_index; + //pe.wallet_index = cxt.index; //tmpl_req.pos_index = pe.index; // gindex <--- this should be removed as soon as pos_entry::index is replaced with tx_id and tx_out_index // TODO: also fill out tx_id and tx_out_index for mining tx creation @@ -3856,9 +3867,9 @@ bool wallet2::build_minted_block(const mining_context& cxt, currency::block b = AUTO_VAL_INIT(b); currency::blobdata block_blob; bool res = epee::string_tools::parse_hexstr_to_binbuff(tmpl_rsp.blocktemplate_blob, block_blob); - WLT_CHECK_AND_ASSERT_MES(res, false, "Failed to create block template after kernel hash found!"); + WLT_CHECK_AND_ASSERT_MES(res, false, "parse_hexstr_to_binbuff() failed after kernel hash found!"); res = parse_and_validate_block_from_blob(block_blob, b); - WLT_CHECK_AND_ASSERT_MES(res, false, "Failed to create block template after kernel hash found!"); + WLT_CHECK_AND_ASSERT_MES(res, false, "parse_and_validate_block_from_blob() failed after kernel hash found!"); if (cxt.last_block_hash != b.prev_id) { @@ -3883,19 +3894,7 @@ bool wallet2::build_minted_block(const mining_context& cxt, else { // old fashioned non-hidden amount PoS scheme - const auto& target = boost::get(stake_out_v).target; - WLT_CHECK_AND_ASSERT_MES(target.type() == typeid(currency::txout_to_key), false, "wrong type_id in source transaction in coinbase tx"); - const currency::txout_to_key& stake_out_to_key = boost::get(target); - std::vector keys_ptrs; - keys_ptrs.push_back(&stake_out_to_key.key); - - - //sign block - res = prepare_and_sign_pos_block(b, - pe, - get_tx_pub_key_from_extra(m_transfers[pe.wallet_index].m_ptx_wallet_info->m_tx), - td.m_internal_output_index, - keys_ptrs); + res = prepare_and_sign_pos_block(b, tmpl_req.pe); WLT_CHECK_AND_ASSERT_MES(res, false, "Failed to prepare_and_sign_pos_block"); } @@ -4784,8 +4783,10 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vector= fake_outputs_count) break; @@ -6050,7 +6051,7 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public continue; tx_output_entry oe = AUTO_VAL_INIT(oe); oe.out_reference = daemon_oe.global_amount_index; - oe.stealth_address = daemon_oe.out_key; + oe.stealth_address = daemon_oe.stealth_address; src.outputs.push_back(oe); if (src.outputs.size() >= fake_outs_count) break; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 63758b85..d655e511 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -821,11 +821,7 @@ namespace tools //next functions in public area only becausce of test_generator //TODO: Need refactoring - remove it back to private zone void set_genesis(const crypto::hash& genesis_hash); - bool prepare_and_sign_pos_block(currency::block& b, - const currency::pos_entry& pos_info, - const crypto::public_key& source_tx_pub_key, - uint64_t in_tx_output_index, - const std::vector& keys_ptrs); + bool prepare_and_sign_pos_block(currency::block& b, const currency::pos_entry& pe) const; void process_new_blockchain_entry(const currency::block& b, const currency::block_direct_data_entry& bche, const crypto::hash& bl_id, @@ -836,8 +832,8 @@ namespace tools bool get_pos_entries(std::vector& entries); // TODO: make it const size_t get_pos_entries_count(); - bool build_minted_block(const mining_context& cxt, uint64_t new_block_expected_height = UINT64_MAX); - bool build_minted_block(const mining_context& cxt, const currency::account_public_address& miner_address, uint64_t new_block_expected_height = UINT64_MAX); + bool build_minted_block(const mining_context& cxt); + bool build_minted_block(const mining_context& cxt, const currency::account_public_address& miner_address); bool reset_history(); bool is_transfer_unlocked(const transfer_details& td) const; bool is_transfer_unlocked(const transfer_details& td, bool for_pos_mining, uint64_t& stake_lock_time) const; diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 94ce0211..55c0cfa9 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -353,7 +353,7 @@ bool test_generator::sign_block(currency::block& b, const std::vector& blocks, const outputs_index& oi) { - uint64_t h = 0; + /*uint64_t h = 0; uint64_t out_i = 0; const transaction * pts = nullptr; crypto::public_key source_tx_pub_key = null_pkey; @@ -368,11 +368,9 @@ bool test_generator::sign_block(currency::block& b, out_i, source_tx_pub_key, out_key); - CHECK_AND_ASSERT_THROW_MES(r, "Failed to get_output_details_by_global_index()"); + CHECK_AND_ASSERT_THROW_MES(r, "Failed to get_output_details_by_global_index()");*/ - std::vector keys_ptrs; - keys_ptrs.push_back(&out_key); - r = w.prepare_and_sign_pos_block(b, pe, source_tx_pub_key, out_i, keys_ptrs); + bool r = w.prepare_and_sign_pos_block(b, pe); CHECK_AND_ASSERT_THROW_MES(r,"Failed to prepare_and_sign_pos_block()"); return true; From 30972db5ad9fd57f5a9bb09309ccff3610bf8d7a Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 12 Oct 2022 18:07:04 +0200 Subject: [PATCH 12/16] COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS adaptation and improvements --- src/rpc/core_rpc_server_commands_defs.h | 10 +++++++--- src/wallet/wallet2.cpp | 6 +++--- tests/core_tests/get_random_outs.cpp | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 563fd950..f6c87873 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -318,11 +318,13 @@ namespace currency struct request { std::list amounts; - uint64_t outs_count; + uint64_t decoys_count; // how many decoy outputs needed (per amount) + uint64_t height_upper_limit; // all the decoy outputs must be either older than, or the same age as this height bool use_forced_mix_outs; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(amounts) - KV_SERIALIZE(outs_count) + KV_SERIALIZE(decoys_count) + KV_SERIALIZE(height_upper_limit) KV_SERIALIZE(use_forced_mix_outs) END_KV_SERIALIZE_MAP() }; @@ -331,7 +333,9 @@ namespace currency struct out_entry { uint64_t global_amount_index; - crypto::public_key out_key; + crypto::public_key stealth_address; + crypto::public_key concealing_point; + crypto::public_key amount_commitment; }; #pragma pack(pop) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index c541170b..1147660a 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -4731,7 +4731,7 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vector scanty_outs; for(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& amount_outs : daemon_resp.outs) { - if (amount_outs.outs.size() < req.outs_count) + if (amount_outs.outs.size() < req.decoys_count) { scanty_outs.push_back(amount_outs); } @@ -5980,7 +5980,7 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public { COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request req = AUTO_VAL_INIT(req); req.use_forced_mix_outs = false; - req.outs_count = fake_outs_count + 1; + req.decoys_count = fake_outs_count + 1; for (uint64_t i : selected_transfers) req.amounts.push_back(m_transfers[i].amount()); diff --git a/tests/core_tests/get_random_outs.cpp b/tests/core_tests/get_random_outs.cpp index 7c5f825d..807ad122 100644 --- a/tests/core_tests/get_random_outs.cpp +++ b/tests/core_tests/get_random_outs.cpp @@ -52,7 +52,7 @@ bool get_random_outs_test::check_get_rand_outs(currency::core& c, size_t ev_inde { currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request req = AUTO_VAL_INIT(req); req.amounts.push_back(m_amount); - req.outs_count = 4; + req.decoys_count = 4; req.use_forced_mix_outs = false; currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response res = AUTO_VAL_INIT(res); c.get_blockchain_storage().get_random_outs_for_amounts(req, res); From 49e78fdbae5c6e7022a39a9ca4960543bd4a7d66 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 12 Oct 2022 19:14:31 +0200 Subject: [PATCH 13/16] Bulletproofs+ Extended generation routine (crypto::bppe_gen) adapted to match with bpp_gen --- src/crypto/range_proof_bppe.h | 43 ++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/crypto/range_proof_bppe.h b/src/crypto/range_proof_bppe.h index 4b074dd9..82d1af40 100644 --- a/src/crypto/range_proof_bppe.h +++ b/src/crypto/range_proof_bppe.h @@ -27,15 +27,17 @@ namespace crypto #define DBG_VAL_PRINT(x) (void(0)) // std::cout << #x ": " << x << ENDL #define DBG_PRINT(x) (void(0)) // std::cout << x << ENDL - template - bool bppe_gen(const scalar_vec_t& values, const scalar_vec_t& masks, const scalar_vec_t& masks2, bppe_signature& sig, std::vector& commitments, uint8_t* p_err = nullptr) - { #define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ if (!(cond)) { LOG_PRINT_RED("bppe_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \ if (p_err) { *p_err = err_code; } return false; } + + template + bool bppe_gen(const scalar_vec_t& values, const scalar_vec_t& masks, const scalar_vec_t& masks2, const std::vector& commitments_1div8, bppe_signature& sig, uint8_t* p_err = nullptr) + { + // Note: commitments_1div8 are supposed to be already calculated static_assert(CT::c_bpp_n <= 255, "too big N"); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() > 0 && values.size() <= CT::c_bpp_values_max && values.size() == masks.size() && masks.size() == masks2.size(), 1); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() > 0 && values.size() <= CT::c_bpp_values_max && values.size() == masks.size() && masks.size() == masks2.size() && values.size() == commitments_1div8.size(), 1); CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(masks.is_reduced() && masks2.is_reduced(), 3); const size_t c_bpp_log2_m = constexpr_ceil_log2(values.size()); @@ -43,15 +45,6 @@ namespace crypto const size_t c_bpp_mn = c_bpp_m * CT::c_bpp_n; const size_t c_bpp_log2_mn = c_bpp_log2_m + CT::c_bpp_log2_n; - // pre-multiply all output points by c_scalar_1div8 - // in order to enforce these points to be in the prime-order subgroup (after mul by 8 in bpp_verify()) - - // calc commitments vector as commitments[i] = 1/8 * values[i] * G + 1/8 * masks[i] * H + 1/8 * masks2[i] * H2 - commitments.resize(values.size()); - for (size_t i = 0; i < values.size(); ++i) - CT::calc_pedersen_commitment_2(values[i] * c_scalar_1div8, masks[i] * c_scalar_1div8, masks2[i] * c_scalar_1div8, commitments[i]); - - // s.a. BP+ paper, page 15, eq. 11 // decompose v into aL and aR: // v = aL o (1, 2, 2^2, ..., 2^n-1), o - component-wise product aka Hadamard product @@ -86,7 +79,7 @@ namespace crypto DBG_PRINT("initial transcript: " << e); hash_helper_t::hs_t hsc; - CT::update_transcript(hsc, e, commitments); + CT::update_transcript(hsc, e, commitments_1div8); // Zarcanum paper, page 33, Fig. D.3: The prover chooses alpha_1, alpha_2 and computes A = g^aL h^aR h_1^alpha_1 h_2^alpha_2 // so we calculate A0 = alpha_1 * H + alpha_2 * H_2 + SUM(aL_i * G_i) + SUM(aR_i * H_i) @@ -336,10 +329,28 @@ namespace crypto DBG_VAL_PRINT(sig.delta_2); return true; -#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE } // bppe_gen() + // convenient overload for tests + template + bool bppe_gen(const scalar_vec_t& values, const scalar_vec_t& masks, const scalar_vec_t& masks2, bppe_signature& sig, std::vector& commitments_1div8_to_be_generated, uint8_t* p_err = nullptr) + { + // calc commitments vector as commitments[i] = 1/8 * values[i] * G + 1/8 * masks[i] * H + 1/8 * masks2[i] * H2 + commitments_1div8_to_be_generated.resize(values.size()); + std::vector commitments_1div8(values.size()); + std::vector commitments_1div8_pointers(values.size()); + for (size_t i = 0; i < values.size(); ++i) + { + CT::calc_pedersen_commitment_2(values[i] * c_scalar_1div8, masks[i] * c_scalar_1div8, masks2[i] * c_scalar_1div8, commitments_1div8_to_be_generated[i]); + commitments_1div8[i] = (commitments_1div8_to_be_generated[i]).to_public_key(); + commitments_1div8_pointers[i] = &commitments_1div8[i]; + } + return bppe_gen(values, masks, masks2, commitments_1div8_pointers, sig, p_err); + } + #undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + + struct bppe_sig_commit_ref_t { bppe_sig_commit_ref_t(const bppe_signature& sig, const std::vector& commitments) @@ -347,7 +358,7 @@ namespace crypto , commitments(commitments) {} const bppe_signature& sig; - const std::vector& commitments; + const std::vector& commitments; // assumed to be premultiplied by 1/8 }; From 7a1a4b00589abd9caad56acabd09e27de74f4125 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 12 Oct 2022 19:17:00 +0200 Subject: [PATCH 14/16] crypto: zarcanum signature generation partially done (work in progress) --- src/crypto/zarcanum.cpp | 128 +++++++++++++++++++- src/crypto/zarcanum.h | 29 +++++ src/currency_core/crypto_config.h | 1 + src/currency_core/currency_basic.h | 27 ++++- src/currency_core/currency_format_utils.cpp | 7 +- src/currency_core/currency_format_utils.h | 1 + 6 files changed, 186 insertions(+), 7 deletions(-) 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; From 525b0cb84003607bf16ea16436c0ddbd0e06cbca Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 12 Oct 2022 19:26:03 +0200 Subject: [PATCH 15/16] coretests: zarcanum_test improvements --- tests/core_tests/zarcanum_test.cpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/tests/core_tests/zarcanum_test.cpp b/tests/core_tests/zarcanum_test.cpp index 73760667..6da94f61 100644 --- a/tests/core_tests/zarcanum_test.cpp +++ b/tests/core_tests/zarcanum_test.cpp @@ -119,20 +119,17 @@ bool zarcanum_basic_test::c1(currency::core& c, size_t ev_index, const std::vect miner_benefeciary_acc.generate(); std::shared_ptr miner_benefeciary_acc_wlt = init_playtime_test_wallet(events, c, miner_benefeciary_acc); + alice_wlt->refresh(); + size_t pos_entries_count = 0; //do staking - for(size_t i = 0; i!= CURRENCY_MINED_MONEY_UNLOCK_WINDOW+4; i++) + for(size_t i = 0; i != CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 4; i++) { - if (!mine_next_pos_block_in_playtime_with_wallet(*alice_wlt.get(), staker_benefeciary_acc_wlt->get_account().get_public_address(), pos_entries_count)) - { - CHECK_AND_ASSERT_MES(false, false, "Couldn't generate staking"); - return false; - } - if (!mine_next_pow_block_in_playtime(miner_benefeciary_acc.get_public_address(), c)) - { - CHECK_AND_ASSERT_MES(false, false, "Couldn't generate pow"); - return false; - } + r = mine_next_pos_block_in_playtime_with_wallet(*alice_wlt.get(), staker_benefeciary_acc_wlt->get_account().get_public_address(), pos_entries_count); + CHECK_AND_ASSERT_MES(r, false, "mine_next_pos_block_in_playtime_with_wallet failed"); + + r = mine_next_pow_block_in_playtime(miner_benefeciary_acc.get_public_address(), c); + CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed"); } //attempt to spend staked and mined coinbase outs @@ -140,10 +137,10 @@ bool zarcanum_basic_test::c1(currency::core& c, size_t ev_index, const std::vect miner_benefeciary_acc_wlt->refresh(); staker_benefeciary_acc_wlt->transfer(transfer_amount2, bob_acc.get_public_address()); - LOG_PRINT_MAGENTA("Zarcanum(pos-coinbase)-2-zarcanum transaction sent from Staker to Bob " << transfer_amount2, LOG_LEVEL_0); + LOG_PRINT_MAGENTA("Zarcanum(pos-coinbase)-2-zarcanum transaction sent from Staker to Bob " << print_money_brief(transfer_amount2), LOG_LEVEL_0); miner_benefeciary_acc_wlt->transfer(transfer_amount2, bob_acc.get_public_address()); - LOG_PRINT_MAGENTA("Zarcanum(pow-coinbase)-2-zarcanum transaction sent from Staker to Bob " << transfer_amount2, LOG_LEVEL_0); + LOG_PRINT_MAGENTA("Zarcanum(pow-coinbase)-2-zarcanum transaction sent from Staker to Bob " << print_money_brief(transfer_amount2), LOG_LEVEL_0); CHECK_AND_FORCE_ASSERT_MES(c.get_pool_transactions_count() == 2, false, "Incorrect txs count in the pool"); From 5b086b935674274eccf4668b1e532f406c61dc28 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 12 Oct 2022 21:24:15 +0200 Subject: [PATCH 16/16] compilation fix (gcc) --- src/crypto/zarcanum.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/zarcanum.h b/src/crypto/zarcanum.h index 528cdfd9..f444d152 100644 --- a/src/crypto/zarcanum.h +++ b/src/crypto/zarcanum.h @@ -6,7 +6,7 @@ // 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/range_proofs.h" #include "crypto/clsag.h" #include