From b94c9f75d3a43e07512da673255eac1ab13c64e4 Mon Sep 17 00:00:00 2001 From: sowle Date: Fri, 14 Oct 2022 19:08:27 +0200 Subject: [PATCH 1/7] 1) logging: channel(s) enabling made optionally less verbose; 2) various fixes after the merge --- contrib/epee/include/misc_log_ex.h | 18 +++++++++++------- src/currency_core/currency_format_utils.cpp | 4 +--- .../currency_format_utils_abstract.h | 1 - src/daemon/daemon.cpp | 2 +- src/wallet/plain_wallet_api.cpp | 2 +- src/wallet/wallet2.h | 3 --- tests/core_tests/chaingen_main.cpp | 2 +- tests/functional_tests/crypto_tests_ml2s.h | 2 +- tests/unit_tests/db_tests.cpp | 2 +- 9 files changed, 17 insertions(+), 19 deletions(-) diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h index c9a96148..f2d1abd2 100644 --- a/contrib/epee/include/misc_log_ex.h +++ b/contrib/epee/include/misc_log_ex.h @@ -116,7 +116,7 @@ DISABLE_VS_WARNINGS(4100) #define ENABLE_CHANNEL_BY_DEFAULT(ch_name) \ static bool COMBINE(init_channel, __LINE__) UNUSED_ATTRIBUTE = epee::misc_utils::static_initializer([](){ \ - epee::log_space::log_singletone::enable_channel(ch_name); return true; \ + epee::log_space::log_singletone::enable_channel(ch_name, false); return true; \ }); @@ -1239,21 +1239,24 @@ namespace log_space return genabled_channels.find(ch_name) != genabled_channels.end(); } - static void enable_channels(const std::string& channels_set) + static void enable_channels(const std::string& channels_set, bool verbose = true) { std::set& genabled_channels = get_enabled_channels(); std::list list_of_channels; boost::split(list_of_channels, channels_set, boost::is_any_of(",;: "), boost::token_compress_on); - std::cout << "log channels: "; + if (verbose) + std::cout << "log channels: "; for (const auto& ch : list_of_channels) { genabled_channels.insert(ch); - std::cout << ch << " "; + if (verbose) + std::cout << ch << " "; } - std::cout << " enabled" << std::endl; + if (verbose) + std::cout << " enabled" << std::endl; } - static void enable_channel(const std::string& ch_name) + static void enable_channel(const std::string& ch_name, bool verbose = true) { std::set& genabled_channels = get_enabled_channels(); //lazy synchronization: just replace with modified copy of whole set @@ -1261,7 +1264,8 @@ namespace log_space enabled_channels_local.insert(ch_name); genabled_channels.swap(enabled_channels_local); #ifndef ANDROID_BUILD - //std::cout << "log channel '" << ch_name << "' enabled" << std::endl; + if (verbose) + std::cout << "log channel '" << ch_name << "' enabled" << std::endl; #endif } diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 95eaec9e..098ccd48 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -578,7 +578,7 @@ namespace currency } //--------------------------------------------------------------- - bool get_tx_fee(const transaction& tx, uint64_t & fee) + bool get_tx_fee(const transaction& tx, uint64_t& fee) { fee = 0; if (is_coinbase(tx)) @@ -607,10 +607,8 @@ namespace currency return true; // continue }; - bool r = process_type_in_variant_container(tx.extra, cb, false); - if (!r) { fee = 0; diff --git a/src/currency_core/currency_format_utils_abstract.h b/src/currency_core/currency_format_utils_abstract.h index 3d8b4226..7355c84f 100644 --- a/src/currency_core/currency_format_utils_abstract.h +++ b/src/currency_core/currency_format_utils_abstract.h @@ -218,7 +218,6 @@ namespace currency catch(...) { // should never go here, just precaution - return false; } return false; diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index 43f1efe6..d9ea6f6c 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -125,7 +125,7 @@ int main(int argc, char* argv[]) #endif log_space::get_set_log_detalisation_level(true, LOG_LEVEL_0); log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL); - log_space::log_singletone::enable_channels("core,currency_protocol,tx_pool,wallet"); + log_space::log_singletone::enable_channels("core,currency_protocol,tx_pool,wallet", false); LOG_PRINT_L0("Starting..."); tools::signal_handler::install_fatal([](int sig_number, void* address) { diff --git a/src/wallet/plain_wallet_api.cpp b/src/wallet/plain_wallet_api.cpp index 2e7914fb..d628446e 100644 --- a/src/wallet/plain_wallet_api.cpp +++ b/src/wallet/plain_wallet_api.cpp @@ -130,7 +130,7 @@ namespace plain_wallet log_dir += "/" LOGS_FOLDER; log_space::get_set_need_thread_id(true, true); - log_space::log_singletone::enable_channels("core,currency_protocol,tx_pool,p2p,wallet"); + log_space::log_singletone::enable_channels("core,currency_protocol,tx_pool,p2p,wallet", false); epee::log_space::get_set_log_detalisation_level(true, log_level); #ifdef ANDROID_BUILD epee::log_space::log_singletone::add_logger(new android_logger()); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index a630312e..52ff03ee 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -252,9 +252,6 @@ namespace tools const currency::tx_destination_entry& change_dst, uint64_t dust_threshold, std::vector& splitted_dsts, uint64_t& dust, uint64_t max_output_allowed) { - //&&&&& - LOG_PRINT_MAGENTA("[--apply_split_strategy_by_id, split strtegy_id: " << id, LOG_LEVEL_0); - switch (id) { case ssi_digit: diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index b0638233..7086798f 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -658,7 +658,7 @@ int main(int argc, char* argv[]) log_space::log_singletone::get_default_log_file().c_str(), log_space::log_singletone::get_default_log_folder().c_str()); - log_space::log_singletone::enable_channels("core,currency_protocol,tx_pool,p2p,wallet"); + log_space::log_singletone::enable_channels("core,currency_protocol,tx_pool,p2p,wallet", false); tools::signal_handler::install_fatal([](int sig_number, void* address) { LOG_ERROR("\n\nFATAL ERROR\nsig: " << sig_number << ", address: " << address); diff --git a/tests/functional_tests/crypto_tests_ml2s.h b/tests/functional_tests/crypto_tests_ml2s.h index b18997a9..c38c8d13 100644 --- a/tests/functional_tests/crypto_tests_ml2s.h +++ b/tests/functional_tests/crypto_tests_ml2s.h @@ -64,7 +64,7 @@ TEST(ml2s, hs) x = 0; crypto::hash h; - scalar_t r; + //scalar_t r; sha3(0, 0, &h, sizeof h); LOG_PRINT("SHA3() -> " << h, LOG_LEVEL_0); diff --git a/tests/unit_tests/db_tests.cpp b/tests/unit_tests/db_tests.cpp index fcf5bac0..61a0ae19 100644 --- a/tests/unit_tests/db_tests.cpp +++ b/tests/unit_tests/db_tests.cpp @@ -986,7 +986,7 @@ namespace db_test bool r = false; epee::shared_recursive_mutex rw_lock; - epee::log_space::log_singletone::enable_channels("lmdb"); + epee::log_space::log_singletone::enable_channels("lmdb", false); static const uint64_t buffer_size = 64 * 1024; // 64 KB static const uint64_t db_total_size = static_cast(2.1 * 1024 * 1024 * 1024); // 2.1 GB -- a bit more than 2GB to test 2GB boundary From 47d18e5deb3a992d1c8b2b06839fe82660780a4c Mon Sep 17 00:00:00 2001 From: sowle Date: Fri, 14 Oct 2022 19:18:24 +0200 Subject: [PATCH 2/7] wallet2::prepare_and_sign_pos_block() refactored, vector added --- src/wallet/wallet2.cpp | 47 +++++++++------------- src/wallet/wallet2.h | 3 +- tests/core_tests/chain_switch_pow_pos.cpp | 4 +- tests/core_tests/chaingen.cpp | 49 ++++++++--------------- tests/core_tests/chaingen.h | 11 ++++- tests/core_tests/wallet_tests_basic.cpp | 4 +- 6 files changed, 50 insertions(+), 68 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 468c15e5..75e8368a 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3647,12 +3647,15 @@ 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& pe) const +bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, currency::block& b, const pos_entry& pe) const { + bool r = false; 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)) + const transfer_details& td = m_transfers[pe.wallet_index]; + const transaction& source_tx = td.m_ptx_wallet_info->m_tx; + WLT_CHECK_AND_ASSERT_MES(pe.tx_out_index < source_tx.vout.size(), false, "invalid pe.tx_out_index: " << pe.tx_out_index); + const currency::tx_out_v& stake_out_v = source_tx.vout[pe.tx_out_index]; + if (!cxt.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()); @@ -3687,7 +3690,6 @@ bool wallet2::prepare_and_sign_pos_block(currency::block& b, const pos_entry& pe // 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); @@ -3884,6 +3886,7 @@ bool wallet2::build_minted_block(const mining_context& cxt, const currency::acco 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; + tmpl_req.extra_text = m_miner_text_info; tmpl_req.pe = AUTO_VAL_INIT(tmpl_req.pe); tmpl_req.pe.amount = td.amount(); @@ -3895,18 +3898,6 @@ bool wallet2::build_minted_block(const mining_context& cxt, const currency::acco 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 - tmpl_req.extra_text = m_miner_text_info; //generate packing tx transaction pack_tx = AUTO_VAL_INIT(pack_tx); if (generate_packing_transaction_if_needed(pack_tx, 0)) @@ -3936,20 +3927,18 @@ bool wallet2::build_minted_block(const mining_context& cxt, const currency::acco set_block_datetime(current_timestamp, b); WLT_LOG_MAGENTA("Applying actual timestamp: " << current_timestamp, LOG_LEVEL_0); - const currency::tx_out_v& stake_out_v = td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]; - if (cxt.zarcanum && td.is_zc()) - { - // Zarcanum - WLT_CHECK_AND_ASSERT_MES(stake_out_v.type() == typeid(tx_out_zarcanum), false, "unexpected stake output type: " << stake_out_v.type().name() << ", expected: zarcanum"); - - return false; - } - else - { + //const currency::tx_out_v& stake_out_v = td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]; + //if (cxt.zarcanum && td.is_zc()) + //{ + // // Zarcanum + // return false; + //} + //else + //{ // old fashioned non-hidden amount PoS scheme - res = prepare_and_sign_pos_block(b, tmpl_req.pe); + res = prepare_and_sign_pos_block(cxt, b, tmpl_req.pe); WLT_CHECK_AND_ASSERT_MES(res, false, "Failed to prepare_and_sign_pos_block"); - } + //} crypto::hash block_hash = get_block_hash(b); WLT_LOG_GREEN("Block " << print16(block_hash) << " has been constructed, sending to core...", LOG_LEVEL_0); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 52ff03ee..16796983 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -429,6 +429,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 z_l_div_z_D; // Zarcanum notation: z * floor( l / (z * D) ) (max possible value (assuming z=2^64) : z * 2^252 / (z * 1) ~= 2^252) + crypto::hash kernel_hash; // Zarcanum notation: h currency::wide_difficulty_type basic_diff; currency::stake_kernel sk; @@ -839,7 +840,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& pe) const; + bool prepare_and_sign_pos_block(const mining_context& cxt, 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, diff --git a/tests/core_tests/chain_switch_pow_pos.cpp b/tests/core_tests/chain_switch_pow_pos.cpp index 73512246..21fb28ea 100644 --- a/tests/core_tests/chain_switch_pow_pos.cpp +++ b/tests/core_tests/chain_switch_pow_pos.cpp @@ -221,7 +221,7 @@ bool gen_chain_switch_pow_pos::check_balance_1(currency::core& c, size_t ev_inde test_generator::wallets_vector w; bool r = generator.build_wallets(get_block_hash(plk_2), m_accounts, w); - CHECK_AND_ASSERT_MES(r && w.size() == 3 && w[0] != 0 && w[1] != 0 && w[2] != 0, false, "failed to build wallets"); + CHECK_AND_ASSERT_MES(r && w.size() == 3 && w[0].wallet != 0 && w[1].wallet != 0 && w[2].wallet != 0, false, "failed to build wallets"); /* uint64_t mined_amount = m_early_blocks_reward * 12 + TX_POOL_MINIMUM_FEE / 2 + m_enormous_fee / 2; @@ -229,7 +229,7 @@ bool gen_chain_switch_pow_pos::check_balance_1(currency::core& c, size_t ev_inde return false; */ - if (!check_balance_via_wallet(*w[1], "alice", MK_TEST_COINS(1), 0, 0, 0, 0)) + if (!check_balance_via_wallet(*w[1].wallet, "alice", MK_TEST_COINS(1), 0, 0, 0, 0)) return false; return true; diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 897d9a4b..11c2dbce 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -330,7 +330,7 @@ bool test_generator::construct_block(currency::block& blk, else { //need to build pos block - r = sign_block(blk, pe, *wallets[won_walled_index], blocks, oi); + r = sign_block(blk, pe, *wallets[won_walled_index].wallet, wallets[won_walled_index].mining_context, blocks, oi); CHECK_AND_ASSERT_MES(r, false, "Failed to find_kernel_and_sign()"); } @@ -347,32 +347,15 @@ bool test_generator::construct_block(currency::block& blk, return true; } -bool test_generator::sign_block(currency::block& b, - pos_entry& pe, - tools::wallet2& w, +bool test_generator::sign_block(currency::block& b, + pos_entry& pe, + tools::wallet2& w, + const tools::wallet2::mining_context& mining_context, const std::vector& blocks, const outputs_index& oi) { - /*uint64_t h = 0; - uint64_t out_i = 0; - const transaction * pts = nullptr; - crypto::public_key source_tx_pub_key = null_pkey; - crypto::public_key out_key = null_pkey; - - bool r = get_output_details_by_global_index(blocks, - oi, - pe.amount, - pe.g_index, - h, - pts, - out_i, - source_tx_pub_key, - out_key); - CHECK_AND_ASSERT_THROW_MES(r, "Failed to get_output_details_by_global_index()");*/ - - bool r = w.prepare_and_sign_pos_block(b, pe); - CHECK_AND_ASSERT_THROW_MES(r,"Failed to prepare_and_sign_pos_block()"); - + bool r = w.prepare_and_sign_pos_block(mining_context, b, pe); + CHECK_AND_ASSERT_MES(r, false, "prepare_and_sign_pos_block failed"); return true; } @@ -438,10 +421,11 @@ bool test_generator::build_wallets(const blockchain_vector& blockchain, wallets.clear(); for (auto a : accs) { - wallets.push_back(std::shared_ptr(new tools::wallet2())); - wallets.back()->assign_account(a); - wallets.back()->get_account().set_createtime(0); - wallets.back()->set_core_proxy(tmp_proxy); + wallets.push_back(gen_wallet_info()); + wallets.back().wallet = std::shared_ptr(new tools::wallet2()); + wallets.back().wallet->assign_account(a); + wallets.back().wallet->get_account().set_createtime(0); + wallets.back().wallet->set_core_proxy(tmp_proxy); currency::core_runtime_config pc = cc; pc.min_coinstake_age = TESTS_POS_CONFIG_MIN_COINSTAKE_AGE; @@ -449,7 +433,7 @@ bool test_generator::build_wallets(const blockchain_vector& blockchain, pc.hard_forks = m_hardforks; pc.get_core_time = test_core_time::get_time; - wallets.back()->set_core_runtime_config(pc); + wallets.back().wallet->set_core_runtime_config(pc); } for (auto& w : wallets) @@ -474,7 +458,7 @@ bool test_generator::build_wallets(const blockchain_vector& blockchain, bdde.txs_ptr.push_back(tx_ptr); } - w->process_new_blockchain_entry(b->b, bdde, currency::get_block_hash(b->b), height); + w.wallet->process_new_blockchain_entry(b->b, bdde, currency::get_block_hash(b->b), height); } } return true; @@ -539,12 +523,13 @@ bool test_generator::find_kernel(const std::list& accs, //lets try to find block for (size_t wallet_index = 0, size = wallets.size(); wallet_index < size; ++wallet_index) { - std::shared_ptr w = wallets[wallet_index]; + std::shared_ptr w = wallets[wallet_index].wallet; + wallets[wallet_index].mining_context = AUTO_VAL_INIT_T(tools::wallet2::mining_context); + tools::wallet2::mining_context& context = wallets[wallet_index].mining_context; //set m_last_pow_block_h to big value, to let wallet to use any available outputs, including the those which is not behind last pow block if (m_ignore_last_pow_in_wallets) w->m_last_pow_block_h = CURRENCY_MAX_BLOCK_NUMBER; - tools::wallet2::mining_context context = AUTO_VAL_INIT(context); w->fill_mining_context(context); std::atomic stop(false); diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index 24026886..9a9ea641 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -372,7 +372,13 @@ public: typedef std::unordered_map > tx_global_indexes; typedef std::vector blockchain_vector; - typedef std::vector > wallets_vector; + + struct gen_wallet_info + { + tools::wallet2::mining_context mining_context; + std::shared_ptr wallet; + }; + typedef std::vector wallets_vector; enum block_fields @@ -430,7 +436,8 @@ public: bool sign_block(currency::block& b, currency::pos_entry& pe, - tools::wallet2& w, + tools::wallet2& w, + const tools::wallet2::mining_context& mining_context, const blockchain_vector& blocks, const outputs_index& oi); diff --git a/tests/core_tests/wallet_tests_basic.cpp b/tests/core_tests/wallet_tests_basic.cpp index a3d40912..6d3c9292 100644 --- a/tests/core_tests/wallet_tests_basic.cpp +++ b/tests/core_tests/wallet_tests_basic.cpp @@ -47,9 +47,9 @@ bool wallet_test::check_balance_via_build_wallets(currency::core& c, size_t ev_i std::list accounts(1, acc); test_generator::wallets_vector w; r = generator.build_wallets(get_block_hash(*top_block), accounts, w, c.get_blockchain_storage().get_core_runtime_config()); - CHECK_AND_ASSERT_MES(r && w.size() == 1 && w[0] != 0, false, "check_balance: failed to build wallets"); + CHECK_AND_ASSERT_MES(r && w.size() == 1 && w[0].wallet != 0, false, "check_balance: failed to build wallets"); - if (!check_balance_via_wallet(*w[0], epee::string_tools::num_to_string_fast(pcb.account_index).c_str(), pcb.total_balance, pcb.mined_balance, pcb.unlocked_balance, pcb.awaiting_in, pcb.awaiting_out)) + if (!check_balance_via_wallet(*w[0].wallet, epee::string_tools::num_to_string_fast(pcb.account_index).c_str(), pcb.total_balance, pcb.mined_balance, pcb.unlocked_balance, pcb.awaiting_in, pcb.awaiting_out)) return false; return true; From c5206d0f52786dd4f3e38c221810c3add034836a Mon Sep 17 00:00:00 2001 From: sowle Date: Fri, 14 Oct 2022 19:26:52 +0200 Subject: [PATCH 3/7] zarcanum PoS: another iteration on zarcanum_generate_proof (WIP) --- src/crypto/zarcanum.cpp | 20 ++++++++++++-------- src/crypto/zarcanum.h | 13 ++++++++----- src/currency_core/currency_format_utils.cpp | 12 +++++++++--- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/crypto/zarcanum.cpp b/src/crypto/zarcanum.cpp index fc905029..29227c69 100644 --- a/src/crypto/zarcanum.cpp +++ b/src/crypto/zarcanum.cpp @@ -46,8 +46,12 @@ namespace crypto 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) + + bool zarcanum_generate_proof(const hash& m, const hash& kernel_hash, const std::vector& ring, const point_t& pseudo_out_amount_commitment, + 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 */) { const scalar_t a = stake_amount; const scalar_t h = scalar_t(kernel_hash); @@ -71,9 +75,9 @@ namespace crypto 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(); + result.C = (c_scalar_1div8 * C).to_public_key(); + result.C_prime = (c_scalar_1div8 * C_prime).to_public_key(); + result.E = (c_scalar_1div8 * 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) @@ -109,12 +113,12 @@ namespace crypto 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 values = { ba }; // 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 }; + const std::vector E_1div8_vec_ptr = { &result.E }; - if (!bppe_gen>(values, masks, masks2, commitments_1div8, result.E_range_proof, p_err)) + if (!bppe_gen>(values, masks, masks2, E_1div8_vec_ptr, result.E_range_proof, p_err)) { return false; } diff --git a/src/crypto/zarcanum.h b/src/crypto/zarcanum.h index f444d152..b59b4b0f 100644 --- a/src/crypto/zarcanum.h +++ b/src/crypto/zarcanum.h @@ -27,9 +27,9 @@ namespace crypto struct zarcanum_proof { scalar_t d = 0; - public_key C; - public_key C_prime; - public_key E; + public_key C; // premultiplied by 1/8 + public_key C_prime; // premultiplied by 1/8 + public_key E; // premultiplied by 1/8 scalar_t c; // shared Fiat-Shamir challenge for the following three proofs scalar_t y0; // 1st linear composition proof @@ -39,10 +39,13 @@ namespace crypto scalar_t y4; // Schnorr proof (F = lin(X)) bppe_signature E_range_proof; - CLSAG_GGXG_signature ring_sig; + + crypto::public_key pseudo_out_amount_commitment; // premultiplied by 1/8 + CLSAG_GGXG_signature clsag_ggxg; }; - bool zarcanum_generate_proof(const hash& kernel_hash, const public_key& stake_commitment_1div8, const scalar_t& last_pow_block_id_hashed, + bool zarcanum_generate_proof(const hash& m, const hash& kernel_hash, const std::vector& ring, const point_t& pseudo_out_amount_commitment, + 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); diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 098ccd48..4cf330cf 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -265,16 +265,22 @@ namespace currency in.height = height; tx.vin.push_back(in); + // input #1: stake (for PoS blocks only) if (pos) { - // input #1: stake (for PoS blocks only) - if (tx.version > TRANSACTION_VERSION_PRE_HF4) + if (tx.version > TRANSACTION_VERSION_PRE_HF4 /* && stake is zarcanum */) { // TODO: add Zarcanum part + txin_zc_input stake_input; + //stake_input.key_offsets.push_back(pe.g_index); + stake_input.k_image = pe.keyimage; + tx.vin.emplace_back(std::move(stake_input)); + //reserve place for ring signature + tx.signatures.emplace_back(std::move(zarcanum_sig())); } else { - // old fashioned tx non-hidden amounts PoS scheme + // old fashioned non-hidden amount direct spend PoS scheme txin_to_key stake_input; stake_input.amount = pe.amount; stake_input.key_offsets.push_back(pe.g_index); From 088ea83808891eef44d22ac0027de2f17ecfbf34 Mon Sep 17 00:00:00 2001 From: sowle Date: Sun, 16 Oct 2022 03:13:03 +0200 Subject: [PATCH 4/7] miner improvements on PoS block validation --- src/currency_core/blockchain_storage.cpp | 13 +++++++------ src/currency_core/blockchain_storage.h | 2 +- src/currency_core/currency_format_utils.cpp | 15 ++++++++------- src/currency_core/currency_format_utils.h | 2 +- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 12c69b0f..0cbe66a9 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -4552,7 +4552,7 @@ struct outputs_visitor //check tx unlock time uint64_t source_out_unlock_time = get_tx_unlock_time(source_tx, out_i); //let coinbase sources for PoS block to have locked inputs, the outputs supposed to be locked same way, except the reward - if (is_coinbase(validated_tx) && is_pos_block(validated_tx)) // @#@ consider changing to one call to is_pos_coinbase() + if (is_coinbase(validated_tx) && is_pos_miner_tx(validated_tx)) // @#@ consider changing to one call to is_pos_coinbase() { CHECK_AND_ASSERT_MES(should_unlock_value_be_treated_as_block_height(source_out_unlock_time), false, "source output #" << out_i << " is locked by time, not by height, which is not allowed for PoS coinbase"); if (source_out_unlock_time > m_source_max_unlock_time_for_pos_coinbase) @@ -5374,7 +5374,7 @@ bool blockchain_storage::validate_pos_block(const block& b, wide_difficulty_type basic_diff, uint64_t& amount, wide_difficulty_type& final_diff, - crypto::hash& proof_hash, + crypto::hash& kernel_hash, const crypto::hash& id, bool for_altchain, const alt_chain_type& alt_chain, @@ -5415,7 +5415,7 @@ bool blockchain_storage::validate_pos_block(const block& b, CHECK_AND_ASSERT_MES(r, false, "failed to build_stake_modifier"); r = build_kernel(stake_key_image, sk, sm, b.timestamp); CHECK_AND_ASSERT_MES(r, false, "failed to build kernel_stake"); - proof_hash = crypto::cn_fast_hash(&sk, sizeof(sk)); + kernel_hash = crypto::cn_fast_hash(&sk, sizeof(sk)); if (is_hardfork_active(ZANO_HARDFORK_04_ZARCANUM)) { @@ -5424,6 +5424,7 @@ bool blockchain_storage::validate_pos_block(const block& b, else { // old PoS non-hidden amount scheme + CHECK_AND_ASSERT_MES(b.miner_tx.version <= TRANSACTION_VERSION_PRE_HF4, false, "PoS miner tx has incorrect version: " << b.miner_tx.version); CHECK_AND_ASSERT_MES(b.miner_tx.vin[1].type() == typeid(txin_to_key), false, "incorrect input 1 type: " << b.miner_tx.vin[1].type().name() << ", txin_to_key expected"); const txin_to_key& intk = boost::get(b.miner_tx.vin[1]); amount = intk.amount; @@ -5435,16 +5436,16 @@ bool blockchain_storage::validate_pos_block(const block& b, LOG_PRINT_L2("STAKE KERNEL for bl ID: " << get_block_hash(b) << ENDL << print_stake_kernel_info(sk) << "amount: " << print_money(amount) << ENDL - << "kernel_hash: " << proof_hash); + << "kernel_hash: " << kernel_hash); final_diff = basic_diff / amount; - if (!check_hash(proof_hash, final_diff)) + if (!check_hash(kernel_hash, final_diff)) { LOG_ERROR("PoS difficulty check failed for block " << get_block_hash(b) << " @ HEIGHT " << get_block_height(b) << ":" << ENDL << " basic_diff: " << basic_diff << ENDL << " final_diff: " << final_diff << ENDL << " amount: " << print_money_brief(amount) << ENDL - << " kernel_hash: " << proof_hash << ENDL + << " kernel_hash: " << kernel_hash << ENDL ); return false; } diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index 8916d8f0..4cb3d9cd 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -352,7 +352,7 @@ namespace currency wide_difficulty_type basic_diff, uint64_t& amount, wide_difficulty_type& final_diff, - crypto::hash& proof_hash, + crypto::hash& kernel_hash, const crypto::hash& id, bool for_altchain, const alt_chain_type& alt_chain = alt_chain_type(), diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 4cf330cf..1331d4ab 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -189,7 +189,6 @@ namespace currency const pos_entry& pe) { bool r = false; - CHECK_AND_ASSERT_THROW_MES(!pos || tx_version <= TRANSACTION_VERSION_PRE_HF4, "PoS miner tx is currently unsupported for HF4 -- sowle"); uint64_t block_reward = 0; if (!get_block_reward(pos, median_size, current_block_size, already_generated_coins, block_reward, height)) @@ -271,10 +270,10 @@ namespace currency if (tx.version > TRANSACTION_VERSION_PRE_HF4 /* && stake is zarcanum */) { // TODO: add Zarcanum part - txin_zc_input stake_input; + //txin_zc_input stake_input = AUTO_VAL_INIT(stake_input); //stake_input.key_offsets.push_back(pe.g_index); - stake_input.k_image = pe.keyimage; - tx.vin.emplace_back(std::move(stake_input)); + //stake_input.k_image = pe.keyimage; + tx.vin.emplace_back(std::move(txin_zc_input())); //reserve place for ring signature tx.signatures.emplace_back(std::move(zarcanum_sig())); } @@ -3579,17 +3578,19 @@ namespace currency { if (!(b.flags & CURRENCY_BLOCK_FLAG_POS_BLOCK)) return false; - return is_pos_block(b.miner_tx); + return is_pos_miner_tx(b.miner_tx); } //--------------------------------------------------------------- - bool is_pos_block(const transaction& tx) + bool is_pos_miner_tx(const transaction& tx) { if (tx.vin.size() == 2 && tx.vin[0].type() == typeid(txin_gen) && - tx.vin[1].type() == typeid(txin_to_key)) + (tx.vin[1].type() == typeid(txin_to_key) || + tx.vin[1].type() == typeid(txin_zc_input))) return true; return false; } + //--------------------------------------------------------------- size_t get_max_block_size() { return CURRENCY_MAX_BLOCK_SIZE; diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index 1fcf9107..54a6b983 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -385,7 +385,7 @@ namespace currency //PoS bool is_pos_block(const block& b); - bool is_pos_block(const transaction& tx); + bool is_pos_miner_tx(const transaction& tx); wide_difficulty_type correct_difficulty_with_sequence_factor(size_t sequence_factor, wide_difficulty_type diff); void print_currency_details(); std::string print_reward_change_first_blocks(size_t n_of_first_blocks); From 6810a656618d1c606e6d5b2c8da6a5f33d16cf98 Mon Sep 17 00:00:00 2001 From: sowle Date: Sun, 16 Oct 2022 03:17:18 +0200 Subject: [PATCH 5/7] the first Zarcanum PoS block generated successfully, but yet to be verified by the core --- src/crypto/zarcanum.cpp | 31 +++++----- src/crypto/zarcanum.h | 6 +- src/wallet/wallet2.cpp | 129 ++++++++++++++++++++++++++++++++++++---- src/wallet/wallet2.h | 2 +- 4 files changed, 135 insertions(+), 33 deletions(-) diff --git a/src/crypto/zarcanum.cpp b/src/crypto/zarcanum.cpp index 29227c69..d9f1b39b 100644 --- a/src/crypto/zarcanum.cpp +++ b/src/crypto/zarcanum.cpp @@ -47,15 +47,14 @@ namespace crypto if (p_err) { *p_err = err_code; } return false; } - bool zarcanum_generate_proof(const hash& m, const hash& kernel_hash, const std::vector& ring, const point_t& pseudo_out_amount_commitment, - 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, + bool zarcanum_generate_proof(const hash& m, const hash& kernel_hash, const std::vector& ring, const point_t& pseudo_out_amount_commitment, + const scalar_t& last_pow_block_id_hashed, const key_image& stake_ki, + const scalar_t& secret_x, const scalar_t& secret_q, uint64_t secret_index, const scalar_t& pseudo_out_blinding_mask, uint64_t stake_amount, const scalar_t& stake_blinding_mask, zarcanum_proof& result, uint8_t* p_err /* = nullptr */) { 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 = stake_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; @@ -118,24 +117,21 @@ namespace crypto const scalar_vec_t masks2 = { bx }; // X component const std::vector E_1div8_vec_ptr = { &result.E }; - if (!bppe_gen>(values, masks, masks2, E_1div8_vec_ptr, result.E_range_proof, p_err)) - { - return false; - } + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(bppe_gen>(values, masks, masks2, E_1div8_vec_ptr, result.E_range_proof), 10); // = four-layers ring signature data outline = // (j in [0, ring_size-1]) // layer 0 ring - // se.outputs[j].stealth_address; + // A[j] ( = ring[j].stealth_address) // layer 0 secret (with respect to G) - // in_contexts[i].in_ephemeral.sec; + // secret_x // layer 0 linkability - // in.k_image; + // stake_ki // // layer 1 ring - // crypto::point_t(se.outputs[j].amount_commitment) - pseudo_out_amount_commitment; + // ring[j].amount_commitment - pseudo_out_amount_commitment // layer 1 secret (with respect to G) - // se.real_out_amount_blinding_mask - blinding_mask; + // stake_blinding_mask - pseudo_out_blinding_mask // // additional layers for Zarcanum: // @@ -148,8 +144,13 @@ namespace crypto // Q[j] // layer 3 secret (with respect to G) // secret_q + TRY_ENTRY() + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(generate_CLSAG_GGXG(m, ring, pseudo_out_amount_commitment, C, stake_ki, + secret_x, stake_blinding_mask - pseudo_out_blinding_mask, x0, secret_q, secret_index, + result.clsag_ggxg), 20); + CATCH_ENTRY2(false); - return true; + return true; } diff --git a/src/crypto/zarcanum.h b/src/crypto/zarcanum.h index b59b4b0f..9d19ce5b 100644 --- a/src/crypto/zarcanum.h +++ b/src/crypto/zarcanum.h @@ -45,11 +45,9 @@ namespace crypto }; bool zarcanum_generate_proof(const hash& m, const hash& kernel_hash, const std::vector& ring, const point_t& pseudo_out_amount_commitment, - 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, + const scalar_t& last_pow_block_id_hashed, const key_image& stake_ki, + const scalar_t& secret_x, const scalar_t& secret_q, uint64_t secret_index, const scalar_t& pseudo_out_blinding_mask, uint64_t stake_amount, const scalar_t& stake_blinding_mask, 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); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 75e8368a..029e97d8 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019 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 @@ -3653,6 +3653,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, currency::bl WLT_CHECK_AND_ASSERT_MES(pe.wallet_index < m_transfers.size(), false, "invalid pe.wallet_index: " << pe.wallet_index); const transfer_details& td = m_transfers[pe.wallet_index]; const transaction& source_tx = td.m_ptx_wallet_info->m_tx; + const crypto::public_key source_tx_pub_key = get_tx_pub_key_from_extra(source_tx); WLT_CHECK_AND_ASSERT_MES(pe.tx_out_index < source_tx.vout.size(), false, "invalid pe.tx_out_index: " << pe.tx_out_index); const currency::tx_out_v& stake_out_v = source_tx.vout[pe.tx_out_index]; if (!cxt.zarcanum) @@ -3670,13 +3671,11 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, currency::bl //derive secret key crypto::key_derivation pos_coin_derivation = AUTO_VAL_INIT(pos_coin_derivation); - bool r = crypto::generate_key_derivation(get_tx_pub_key_from_extra(source_tx), + bool r = crypto::generate_key_derivation(source_tx_pub_key, 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(" - << pe.tx_id - << ", view secret key: " << m_account.get_keys().view_secret_key << ")"); + WLT_CHECK_AND_ASSERT_MES(r, false, "generate_key_derivation failed, pe.tx_id: " << pe.tx_id); crypto::secret_key derived_secret_ephemeral_key = AUTO_VAL_INIT(derived_secret_ephemeral_key); crypto::derive_secret_key(pos_coin_derivation, @@ -3709,8 +3708,113 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, currency::bl } // Zarcanum - WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(false, "ZRCANUM BLOCKS NOT IMPLEMENTED YET"); - return false; // to get rid of warning + + WLT_CHECK_AND_ASSERT_MES(td.is_zc(), false, "the transfer [" << pe.wallet_index << "] is not zc type, which is required for zarcanum"); + 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_zc_input), false, "Wrong input 1 type in transaction: " << b.miner_tx.vin[1].type().name()); + WLT_CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1 && b.miner_tx.signatures[0].type() == typeid(zarcanum_sig), false, "wrong sig prepared in a PoS block"); + WLT_CHECK_AND_ASSERT_MES(stake_out_v.type() == typeid(tx_out_zarcanum), false, "unexpected stake output type: " << stake_out_v.type().name() << ", expected: tx_out_zarcanum"); + + zarcanum_sig& sig = boost::get(b.miner_tx.signatures[0]); + txin_zc_input& stake_input = boost::get(b.miner_tx.vin[1]); + const tx_out_zarcanum& stake_out = boost::get(stake_out_v); + + COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response decoys_resp = AUTO_VAL_INIT(decoys_resp); + std::vector ring; + uint64_t secret_index = 0; // index of the real stake output + + // get decoys outputs and construct miner tx + static size_t required_decoys_count = 8; // TODO @#@# set them somewhere else + static bool use_only_forced_to_mix = false; // TODO @#@# set them somewhere else + if (required_decoys_count > 0) + { + COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request decoys_req = AUTO_VAL_INIT(decoys_req); + decoys_req.height_upper_limit = m_last_pow_block_h; // request decoys to be either older than, or the same age as stake output's height + decoys_req.use_forced_mix_outs = use_only_forced_to_mix; + decoys_req.decoys_count = required_decoys_count + 1; // one more to be able to skip a decoy in case it hits the real output + decoys_req.amounts.push_back(0); // request one batch of decoys for hidden amounts + + r = m_core_proxy->call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS(decoys_req, decoys_resp); + // TODO @#@# do we need these exceptions? + THROW_IF_FALSE_WALLET_EX(r, error::no_connection_to_daemon, "getrandom_outs.bin"); + THROW_IF_FALSE_WALLET_EX(decoys_resp.status != API_RETURN_CODE_BUSY, error::daemon_busy, "getrandom_outs.bin"); + THROW_IF_FALSE_WALLET_EX(decoys_resp.status == API_RETURN_CODE_OK, error::get_random_outs_error, decoys_resp.status); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(decoys_resp.outs.size() == 1, "got wrong number of decoys batches: " << decoys_resp.outs.size()); + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(decoys_resp.outs[0].outs.size() == required_decoys_count + 1, "for PoS stake tx got less decoys to mix than requested: " << decoys_resp.outs[0].outs.size() << " < " << required_decoys_count + 1); + + auto& decoys = decoys_resp.outs[0].outs; + std::unordered_set used_gindices{ td.m_global_output_index }; + size_t good_decoys_count = 0; + for(auto it = decoys.begin(); it != decoys.end(); ) + { + if (used_gindices.count(it->global_amount_index) != 0) + { + it = decoys.erase(it); + continue; + } + used_gindices.insert(it->global_amount_index); + if (++good_decoys_count == required_decoys_count) + { + decoys.erase(++it, decoys.end()); + break; + } + ++it; + } + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(decoys.size() == required_decoys_count, "for PoS stake got less good decoys than required: " << decoys.size() << " < " << required_decoys_count); + + secret_index = crypto::rand() % (decoys.size()); + uint64_t i = 0; + for(auto& el : decoys) + { + if (i++ == secret_index) + { + ring.emplace_back(stake_out.stealth_address, stake_out.amount_commitment, stake_out.concealing_point); + stake_input.key_offsets.push_back(td.m_global_output_index); + } + ring.emplace_back(el.stealth_address, el.amount_commitment, el.concealing_point); + stake_input.key_offsets.push_back(el.global_amount_index); + } + if (i == secret_index) + { + ring.emplace_back(stake_out.stealth_address, stake_out.amount_commitment, stake_out.concealing_point); + stake_input.key_offsets.push_back(td.m_global_output_index); + } + stake_input.key_offsets = absolute_output_offsets_to_relative(stake_input.key_offsets); + } + else + { + // no decoys, the ring consist of one element -- the real stake output + ring.emplace_back(stake_out.stealth_address, stake_out.amount_commitment, stake_out.concealing_point); + stake_input.key_offsets.push_back(td.m_global_output_index); + } + stake_input.k_image = pe.keyimage; + + #ifndef NDEBUG + { + crypto::point_t source_amount_commitment = crypto::c_scalar_1div8 * td.m_amount * crypto::c_point_H + crypto::c_scalar_1div8 * *td.m_opt_blinding_mask * crypto::c_point_G; + CHECK_AND_ASSERT_MES(stake_out.amount_commitment == source_amount_commitment.to_public_key(), false, "real output amount commitment check failed"); + } + #endif + + crypto::scalar_t pseudo_out_blinding_mask = crypto::scalar_t::random(); + crypto::point_t pseudo_out_amount_commitment = td.m_amount * crypto::c_point_H + pseudo_out_blinding_mask * crypto::c_point_G; + sig.pseudo_out_amount_commitment = (crypto::c_scalar_1div8 * pseudo_out_amount_commitment).to_public_key(); + + crypto::hash tx_hash_for_sig = get_transaction_hash(b.miner_tx); + + crypto::key_derivation derivation = AUTO_VAL_INIT(derivation); + r = crypto::generate_key_derivation(source_tx_pub_key, m_account.get_keys().view_secret_key, derivation); + WLT_CHECK_AND_ASSERT_MES(r, false, "generate_key_derivation failed, tid: " << pe.wallet_index << ", pe.tx_id: " << pe.tx_id); + crypto::secret_key secret_x = AUTO_VAL_INIT(secret_x); + crypto::derive_secret_key(derivation, pe.tx_out_index, m_account.get_keys().spend_secret_key, secret_x); + + uint8_t err = 0; + r = crypto::zarcanum_generate_proof(tx_hash_for_sig, cxt.kernel_hash, ring, pseudo_out_amount_commitment, cxt.last_pow_block_id_hashed, + pe.keyimage, secret_x, cxt.secret_q, secret_index, pseudo_out_blinding_mask, td.m_amount, *td.m_opt_blinding_mask, + static_cast(sig), &err); + WLT_CHECK_AND_ASSERT_MES(r, false, "zarcanum_generate_proof failed, err: " << (int)err); + + return true; } //------------------------------------------------------------------ bool wallet2::fill_mining_context(mining_context& ctx) @@ -3801,10 +3905,9 @@ bool wallet2::do_pos_mining_iteration(mining_context& context, size_t transfer_i // update stake kernel and calculate it's hash context.sk.block_timestamp = ts; - crypto::hash kernel_hash; { PROFILE_FUNC("calc_hash"); - kernel_hash = crypto::cn_fast_hash(&context.sk, sizeof(context.sk)); + context.kernel_hash = crypto::cn_fast_hash(&context.sk, sizeof(context.sk)); } const uint64_t stake_amount = td.amount(); @@ -3816,7 +3919,7 @@ bool wallet2::do_pos_mining_iteration(mining_context& context, size_t transfer_i 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); + found = crypto::zarcanum_check_main_pos_inequality(context.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) @@ -3826,7 +3929,7 @@ bool wallet2::do_pos_mining_iteration(mining_context& context, size_t transfer_i << "difficulty: " << context.basic_diff << ENDL << "kernel info: " << ENDL << print_stake_kernel_info(context.sk) - << "kernel_hash: " << kernel_hash << ENDL + << "kernel_hash: " << context.kernel_hash << ENDL << "lhs: " << lhs << ENDL << "rhs: " << rhs , LOG_LEVEL_0); @@ -3839,7 +3942,7 @@ bool wallet2::do_pos_mining_iteration(mining_context& context, size_t transfer_i currency::wide_difficulty_type final_diff = context.basic_diff / stake_amount; { PROFILE_FUNC("check_hash"); - found = currency::check_hash(kernel_hash, final_diff); + found = currency::check_hash(context.kernel_hash, final_diff); ++context.iterations_processed; } if (found) @@ -3848,7 +3951,7 @@ bool wallet2::do_pos_mining_iteration(mining_context& context, size_t transfer_i << "difficulty: " << context.basic_diff << ", final_diff: " << final_diff << ENDL << "kernel info: " << ENDL << print_stake_kernel_info(context.sk) - << "kernel_hash(proof): " << kernel_hash, + << "kernel_hash(proof): " << context.kernel_hash, LOG_LEVEL_0); } } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 16796983..7a05c0ad 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020 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 From 73a8f57f84b4e8f6f39db9047c4c3fb8a822673e Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Sun, 16 Oct 2022 14:44:45 +0200 Subject: [PATCH 6/7] test for validatiing n-outputs against hardfork 4 --- src/currency_core/currency_config.h | 1 + tests/core_tests/chaingen_main.cpp | 10 +---- tests/core_tests/zarcanum_test.cpp | 62 +++++++++++++++++++++++++++++ tests/core_tests/zarcanum_test.h | 8 ++++ 4 files changed, 73 insertions(+), 8 deletions(-) diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index ebe69442..5318bc33 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -30,6 +30,7 @@ #define CURRENT_TRANSACTION_VERSION 2 #define TRANSACTION_VERSION_INITAL 0 #define TRANSACTION_VERSION_PRE_HF4 1 +#define TRANSACTION_VERSION_POST_HF4 2 #define HF1_BLOCK_MAJOR_VERSION 1 #define HF3_BLOCK_MAJOR_VERSION 2 #define CURRENT_BLOCK_MAJOR_VERSION 3 diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 7086798f..129198f9 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -1061,14 +1061,8 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(zarcanum_basic_test); - //stop_on_first_fail = true; - //for (size_t i = 0; i != 100; i++) - //{ - multiassets_basic_test::ts_starter = 0; - GENERATE_AND_PLAY(multiassets_basic_test); - //} - - + GENERATE_AND_PLAY(multiassets_basic_test); + GENERATE_AND_PLAY(zarcanum_test_n_inputs_validation); // GENERATE_AND_PLAY(gen_block_reward); // END OF TESTS */ diff --git a/tests/core_tests/zarcanum_test.cpp b/tests/core_tests/zarcanum_test.cpp index 7ce373d5..ffad0c0b 100644 --- a/tests/core_tests/zarcanum_test.cpp +++ b/tests/core_tests/zarcanum_test.cpp @@ -8,6 +8,8 @@ #include "wallet_test_core_proxy.h" #include "random_helper.h" +#include "tx_builder.h" + #define AMOUNT_TO_TRANSFER_ZARCANUM_BASIC (TESTS_DEFAULT_FEE*10) @@ -52,6 +54,7 @@ bool zarcanum_basic_test::c1(currency::core& c, size_t ev_index, const std::vect account_base alice_acc; alice_acc.generate(); std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, alice_acc); + //pass over hardfork r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 2); @@ -165,3 +168,62 @@ bool zarcanum_basic_test::c1(currency::core& c, size_t ev_index, const std::vect return true; } + + + +zarcanum_test_n_inputs_validation::zarcanum_test_n_inputs_validation() +{ + REGISTER_CALLBACK_METHOD(zarcanum_basic_test, configure_core); + + m_hardforks.set_hardfork_height(1, 1); + m_hardforks.set_hardfork_height(2, 1); + m_hardforks.set_hardfork_height(3, 1); + m_hardforks.set_hardfork_height(4, 12); +} + + +bool zarcanum_test_n_inputs_validation::generate(std::vector& events) const +{ + uint64_t ts_start = 1338224400; + + GENERATE_ACCOUNT(miner_account); + MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start); + REWIND_BLOCKS(events, blk_0r, blk_0, miner_account); + + std::vector sources; + std::vector destinations; + fill_tx_sources_and_destinations(events, blk_0r, miner_account, miner_account, MK_TEST_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations); + destinations.resize(1); + + tx_builder builder; + builder.step1_init(TRANSACTION_VERSION_PRE_HF4); + builder.step2_fill_inputs(miner_account.get_keys(), sources); + builder.step3_fill_outputs(destinations); + builder.step4_calc_hash(); + builder.step5_sign(sources); + +// DO_CALLBACK(events, "mark_invalid_tx"); + events.push_back(builder.m_tx); + + MAKE_NEXT_BLOCK_TX1(events, blk_11, blk_0r, miner_account, builder.m_tx); + REWIND_BLOCKS_N(events, blk_14, blk_11, miner_account, 4); + + + sources.clear(); + destinations.clear(); + fill_tx_sources_and_destinations(events, blk_0r, miner_account, miner_account, MK_TEST_COINS(1), TESTS_DEFAULT_FEE, 0, sources, destinations); + destinations.resize(1); + tx_builder builder2; + //TODO: implement configuring for zarcanum type outputs + builder2.step1_init(TRANSACTION_VERSION_POST_HF4); + builder2.step2_fill_inputs(miner_account.get_keys(), sources); + builder2.step3_fill_outputs(destinations); + builder2.step4_calc_hash(); + builder2.step5_sign(sources); + + DO_CALLBACK(events, "mark_invalid_tx"); + events.push_back(builder2.m_tx); + REWIND_BLOCKS_N(events, blk_16, blk_14, miner_account, 2); + + return true; +} \ No newline at end of file diff --git a/tests/core_tests/zarcanum_test.h b/tests/core_tests/zarcanum_test.h index a6e2b200..7a40dacf 100644 --- a/tests/core_tests/zarcanum_test.h +++ b/tests/core_tests/zarcanum_test.h @@ -14,3 +14,11 @@ struct zarcanum_basic_test : public wallet_test bool generate(std::vector& events) const; bool c1(currency::core& c, size_t ev_index, const std::vector& events); }; + +struct zarcanum_test_n_inputs_validation : public wallet_test +{ + zarcanum_test_n_inputs_validation(); + bool generate(std::vector& events) const; +}; + + From 76e628d63fb3ff59faa861a2a9db40fc2259f833 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Sun, 16 Oct 2022 14:46:02 +0200 Subject: [PATCH 7/7] disabled zarcanum_test_n_inputs_validation for zarcanum branch --- tests/core_tests/chaingen_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 129198f9..133234bc 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -1062,7 +1062,7 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(zarcanum_basic_test); GENERATE_AND_PLAY(multiassets_basic_test); - GENERATE_AND_PLAY(zarcanum_test_n_inputs_validation); + //GENERATE_AND_PLAY(zarcanum_test_n_inputs_validation); // GENERATE_AND_PLAY(gen_block_reward); // END OF TESTS */