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:
moneromooo-monero 2016-08-01 22:16:00 +01:00
parent 0fbe9cfcdb
commit 1593553e03
No known key found for this signature in database
GPG key ID: 686F07454D6CEFC3
9 changed files with 41 additions and 18 deletions

View file

@ -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?

View file

@ -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;

View file

@ -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);

View file

@ -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()

View file

@ -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

View file

@ -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)
{ {

View file

@ -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()
}; };

View file

@ -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)

View file

@ -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);