aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/blockchain_db/blockchain_db.h7
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp23
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.h7
-rw-r--r--src/cryptonote_core/blockchain.cpp4
-rw-r--r--src/cryptonote_core/blockchain.h3
-rw-r--r--src/rpc/core_rpc_server.cpp2
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h2
-rw-r--r--src/wallet/wallet2.cpp9
-rw-r--r--src/wallet/wallet2.h2
9 files changed, 41 insertions, 18 deletions
diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h
index ab5d2d44c..4c2157a39 100644
--- a/src/blockchain_db/blockchain_db.h
+++ b/src/blockchain_db/blockchain_db.h
@@ -1140,7 +1140,7 @@ public:
*
* @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
@@ -1153,7 +1153,7 @@ public:
* @param offsets a list of amount-specific output indices
* @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
@@ -1305,10 +1305,11 @@ public:
* @brief return a histogram of outputs on the blockchain
*
* @param amounts optional set of amounts to lookup
+ * @param unlocked whether to restrict count to unlocked outputs
*
* @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?
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index 2cd3943e9..4f1e84a04 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -1945,7 +1945,7 @@ tx_out_index BlockchainLMDB::get_output_tx_and_index_from_global(const uint64_t&
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__);
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);
}
-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__);
check_open();
@@ -2586,7 +2586,7 @@ void BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, const std::
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__);
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();
return histogram;
diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h
index d7a78617e..d60701bbe 100644
--- a/src/blockchain_db/lmdb/db_lmdb.h
+++ b/src/blockchain_db/lmdb/db_lmdb.h
@@ -224,8 +224,8 @@ public:
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;
- virtual tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index);
- virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<tx_out_index> &indices);
+ 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) 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
*
* @param amounts optional set of amounts to lookup
+ * @param unlocked whether to restrict count to unlocked outputs
*
* @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:
void do_resize(uint64_t size_increase=0);
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index d332f8997..36a233ee7 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -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);
}
-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()
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index 21086d578..903e0096b 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -688,10 +688,11 @@ namespace cryptonote
* @brief return a histogram of outputs on the blockchain
*
* @param amounts optional set of amounts to lookup
+ * @param unlocked whether to restrict instances to unlocked ones
*
* @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
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 166d1ba94..90f7a8434 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -1126,7 +1126,7 @@ namespace cryptonote
std::map<uint64_t, uint64_t> histogram;
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)
{
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 63167e249..89370a035 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -1071,11 +1071,13 @@ namespace cryptonote
std::vector<uint64_t> amounts;
uint64_t min_count;
uint64_t max_count;
+ bool unlocked;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(amounts);
KV_SERIALIZE(min_count);
KV_SERIALIZE(max_count);
+ KV_SERIALIZE(unlocked);
END_KV_SERIALIZE_MAP()
};
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 43dedaf82..502d64c9c 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -2238,7 +2238,7 @@ uint64_t wallet2::sanitize_fee_multiplier(uint64_t fee_multiplier) const
// 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)
{
- 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);
@@ -3061,7 +3061,7 @@ std::vector<uint64_t> wallet2::get_unspent_amounts_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::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.min_count = count;
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);
m_daemon_rpc_mutex.unlock();
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)
{
// 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)
{
// 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)
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 62a3c5031..9ff6c4e21 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -383,7 +383,7 @@ namespace tools
std::string get_keys_file() 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_unmixable_outputs(bool trusted_daemon);
std::vector<size_t> select_available_mixable_outputs(bool trusted_daemon);