From f0bbcb5f40ec37235578e10b7e05b763d8a22857 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 12 Oct 2022 18:02:22 +0200 Subject: [PATCH] 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;