From 5b4a3e3a38f51e1fcd024bec7081b7e06a9d37ad Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 8 Dec 2023 20:41:47 +0100 Subject: [PATCH] get_random_outs_for_amounts2 in work --- src/currency_core/blockchain_storage.cpp | 75 ++++++++++++++++++++++++ src/currency_core/blockchain_storage.h | 1 + src/rpc/core_rpc_server.cpp | 11 ++++ src/rpc/core_rpc_server.h | 2 + src/rpc/core_rpc_server_commands_defs.h | 70 ++++++++++++++++++++++ 5 files changed, 159 insertions(+) diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index cc66cf69..55e46505 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -2660,6 +2660,81 @@ bool blockchain_storage::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDO return true; } //------------------------------------------------------------------ +bool blockchain_storage::get_random_outs_for_amounts2(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res)const +{ + CRITICAL_REGION_LOCAL(m_read_lock); + LOG_PRINT_L3("[get_random_outs_for_amounts] amounts: " << req.amounts.size()); + std::map amounts_to_up_index_limit_cache; + + for (size_t i = 0; i != req.amounts.size(); i++) + { + uint64_t amount = req.amounts[i].amount; + const std::list& offsets = req.amounts[i].offsets; + 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; + + uint64_t zc_hard_fork_after_h = m_core_runtime_config.hard_forks[ZANO_HARDFORK_04_ZARCANUM]; + for (auto it = offsets.begin(); it != offsets.end(); it++) + { + uint64_t target_height = + + } + + + + + uint64_t outs_container_size = m_db_outputs.get_item_size(amount); + if (!outs_container_size) + { + LOG_ERROR("COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS: not outs for amount " << amount << ", wallet should use some real outs when it lookup for some mix, so, at least one out for this amount should exist"); + continue;//actually this is strange situation, wallet should use some real outs when it lookup for some mix, so, at least one out for this amount should exist + } + //it is not good idea to use top fresh outs, because it increases possibility of transaction canceling on split + //lets find upper bound of not fresh outs + size_t up_index_limit = 0; + auto it_limit = amounts_to_up_index_limit_cache.find(amount); + if (it_limit == amounts_to_up_index_limit_cache.end()) + { + up_index_limit = find_end_of_allowed_index(amount); + amounts_to_up_index_limit_cache[up_index_limit]; + } + else + { + up_index_limit = it_limit->second; + } + + 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.decoys_count) + { + std::set used; + size_t try_count = 0; + for (uint64_t j = 0; j != req.decoys_count && try_count < up_index_limit;) + { + 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, 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.decoys_count) + { + LOG_PRINT_YELLOW("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", LOG_LEVEL_0); + } + } + 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.decoys_count, req.use_forced_mix_outs, req.height_upper_limit) ? 1 : 0; + LOG_PRINT_YELLOW("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", LOG_LEVEL_0); + } + } + return true; +} +//------------------------------------------------------------------ boost::multiprecision::uint128_t blockchain_storage::total_coins() const { CRITICAL_REGION_LOCAL(m_read_lock); diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index 124c61a0..7eb8aeb4 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -281,6 +281,7 @@ namespace currency bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp)const; bool handle_get_objects(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res)const; bool 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; + bool get_random_outs_for_amounts2(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res)const; bool get_backward_blocks_sizes(size_t from_height, std::vector& sz, size_t count)const; bool get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector& indexs)const; bool get_alias_info(const std::string& alias, extra_alias_entry_base& info)const; diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index eb5af1ac..69768792 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -384,6 +384,17 @@ namespace currency return true; } + bool core_rpc_server::on_get_random_outs2(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res, connection_context& cntx) + { + CHECK_CORE_READY(); + res.status = API_RETURN_CODE_FAIL; + if (!m_core.get_blockchain_storage().get_random_outs_for_amounts2(req, res)) + { + return true; + } + + res.status = API_RETURN_CODE_OK; + } //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& res, connection_context& cntx) { diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index b1e296fb..d88b20ff 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -49,6 +49,7 @@ namespace currency bool on_start_mining(const COMMAND_RPC_START_MINING::request& req, COMMAND_RPC_START_MINING::response& res, connection_context& cntx); bool on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res, connection_context& cntx); bool on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res, connection_context& cntx); + bool on_get_random_outs2(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res, connection_context& cntx); bool on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res, connection_context& cntx); bool on_set_maintainers_info(const COMMAND_RPC_SET_MAINTAINERS_INFO::request& req, COMMAND_RPC_SET_MAINTAINERS_INFO::response& res, connection_context& cntx); bool on_get_tx_pool(const COMMAND_RPC_GET_TX_POOL::request& req, COMMAND_RPC_GET_TX_POOL::response& res, connection_context& cntx); @@ -141,6 +142,7 @@ namespace currency MAP_JON_RPC ("get_all_pool_tx_list", on_get_all_pool_tx_list, COMMAND_RPC_GET_ALL_POOL_TX_LIST) MAP_JON_RPC ("get_pool_info", on_get_pool_info, COMMAND_RPC_GET_POOL_INFO) MAP_JON_RPC ("getrandom_outs", on_get_random_outs, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS) + MAP_JON_RPC ("getrandom_outs2", on_get_random_outs2, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2) MAP_JON_RPC ("get_votes", on_get_votes, COMMAND_RPC_GET_VOTES) //assets api MAP_JON_RPC ("get_asset_info", on_get_asset_info, COMMAND_RPC_GET_ASSET_INFO) diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 450a1a8f..a0cfbdf8 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -422,6 +422,76 @@ namespace currency }; }; + + //----------------------------------------------- + struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2 + { + struct offsets_distribution + { + uint64_t amount; //if amount is 0 then lookup in post-zarcanum zone only, if not 0 then pre-zarcanum only + std::list offsets; //[i] = height, estimated location where to pickup output of transaction + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(amount) + KV_SERIALIZE(offsets) + END_KV_SERIALIZE_MAP() + }; + + + struct request + { + std::list amounts; + uint64_t height_upper_limit; // if nonzero, 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(decoys_count) + KV_SERIALIZE(height_upper_limit) + KV_SERIALIZE(use_forced_mix_outs) + END_KV_SERIALIZE_MAP() + }; + +#pragma pack (push, 1) + struct out_entry + { + out_entry() = default; + out_entry(uint64_t global_amount_index, const crypto::public_key& stealth_address) + : global_amount_index(global_amount_index), stealth_address(stealth_address), concealing_point{}, amount_commitment{}, blinded_asset_id{} + {} + out_entry(uint64_t global_amount_index, const crypto::public_key& stealth_address, const crypto::public_key& amount_commitment, const crypto::public_key& concealing_point, const crypto::public_key& blinded_asset_id) + : global_amount_index(global_amount_index), stealth_address(stealth_address), concealing_point(concealing_point), amount_commitment(amount_commitment), blinded_asset_id(blinded_asset_id) + {} + uint64_t global_amount_index; + crypto::public_key stealth_address; + crypto::public_key concealing_point; // premultiplied by 1/8 + crypto::public_key amount_commitment; // premultiplied by 1/8 + crypto::public_key blinded_asset_id; // premultiplied by 1/8 + }; +#pragma pack(pop) + + struct outs_for_amount + { + uint64_t amount; + std::list outs; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(amount) + KV_SERIALIZE_CONTAINER_POD_AS_BLOB(outs) + END_KV_SERIALIZE_MAP() + }; + + struct response + { + std::vector outs; + std::string status; + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(outs) + KV_SERIALIZE(status) + END_KV_SERIALIZE_MAP() + }; + }; + + //----------------------------------------------- struct COMMAND_RPC_SET_MAINTAINERS_INFO {