diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index a622b08b..4cc1406a 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -10,7 +10,7 @@ #ifndef TESTNET #define CURRENCY_FORMATION_VERSION 84 #else -#define CURRENCY_FORMATION_VERSION 91 +#define CURRENCY_FORMATION_VERSION 90 #endif #define CURRENCY_GENESIS_NONCE (CURRENCY_FORMATION_VERSION + 101011010121) //bender's nightmare diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index ec20b07b..96f77c35 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -5881,14 +5881,17 @@ void wallet2::prefetch_global_indicies_if_needed(const std::vector& se } } //---------------------------------------------------------------------------------------------------- -bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vector& sources, const std::vector& selected_indicies) +bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector& sources, const std::vector& selected_indicies) { typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry out_entry; typedef currency::tx_source_entry::output_entry tx_output_entry; COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response daemon_resp = AUTO_VAL_INIT(daemon_resp); - if (fake_outputs_count) + //we should request even of fake_outputs_count == 0, since for for postzarcanum this era this param is redefined + //todo: remove if(true) block later if this code will be settled + if (true) { + size_t fake_outputs_count = fake_outputs_count_; uint64_t zarcanum_start_from = m_core_runtime_config.hard_forks.m_height_the_hardfork_n_active_after[ZANO_HARDFORK_04_ZARCANUM]; uint64_t current_size = m_chain.get_blockchain_current_size(); decoy_selection_generator zarcanum_decoy_set_generator; @@ -5899,8 +5902,7 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vectoris_zc()) { + if(this->is_auditable()) + continue; //Zarcanum era rdisttib.amount = 0; //generate distribution in Zarcanum hardfork THROW_IF_FALSE_WALLET_INT_ERR_EX(zarcanum_decoy_set_generator.is_initialized(), "zarcanum_decoy_set_generator are not initialized"); - rdisttib.offsets = zarcanum_decoy_set_generator.generate_distribution(fake_outputs_count); + rdisttib.offsets = zarcanum_decoy_set_generator.generate_distribution(m_core_runtime_config.hf4_minimum_mixins); + need_to_request = true; } else { @@ -5932,42 +5937,44 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vectorcall_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2(req, daemon_resp); - THROW_IF_FALSE_WALLET_EX(r, error::no_connection_to_daemon, "getrandom_outs2.bin"); - if(daemon_resp.status == API_RETURN_CODE_FAIL) + size_t attempt_count = 0; + while (true) { - if (attempt_count < 10) + daemon_resp = COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response(); + bool r = m_core_proxy->call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2(req, daemon_resp); + THROW_IF_FALSE_WALLET_EX(r, error::no_connection_to_daemon, "getrandom_outs2.bin"); + if (daemon_resp.status == API_RETURN_CODE_FAIL) { - attempt_count++; - continue; + if (attempt_count < 10) + { + attempt_count++; + continue; + } + else + { + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(daemon_resp.outs.size() == selected_indicies.size(), + "unable to exacute getrandom_outs.bin after 10 attempts with code API_RETURN_CODE_FAIL, there must be problems with mixins"); + } } - else + THROW_IF_FALSE_WALLET_EX(daemon_resp.status != API_RETURN_CODE_BUSY, error::daemon_busy, "getrandom_outs.bin"); + THROW_IF_FALSE_WALLET_EX(daemon_resp.status == API_RETURN_CODE_OK, error::get_random_outs_error, daemon_resp.status); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(daemon_resp.outs.size() == selected_indicies.size(), + "daemon returned wrong response for getrandom_outs.bin, wrong amounts count = " << daemon_resp.outs.size() << ", expected: " << selected_indicies.size()); + break; + } + + 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() < fake_outputs_count) { - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(daemon_resp.outs.size() == selected_indicies.size(), - "unable to exacute getrandom_outs.bin after 10 attempts with code API_RETURN_CODE_FAIL, there must be problems with mixins"); + scanty_outs.push_back(amount_outs); } } - THROW_IF_FALSE_WALLET_EX(daemon_resp.status != API_RETURN_CODE_BUSY, error::daemon_busy, "getrandom_outs.bin"); - THROW_IF_FALSE_WALLET_EX(daemon_resp.status == API_RETURN_CODE_OK, error::get_random_outs_error, daemon_resp.status); - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(daemon_resp.outs.size() == selected_indicies.size(), - "daemon returned wrong response for getrandom_outs.bin, wrong amounts count = " << daemon_resp.outs.size() << ", expected: " << selected_indicies.size()); - break; + THROW_IF_FALSE_WALLET_EX(scanty_outs.empty(), error::not_enough_outs_to_mix, scanty_outs, 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() < fake_outputs_count) - { - scanty_outs.push_back(amount_outs); - } - } - THROW_IF_FALSE_WALLET_EX(scanty_outs.empty(), error::not_enough_outs_to_mix, scanty_outs, fake_outputs_count); } //lets prefetch m_global_output_index for selected_indicies @@ -5985,6 +5992,12 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vectoris_auditable()) + fake_outputs_count = m_core_runtime_config.hf4_minimum_mixins; + + //paste mixin transaction if (daemon_resp.outs.size()) { @@ -6506,9 +6519,9 @@ bool wallet2::select_indices_for_transfer(assets_selection_context& needed_money return res; } //---------------------------------------------------------------------------------------------------- -uint64_t wallet2::select_indices_for_transfer(std::vector& selected_indexes, free_amounts_cache_type& found_free_amounts, uint64_t needed_money, uint64_t fake_outputs_count) +uint64_t wallet2::select_indices_for_transfer(std::vector& selected_indexes, free_amounts_cache_type& found_free_amounts, uint64_t needed_money, uint64_t fake_outputs_count_) { - WLT_LOG_GREEN("Selecting indices for transfer of " << print_money_brief(needed_money) << " with " << fake_outputs_count << " fake outs, found_free_amounts.size()=" << found_free_amounts.size() << "...", LOG_LEVEL_0); + WLT_LOG_GREEN("Selecting indices for transfer of " << print_money_brief(needed_money) << " with " << fake_outputs_count_ << " fake outs, found_free_amounts.size()=" << found_free_amounts.size() << "...", LOG_LEVEL_0); uint64_t found_money = 0; //uint64_t found_zc_input = false; std::string selected_amounts_str; @@ -6520,6 +6533,11 @@ uint64_t wallet2::select_indices_for_transfer(std::vector& selected_in it = --found_free_amounts.end(); WLT_CHECK_AND_ASSERT_MES(it->second.size(), 0, "internal error: empty found_free_amounts map"); } + uint64_t fake_outputs_count = fake_outputs_count_; + if (!this->is_auditable() && m_transfers[*it->second.begin()].is_zc()) + { + fake_outputs_count = m_core_runtime_config.hf4_minimum_mixins; + } if (is_transfer_ready_to_go(m_transfers[*it->second.begin()], fake_outputs_count)) { found_money += it->first; @@ -6582,7 +6600,13 @@ bool wallet2::prepare_free_transfers_cache(uint64_t fake_outputs_count) for (size_t i = 0; i < m_transfers.size(); ++i) { const transfer_details& td = m_transfers[i]; - if (is_transfer_able_to_go(td, fake_outputs_count)) + uint64_t fake_outputs_count_local = fake_outputs_count; + if (td.m_zc_info_ptr) + { + //zarcanum out, redefine fake_outputs_count + fake_outputs_count_local = this->is_auditable() ? 0 : CURRENCY_HF4_MANDATORY_DECOY_SET_SIZE; + } + if (is_transfer_able_to_go(td, fake_outputs_count_local)) { //@#@ m_found_free_amounts[td.get_asset_id()][td.amount()].insert(i); @@ -6978,7 +7002,7 @@ bool wallet2::prepare_transaction(construct_tx_param& ctp, currency::finalize_tx return true; } //---------------------------------------------------------------------------------------------------- -void wallet2::finalize_transaction(const currency::finalize_tx_param& ftp, currency::transaction& tx, crypto::secret_key& tx_key, bool broadcast_tx, bool store_tx_secret_key /* = true */) +void wallet2::finalize_transaction(currency::finalize_tx_param& ftp, currency::transaction& tx, crypto::secret_key& tx_key, bool broadcast_tx, bool store_tx_secret_key /* = true */) { currency::finalized_tx result = AUTO_VAL_INIT(result); result.tx = tx; @@ -6988,7 +7012,7 @@ void wallet2::finalize_transaction(const currency::finalize_tx_param& ftp, curre tx_key = result.one_time_key; } //---------------------------------------------------------------------------------------------------- -void wallet2::finalize_transaction(const currency::finalize_tx_param& ftp, currency::finalized_tx& result, bool broadcast_tx, bool store_tx_secret_key /* = true */) +void wallet2::finalize_transaction(currency::finalize_tx_param& ftp, currency::finalized_tx& result, bool broadcast_tx, bool store_tx_secret_key /* = true */) { // NOTE: if broadcast_tx == true callback rise_on_transfer2() may be called at the end of this function. // That callback may call balance(), so it's important to have all used/spending transfers @@ -6997,7 +7021,10 @@ void wallet2::finalize_transaction(const currency::finalize_tx_param& ftp, curre // broadcasting tx without secret key storing is forbidden to avoid lost key issues WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(!broadcast_tx || store_tx_secret_key, "finalize_tx is requested to broadcast a tx without storing the key"); - //TIME_MEASURE_START_MS(construct_tx_time); + //overide mixins count for hardfork 4 outputs + if (is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM)) + ftp.tx_outs_attr = m_core_runtime_config.hf4_minimum_mixins; + bool r = currency::construct_tx(m_account.get_keys(), ftp, result); //TIME_MEASURE_FINISH_MS(construct_tx_time); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 67154320..0caefca0 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -635,8 +635,8 @@ namespace tools bool prepare_transaction(construct_tx_param& ctp, currency::finalize_tx_param& ftp, const mode_separate_context& emode_separate = mode_separate_context()); - void finalize_transaction(const currency::finalize_tx_param& ftp, currency::transaction& tx, crypto::secret_key& tx_key, bool broadcast_tx, bool store_tx_secret_key = true); - void finalize_transaction(const currency::finalize_tx_param& ftp, currency::finalized_tx& result, bool broadcast_tx, bool store_tx_secret_key = true ); + void finalize_transaction(currency::finalize_tx_param& ftp, currency::transaction& tx, crypto::secret_key& tx_key, bool broadcast_tx, bool store_tx_secret_key = true); + void finalize_transaction(currency::finalize_tx_param& ftp, currency::finalized_tx& result, bool broadcast_tx, bool store_tx_secret_key = true ); std::string get_log_prefix() const { return m_log_prefix; } static uint64_t get_max_unlock_time_from_receive_indices(const currency::transaction& tx, const wallet_public::employed_tx_entries& td); diff --git a/utils/test_api_files/transfer.json b/utils/test_api_files/transfer.json new file mode 100644 index 00000000..a9ebbc16 --- /dev/null +++ b/utils/test_api_files/transfer.json @@ -0,0 +1,20 @@ +{ + "jsonrpc": "2.0", + "id": 0, + "method": "transfer", + "params": { + "destinations": [ + { + "amount": 1000000000, + "address": "ZxCkEgHf3ci8hgBfboZeCENaYrHBYZ1bLFi5cgWvn4WJLaxfgs4kqG6cJi9ai2zrXWSCpsvRXit14gKjeijx6YPC1zT8rneEf" + } + ], + "push_payer": true, + "hide_receiver": false, + "service_entries_permanent": false, + "fee": 1000000000000, + "mixin": 10, + "comment": "", + "service_entries": [] + } +} \ No newline at end of file