new unlocked parameter to output_histogram
This constrains the number of instances of any amount to the unlocked ones (as defined by the default unlock time setting: outputs with non default unlock time are not considered, so may be counted as unlocked even if they are not actually unlocked).
This commit is contained in:
parent
0fbe9cfcdb
commit
1593553e03
9 changed files with 41 additions and 18 deletions
|
@ -1140,7 +1140,7 @@ public:
|
||||||
*
|
*
|
||||||
* @return the tx hash and output index
|
* @return the tx hash and output index
|
||||||
*/
|
*/
|
||||||
virtual tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index) = 0;
|
virtual tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief gets some outputs' tx hashes and indices
|
* @brief gets some outputs' tx hashes and indices
|
||||||
|
@ -1153,7 +1153,7 @@ public:
|
||||||
* @param offsets a list of amount-specific output indices
|
* @param offsets a list of amount-specific output indices
|
||||||
* @param indices return-by-reference a list of tx hashes and output indices (as pairs)
|
* @param indices return-by-reference a list of tx hashes and output indices (as pairs)
|
||||||
*/
|
*/
|
||||||
virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<tx_out_index> &indices) = 0;
|
virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<tx_out_index> &indices) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief gets outputs' data
|
* @brief gets outputs' data
|
||||||
|
@ -1305,10 +1305,11 @@ public:
|
||||||
* @brief return a histogram of outputs on the blockchain
|
* @brief return a histogram of outputs on the blockchain
|
||||||
*
|
*
|
||||||
* @param amounts optional set of amounts to lookup
|
* @param amounts optional set of amounts to lookup
|
||||||
|
* @param unlocked whether to restrict count to unlocked outputs
|
||||||
*
|
*
|
||||||
* @return a set of amount/instances
|
* @return a set of amount/instances
|
||||||
*/
|
*/
|
||||||
virtual std::map<uint64_t, uint64_t> get_output_histogram(const std::vector<uint64_t> &amounts) const = 0;
|
virtual std::map<uint64_t, uint64_t> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief is BlockchainDB in read-only mode?
|
* @brief is BlockchainDB in read-only mode?
|
||||||
|
|
|
@ -1945,7 +1945,7 @@ tx_out_index BlockchainLMDB::get_output_tx_and_index_from_global(const uint64_t&
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
tx_out_index BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, const uint64_t& index)
|
tx_out_index BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, const uint64_t& index) const
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||||
std::vector < uint64_t > offsets;
|
std::vector < uint64_t > offsets;
|
||||||
|
@ -2551,7 +2551,7 @@ void BlockchainLMDB::get_output_key(const uint64_t &amount, const std::vector<ui
|
||||||
LOG_PRINT_L3("db3: " << db3);
|
LOG_PRINT_L3("db3: " << db3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<tx_out_index> &indices)
|
void BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<tx_out_index> &indices) const
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||||
check_open();
|
check_open();
|
||||||
|
@ -2586,7 +2586,7 @@ void BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, const std::
|
||||||
LOG_PRINT_L3("db3: " << db3);
|
LOG_PRINT_L3("db3: " << db3);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<uint64_t, uint64_t> BlockchainLMDB::get_output_histogram(const std::vector<uint64_t> &amounts) const
|
std::map<uint64_t, uint64_t> BlockchainLMDB::get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked) const
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||||
check_open();
|
check_open();
|
||||||
|
@ -2638,6 +2638,23 @@ std::map<uint64_t, uint64_t> BlockchainLMDB::get_output_histogram(const std::vec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unlocked) {
|
||||||
|
const uint64_t blockchain_height = height();
|
||||||
|
for (auto i: histogram) {
|
||||||
|
uint64_t amount = i.first;
|
||||||
|
uint64_t num_elems = i.second;
|
||||||
|
while (num_elems > 0) {
|
||||||
|
const tx_out_index toi = get_output_tx_and_index(amount, num_elems - 1);
|
||||||
|
const uint64_t height = get_tx_block_height(toi.first);
|
||||||
|
if (height + CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE <= blockchain_height)
|
||||||
|
break;
|
||||||
|
--num_elems;
|
||||||
|
}
|
||||||
|
// modifying second does not invalidate the iterator
|
||||||
|
i.second = num_elems;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TXN_POSTFIX_RDONLY();
|
TXN_POSTFIX_RDONLY();
|
||||||
|
|
||||||
return histogram;
|
return histogram;
|
||||||
|
|
|
@ -224,8 +224,8 @@ public:
|
||||||
virtual void get_output_tx_and_index_from_global(const std::vector<uint64_t> &global_indices,
|
virtual void get_output_tx_and_index_from_global(const std::vector<uint64_t> &global_indices,
|
||||||
std::vector<tx_out_index> &tx_out_indices) const;
|
std::vector<tx_out_index> &tx_out_indices) const;
|
||||||
|
|
||||||
virtual tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index);
|
virtual tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index) const;
|
||||||
virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<tx_out_index> &indices);
|
virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<tx_out_index> &indices) const;
|
||||||
|
|
||||||
virtual std::vector<uint64_t> get_tx_amount_output_indices(const uint64_t tx_id) const;
|
virtual std::vector<uint64_t> get_tx_amount_output_indices(const uint64_t tx_id) const;
|
||||||
|
|
||||||
|
@ -263,10 +263,11 @@ public:
|
||||||
* @brief return a histogram of outputs on the blockchain
|
* @brief return a histogram of outputs on the blockchain
|
||||||
*
|
*
|
||||||
* @param amounts optional set of amounts to lookup
|
* @param amounts optional set of amounts to lookup
|
||||||
|
* @param unlocked whether to restrict count to unlocked outputs
|
||||||
*
|
*
|
||||||
* @return a set of amount/instances
|
* @return a set of amount/instances
|
||||||
*/
|
*/
|
||||||
std::map<uint64_t, uint64_t> get_output_histogram(const std::vector<uint64_t> &amounts) const;
|
std::map<uint64_t, uint64_t> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void do_resize(uint64_t size_increase=0);
|
void do_resize(uint64_t size_increase=0);
|
||||||
|
|
|
@ -3316,9 +3316,9 @@ bool Blockchain::get_hard_fork_voting_info(uint8_t version, uint32_t &window, ui
|
||||||
return m_hardfork->get_voting_info(version, window, votes, threshold, earliest_height, voting);
|
return m_hardfork->get_voting_info(version, window, votes, threshold, earliest_height, voting);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<uint64_t, uint64_t> Blockchain:: get_output_histogram(const std::vector<uint64_t> &amounts) const
|
std::map<uint64_t, uint64_t> Blockchain:: get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked) const
|
||||||
{
|
{
|
||||||
return m_db->get_output_histogram(amounts);
|
return m_db->get_output_histogram(amounts, unlocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Blockchain::load_compiled_in_block_hashes()
|
void Blockchain::load_compiled_in_block_hashes()
|
||||||
|
|
|
@ -688,10 +688,11 @@ namespace cryptonote
|
||||||
* @brief return a histogram of outputs on the blockchain
|
* @brief return a histogram of outputs on the blockchain
|
||||||
*
|
*
|
||||||
* @param amounts optional set of amounts to lookup
|
* @param amounts optional set of amounts to lookup
|
||||||
|
* @param unlocked whether to restrict instances to unlocked ones
|
||||||
*
|
*
|
||||||
* @return a set of amount/instances
|
* @return a set of amount/instances
|
||||||
*/
|
*/
|
||||||
std::map<uint64_t, uint64_t> get_output_histogram(const std::vector<uint64_t> &amounts) const;
|
std::map<uint64_t, uint64_t> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief perform a check on all key images in the blockchain
|
* @brief perform a check on all key images in the blockchain
|
||||||
|
|
|
@ -1126,7 +1126,7 @@ namespace cryptonote
|
||||||
std::map<uint64_t, uint64_t> histogram;
|
std::map<uint64_t, uint64_t> histogram;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
histogram = m_core.get_blockchain_storage().get_output_histogram(req.amounts);
|
histogram = m_core.get_blockchain_storage().get_output_histogram(req.amounts, req.unlocked);
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception &e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1071,11 +1071,13 @@ namespace cryptonote
|
||||||
std::vector<uint64_t> amounts;
|
std::vector<uint64_t> amounts;
|
||||||
uint64_t min_count;
|
uint64_t min_count;
|
||||||
uint64_t max_count;
|
uint64_t max_count;
|
||||||
|
bool unlocked;
|
||||||
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
KV_SERIALIZE(amounts);
|
KV_SERIALIZE(amounts);
|
||||||
KV_SERIALIZE(min_count);
|
KV_SERIALIZE(min_count);
|
||||||
KV_SERIALIZE(max_count);
|
KV_SERIALIZE(max_count);
|
||||||
|
KV_SERIALIZE(unlocked);
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2238,7 +2238,7 @@ uint64_t wallet2::sanitize_fee_multiplier(uint64_t fee_multiplier) const
|
||||||
// transactions will be required
|
// transactions will be required
|
||||||
std::vector<wallet2::pending_tx> wallet2::create_transactions(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint64_t fee_multiplier, const std::vector<uint8_t> extra, bool trusted_daemon)
|
std::vector<wallet2::pending_tx> wallet2::create_transactions(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint64_t fee_multiplier, const std::vector<uint8_t> extra, bool trusted_daemon)
|
||||||
{
|
{
|
||||||
const std::vector<size_t> unused_transfers_indices = select_available_outputs_from_histogram(fake_outs_count + 1, true, trusted_daemon);
|
const std::vector<size_t> unused_transfers_indices = select_available_outputs_from_histogram(fake_outs_count + 1, true, true, trusted_daemon);
|
||||||
|
|
||||||
fee_multiplier = sanitize_fee_multiplier(fee_multiplier);
|
fee_multiplier = sanitize_fee_multiplier(fee_multiplier);
|
||||||
|
|
||||||
|
@ -3061,7 +3061,7 @@ std::vector<uint64_t> wallet2::get_unspent_amounts_vector()
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
std::vector<size_t> wallet2::select_available_outputs_from_histogram(uint64_t count, bool atleast, bool trusted_daemon)
|
std::vector<size_t> wallet2::select_available_outputs_from_histogram(uint64_t count, bool atleast, bool unlocked, bool trusted_daemon)
|
||||||
{
|
{
|
||||||
epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::request> req_t = AUTO_VAL_INIT(req_t);
|
epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::request> req_t = AUTO_VAL_INIT(req_t);
|
||||||
epee::json_rpc::response<cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::response, std::string> resp_t = AUTO_VAL_INIT(resp_t);
|
epee::json_rpc::response<cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::response, std::string> resp_t = AUTO_VAL_INIT(resp_t);
|
||||||
|
@ -3073,6 +3073,7 @@ std::vector<size_t> wallet2::select_available_outputs_from_histogram(uint64_t co
|
||||||
req_t.params.amounts = get_unspent_amounts_vector();
|
req_t.params.amounts = get_unspent_amounts_vector();
|
||||||
req_t.params.min_count = count;
|
req_t.params.min_count = count;
|
||||||
req_t.params.max_count = 0;
|
req_t.params.max_count = 0;
|
||||||
|
req_t.params.unlocked = unlocked;
|
||||||
bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
|
bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
|
||||||
m_daemon_rpc_mutex.unlock();
|
m_daemon_rpc_mutex.unlock();
|
||||||
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "select_available_unmixable_outputs");
|
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "select_available_unmixable_outputs");
|
||||||
|
@ -3102,13 +3103,13 @@ std::vector<size_t> wallet2::select_available_outputs_from_histogram(uint64_t co
|
||||||
std::vector<size_t> wallet2::select_available_unmixable_outputs(bool trusted_daemon)
|
std::vector<size_t> wallet2::select_available_unmixable_outputs(bool trusted_daemon)
|
||||||
{
|
{
|
||||||
// request all outputs with less than 3 instances
|
// request all outputs with less than 3 instances
|
||||||
return select_available_outputs_from_histogram(3, false, trusted_daemon);
|
return select_available_outputs_from_histogram(3, false, true, trusted_daemon);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
std::vector<size_t> wallet2::select_available_mixable_outputs(bool trusted_daemon)
|
std::vector<size_t> wallet2::select_available_mixable_outputs(bool trusted_daemon)
|
||||||
{
|
{
|
||||||
// request all outputs with at least 3 instances, so we can use mixin 2 with
|
// request all outputs with at least 3 instances, so we can use mixin 2 with
|
||||||
return select_available_outputs_from_histogram(3, true, trusted_daemon);
|
return select_available_outputs_from_histogram(3, true, true, trusted_daemon);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
std::vector<wallet2::pending_tx> wallet2::create_unmixable_sweep_transactions(bool trusted_daemon)
|
std::vector<wallet2::pending_tx> wallet2::create_unmixable_sweep_transactions(bool trusted_daemon)
|
||||||
|
|
|
@ -383,7 +383,7 @@ namespace tools
|
||||||
std::string get_keys_file() const;
|
std::string get_keys_file() const;
|
||||||
std::string get_daemon_address() const;
|
std::string get_daemon_address() const;
|
||||||
|
|
||||||
std::vector<size_t> select_available_outputs_from_histogram(uint64_t count, bool atleast, bool trusted_daemon);
|
std::vector<size_t> select_available_outputs_from_histogram(uint64_t count, bool atleast, bool unlocked, bool trusted_daemon);
|
||||||
std::vector<size_t> select_available_outputs(const std::function<bool(const transfer_details &td)> &f);
|
std::vector<size_t> select_available_outputs(const std::function<bool(const transfer_details &td)> &f);
|
||||||
std::vector<size_t> select_available_unmixable_outputs(bool trusted_daemon);
|
std::vector<size_t> select_available_unmixable_outputs(bool trusted_daemon);
|
||||||
std::vector<size_t> select_available_mixable_outputs(bool trusted_daemon);
|
std::vector<size_t> select_available_mixable_outputs(bool trusted_daemon);
|
||||||
|
|
Loading…
Reference in a new issue