Merge pull request #6074
38f691048
simplewallet: plug a timing leak (moneromooo-monero)dcff02e4c
epee: allow a random component in once_a_time timeouts (moneromooo-monero)e10833024
wallet: reuse cached height when set after refresh (moneromooo-monero)5956beaa1
wallet2: fix is_synced checking target height, not height (moneromooo-monero)fd35e2304
wallet: fix another facet of "did I get some monero" information leak (moneromooo-monero)d5472bd87
wallet2: do not send an unnecessary last getblocks.bin call on refresh (moneromooo-monero)97ae7bb5c
wallet2: do not repeatedly ask for pool txes sent to us (moneromooo-monero)
This commit is contained in:
commit
06b0441762
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include <list>
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
#include <boost/timer/timer.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/random_generator.hpp>
|
||||
|
@ -230,7 +231,7 @@ namespace math_helper
|
|||
}
|
||||
|
||||
}
|
||||
template<uint64_t scale, int default_interval, bool start_immediate = true>
|
||||
template<typename get_interval, bool start_immediate = true>
|
||||
class once_a_time
|
||||
{
|
||||
uint64_t get_time() const
|
||||
|
@ -251,12 +252,18 @@ namespace math_helper
|
|||
#endif
|
||||
}
|
||||
|
||||
void set_next_interval()
|
||||
{
|
||||
m_interval = get_interval()();
|
||||
}
|
||||
|
||||
public:
|
||||
once_a_time():m_interval(default_interval * scale)
|
||||
once_a_time()
|
||||
{
|
||||
m_last_worked_time = 0;
|
||||
if(!start_immediate)
|
||||
m_last_worked_time = get_time();
|
||||
set_next_interval();
|
||||
}
|
||||
|
||||
void trigger()
|
||||
|
@ -273,6 +280,7 @@ namespace math_helper
|
|||
{
|
||||
bool res = functr();
|
||||
m_last_worked_time = get_time();
|
||||
set_next_interval();
|
||||
return res;
|
||||
}
|
||||
return true;
|
||||
|
@ -283,9 +291,13 @@ namespace math_helper
|
|||
uint64_t m_interval;
|
||||
};
|
||||
|
||||
template<uint64_t N> struct get_constant_interval { public: uint64_t operator()() const { return N; } };
|
||||
|
||||
template<int default_interval, bool start_immediate = true>
|
||||
class once_a_time_seconds: public once_a_time<1000000, default_interval, start_immediate> {};
|
||||
class once_a_time_seconds: public once_a_time<get_constant_interval<default_interval * (uint64_t)1000000>, start_immediate> {};
|
||||
template<int default_interval, bool start_immediate = true>
|
||||
class once_a_time_milliseconds: public once_a_time<1000, default_interval, start_immediate> {};
|
||||
class once_a_time_milliseconds: public once_a_time<get_constant_interval<default_interval * (uint64_t)1000>, start_immediate> {};
|
||||
template<typename get_interval, bool start_immediate = true>
|
||||
class once_a_time_seconds_range: public once_a_time<get_interval, start_immediate> {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8356,7 +8356,11 @@ bool simple_wallet::get_transfers(std::vector<std::string>& local_args, std::vec
|
|||
m_in_manual_refresh.store(true, std::memory_order_relaxed);
|
||||
epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){m_in_manual_refresh.store(false, std::memory_order_relaxed);});
|
||||
|
||||
m_wallet->update_pool_state();
|
||||
std::vector<std::pair<cryptonote::transaction, bool>> process_txs;
|
||||
m_wallet->update_pool_state(process_txs);
|
||||
if (!process_txs.empty())
|
||||
m_wallet->process_pool_state(process_txs);
|
||||
|
||||
std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>> payments;
|
||||
m_wallet->get_unconfirmed_payments(payments, m_current_subaddress_account, subaddr_indices);
|
||||
for (std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) {
|
||||
|
@ -8803,12 +8807,25 @@ void simple_wallet::check_for_messages()
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
void simple_wallet::wallet_idle_thread()
|
||||
{
|
||||
const boost::posix_time::ptime start_time = boost::posix_time::microsec_clock::universal_time();
|
||||
while (true)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(m_idle_mutex);
|
||||
if (!m_idle_run.load(std::memory_order_relaxed))
|
||||
break;
|
||||
|
||||
// if another thread was busy (ie, a foreground refresh thread), we'll end up here at
|
||||
// some random time that's not what we slept for, so we should not call refresh now
|
||||
// or we'll be leaking that fact through timing
|
||||
const boost::posix_time::ptime now0 = boost::posix_time::microsec_clock::universal_time();
|
||||
const uint64_t dt_actual = (now0 - start_time).total_microseconds() % 1000000;
|
||||
#ifdef _WIN32
|
||||
static const uint64_t threshold = 10000;
|
||||
#else
|
||||
static const uint64_t threshold = 2000;
|
||||
#endif
|
||||
if (dt_actual < threshold) // if less than a threshold... would a very slow machine always miss it ?
|
||||
{
|
||||
#ifndef _WIN32
|
||||
m_inactivity_checker.do_call(boost::bind(&simple_wallet::check_inactivity, this));
|
||||
#endif
|
||||
|
@ -8818,7 +8835,13 @@ void simple_wallet::wallet_idle_thread()
|
|||
|
||||
if (!m_idle_run.load(std::memory_order_relaxed))
|
||||
break;
|
||||
m_idle_cond.wait_for(lock, boost::chrono::seconds(1));
|
||||
}
|
||||
|
||||
// aim for the next multiple of 1 second
|
||||
const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
|
||||
const auto dt = (now - start_time).total_microseconds();
|
||||
const auto wait = 1000000 - dt % 1000000;
|
||||
m_idle_cond.wait_for(lock, boost::chrono::microseconds(wait));
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
@ -10002,7 +10025,11 @@ bool simple_wallet::show_transfer(const std::vector<std::string> &args)
|
|||
|
||||
try
|
||||
{
|
||||
m_wallet->update_pool_state();
|
||||
std::vector<std::pair<cryptonote::transaction, bool>> process_txs;
|
||||
m_wallet->update_pool_state(process_txs);
|
||||
if (!process_txs.empty())
|
||||
m_wallet->process_pool_state(process_txs);
|
||||
|
||||
std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>> pool_payments;
|
||||
m_wallet->get_unconfirmed_payments(pool_payments, m_current_subaddress_account);
|
||||
for (std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>>::const_iterator i = pool_payments.begin(); i != pool_payments.end(); ++i) {
|
||||
|
|
|
@ -448,10 +448,12 @@ namespace cryptonote
|
|||
std::atomic<bool> m_locked;
|
||||
std::atomic<bool> m_in_command;
|
||||
|
||||
template<uint64_t mini, uint64_t maxi> struct get_random_interval { public: uint64_t operator()() const { return crypto::rand_range(mini, maxi); } };
|
||||
|
||||
epee::math_helper::once_a_time_seconds<1> m_inactivity_checker;
|
||||
epee::math_helper::once_a_time_seconds<90> m_refresh_checker;
|
||||
epee::math_helper::once_a_time_seconds<90> m_mms_checker;
|
||||
epee::math_helper::once_a_time_seconds<90> m_rpc_payment_checker;
|
||||
epee::math_helper::once_a_time_seconds_range<get_random_interval<80 * 1000000, 100 * 1000000>> m_refresh_checker;
|
||||
epee::math_helper::once_a_time_seconds_range<get_random_interval<90 * 1000000, 110 * 1000000>> m_mms_checker;
|
||||
epee::math_helper::once_a_time_seconds_range<get_random_interval<90 * 1000000, 115 * 1000000>> m_rpc_payment_checker;
|
||||
|
||||
std::atomic<bool> m_need_payment;
|
||||
boost::posix_time::ptime m_last_rpc_payment_mining_time;
|
||||
|
|
|
@ -77,6 +77,7 @@ void NodeRPCProxy::invalidate()
|
|||
m_rpc_payment_seed_height = 0;
|
||||
m_rpc_payment_seed_hash = crypto::null_hash;
|
||||
m_rpc_payment_next_seed_hash = crypto::null_hash;
|
||||
m_height_time = 0;
|
||||
}
|
||||
|
||||
boost::optional<std::string> NodeRPCProxy::get_rpc_version(uint32_t &rpc_version)
|
||||
|
@ -101,6 +102,7 @@ boost::optional<std::string> NodeRPCProxy::get_rpc_version(uint32_t &rpc_version
|
|||
void NodeRPCProxy::set_height(uint64_t h)
|
||||
{
|
||||
m_height = h;
|
||||
m_height_time = time(NULL);
|
||||
}
|
||||
|
||||
boost::optional<std::string> NodeRPCProxy::get_info()
|
||||
|
@ -126,12 +128,20 @@ boost::optional<std::string> NodeRPCProxy::get_info()
|
|||
m_target_height = resp_t.target_height;
|
||||
m_block_weight_limit = resp_t.block_weight_limit ? resp_t.block_weight_limit : resp_t.block_size_limit;
|
||||
m_get_info_time = now;
|
||||
m_height_time = now;
|
||||
}
|
||||
return boost::optional<std::string>();
|
||||
}
|
||||
|
||||
boost::optional<std::string> NodeRPCProxy::get_height(uint64_t &height)
|
||||
{
|
||||
const time_t now = time(NULL);
|
||||
if (now < m_height_time + 30) // re-cache every 30 seconds
|
||||
{
|
||||
height = m_height;
|
||||
return boost::optional<std::string>();
|
||||
}
|
||||
|
||||
auto res = get_info();
|
||||
if (res)
|
||||
return res;
|
||||
|
|
|
@ -97,6 +97,7 @@ private:
|
|||
crypto::hash m_rpc_payment_seed_hash;
|
||||
crypto::hash m_rpc_payment_next_seed_hash;
|
||||
uint32_t m_rpc_payment_cookie;
|
||||
time_t m_height_time;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -2519,12 +2519,14 @@ void wallet2::parse_block_round(const cryptonote::blobdata &blob, cryptonote::bl
|
|||
error = !cryptonote::parse_and_validate_block_from_blob(blob, bl, bl_id);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::pull_blocks(uint64_t start_height, uint64_t &blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::vector<cryptonote::block_complete_entry> &blocks, std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> &o_indices)
|
||||
void wallet2::pull_blocks(uint64_t start_height, uint64_t &blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::vector<cryptonote::block_complete_entry> &blocks, std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> &o_indices, uint64_t ¤t_height)
|
||||
{
|
||||
cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::request req = AUTO_VAL_INIT(req);
|
||||
cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::response res = AUTO_VAL_INIT(res);
|
||||
req.block_ids = short_chain_history;
|
||||
|
||||
MDEBUG("Pulling blocks: start_height " << start_height);
|
||||
|
||||
req.prune = true;
|
||||
req.start_height = start_height;
|
||||
req.no_miner_tx = m_refresh_type == RefreshNoCoinbase;
|
||||
|
@ -2544,6 +2546,10 @@ void wallet2::pull_blocks(uint64_t start_height, uint64_t &blocks_start_height,
|
|||
blocks_start_height = res.start_height;
|
||||
blocks = std::move(res.blocks);
|
||||
o_indices = std::move(res.output_indices);
|
||||
current_height = res.current_height;
|
||||
|
||||
MDEBUG("Pulled blocks: blocks_start_height " << blocks_start_height << ", count " << blocks.size()
|
||||
<< ", height " << blocks_start_height + blocks.size() << ", node height " << res.current_height);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::pull_hashes(uint64_t start_height, uint64_t &blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::vector<crypto::hash> &hashes)
|
||||
|
@ -2726,9 +2732,10 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
|
|||
refresh(trusted_daemon, start_height, blocks_fetched, received_money);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::pull_and_parse_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, const std::vector<cryptonote::block_complete_entry> &prev_blocks, const std::vector<parsed_block> &prev_parsed_blocks, std::vector<cryptonote::block_complete_entry> &blocks, std::vector<parsed_block> &parsed_blocks, bool &error, std::exception_ptr &exception)
|
||||
void wallet2::pull_and_parse_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, const std::vector<cryptonote::block_complete_entry> &prev_blocks, const std::vector<parsed_block> &prev_parsed_blocks, std::vector<cryptonote::block_complete_entry> &blocks, std::vector<parsed_block> &parsed_blocks, bool &last, bool &error, std::exception_ptr &exception)
|
||||
{
|
||||
error = false;
|
||||
last = false;
|
||||
exception = NULL;
|
||||
|
||||
try
|
||||
|
@ -2746,7 +2753,8 @@ void wallet2::pull_and_parse_next_blocks(uint64_t start_height, uint64_t &blocks
|
|||
|
||||
// pull the new blocks
|
||||
std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> o_indices;
|
||||
pull_blocks(start_height, blocks_start_height, short_chain_history, blocks, o_indices);
|
||||
uint64_t current_height;
|
||||
pull_blocks(start_height, blocks_start_height, short_chain_history, blocks, o_indices, current_height);
|
||||
THROW_WALLET_EXCEPTION_IF(blocks.size() != o_indices.size(), error::wallet_internal_error, "Mismatched sizes of blocks and o_indices");
|
||||
|
||||
tools::threadpool& tpool = tools::threadpool::getInstance();
|
||||
|
@ -2784,6 +2792,7 @@ void wallet2::pull_and_parse_next_blocks(uint64_t start_height, uint64_t &blocks
|
|||
}
|
||||
}
|
||||
waiter.wait(&tpool);
|
||||
last = !blocks.empty() && cryptonote::get_block_height(parsed_blocks.back().block) + 1 == current_height;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -2820,7 +2829,7 @@ void wallet2::remove_obsolete_pool_txs(const std::vector<crypto::hash> &tx_hashe
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::update_pool_state(bool refreshed)
|
||||
void wallet2::update_pool_state(std::vector<std::pair<cryptonote::transaction, bool>> &process_txs, bool refreshed)
|
||||
{
|
||||
MTRACE("update_pool_state start");
|
||||
|
||||
|
@ -2968,11 +2977,6 @@ void wallet2::update_pool_state(bool refreshed)
|
|||
LOG_PRINT_L1("We sent that one");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_PRINT_L1("Already saw that one, it's for us");
|
||||
txids.push_back({txid, true});
|
||||
}
|
||||
}
|
||||
|
||||
// get those txes
|
||||
|
@ -3015,13 +3019,7 @@ void wallet2::update_pool_state(bool refreshed)
|
|||
[tx_hash](const std::pair<crypto::hash, bool> &e) { return e.first == tx_hash; });
|
||||
if (i != txids.end())
|
||||
{
|
||||
process_new_transaction(tx_hash, tx, std::vector<uint64_t>(), 0, 0, time(NULL), false, true, tx_entry.double_spend_seen, {});
|
||||
m_scanned_pool_txs[0].insert(tx_hash);
|
||||
if (m_scanned_pool_txs[0].size() > 5000)
|
||||
{
|
||||
std::swap(m_scanned_pool_txs[0], m_scanned_pool_txs[1]);
|
||||
m_scanned_pool_txs[0].clear();
|
||||
}
|
||||
process_txs.push_back(std::make_pair(tx, tx_entry.double_spend_seen));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3052,6 +3050,24 @@ void wallet2::update_pool_state(bool refreshed)
|
|||
MTRACE("update_pool_state end");
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::process_pool_state(const std::vector<std::pair<cryptonote::transaction, bool>> &txs)
|
||||
{
|
||||
const time_t now = time(NULL);
|
||||
for (const auto &e: txs)
|
||||
{
|
||||
const cryptonote::transaction &tx = e.first;
|
||||
const bool double_spend_seen = e.second;
|
||||
const crypto::hash tx_hash = get_transaction_hash(tx);
|
||||
process_new_transaction(tx_hash, tx, std::vector<uint64_t>(), 0, 0, now, false, true, double_spend_seen, {});
|
||||
m_scanned_pool_txs[0].insert(tx_hash);
|
||||
if (m_scanned_pool_txs[0].size() > 5000)
|
||||
{
|
||||
std::swap(m_scanned_pool_txs[0], m_scanned_pool_txs[1]);
|
||||
m_scanned_pool_txs[0].clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, bool force)
|
||||
{
|
||||
std::vector<crypto::hash> hashes;
|
||||
|
@ -3255,7 +3271,15 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
|
|||
});
|
||||
|
||||
auto scope_exit_handler_hwdev = epee::misc_utils::create_scope_leave_handler([&](){hwdev.computing_key_images(false);});
|
||||
bool first = true;
|
||||
|
||||
// get updated pool state first, but do not process those txes just yet,
|
||||
// since that might cause a password prompt, which would introduce a data
|
||||
// leak allowing a passive adversary with traffic analysis capability to
|
||||
// infer when we get an incoming output
|
||||
std::vector<std::pair<cryptonote::transaction, bool>> process_pool_txs;
|
||||
update_pool_state(process_pool_txs, refreshed);
|
||||
|
||||
bool first = true, last = false;
|
||||
while(m_run.load(std::memory_order_relaxed))
|
||||
{
|
||||
uint64_t next_blocks_start_height;
|
||||
|
@ -3277,7 +3301,8 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
|
|||
refreshed = true;
|
||||
break;
|
||||
}
|
||||
tpool.submit(&waiter, [&]{pull_and_parse_next_blocks(start_height, next_blocks_start_height, short_chain_history, blocks, parsed_blocks, next_blocks, next_parsed_blocks, error, exception);});
|
||||
if (!last)
|
||||
tpool.submit(&waiter, [&]{pull_and_parse_next_blocks(start_height, next_blocks_start_height, short_chain_history, blocks, parsed_blocks, next_blocks, next_parsed_blocks, last, error, exception);});
|
||||
|
||||
if (!first)
|
||||
{
|
||||
|
@ -3384,8 +3409,8 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
|
|||
try
|
||||
{
|
||||
// If stop() is called we don't need to check pending transactions
|
||||
if (check_pool && m_run.load(std::memory_order_relaxed))
|
||||
update_pool_state(refreshed);
|
||||
if (check_pool && m_run.load(std::memory_order_relaxed) && !process_pool_txs.empty())
|
||||
process_pool_state(process_pool_txs);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
@ -13187,7 +13212,7 @@ uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, ui
|
|||
bool wallet2::is_synced()
|
||||
{
|
||||
uint64_t height;
|
||||
boost::optional<std::string> result = m_node_rpc_proxy.get_target_height(height);
|
||||
boost::optional<std::string> result = m_node_rpc_proxy.get_height(height);
|
||||
if (result && *result != CORE_RPC_STATUS_OK)
|
||||
return false;
|
||||
return get_blockchain_current_height() >= height;
|
||||
|
|
|
@ -1219,7 +1219,8 @@ private:
|
|||
bool import_key_images(signed_tx_set & signed_tx, size_t offset=0, bool only_selected_transfers=false);
|
||||
crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const;
|
||||
|
||||
void update_pool_state(bool refreshed = false);
|
||||
void update_pool_state(std::vector<std::pair<cryptonote::transaction, bool>> &process_txs, bool refreshed = false);
|
||||
void process_pool_state(const std::vector<std::pair<cryptonote::transaction, bool>> &txs);
|
||||
void remove_obsolete_pool_txs(const std::vector<crypto::hash> &tx_hashes);
|
||||
|
||||
std::string encrypt(const char *plaintext, size_t len, const crypto::secret_key &skey, bool authenticated = true) const;
|
||||
|
@ -1403,10 +1404,10 @@ private:
|
|||
void get_short_chain_history(std::list<crypto::hash>& ids, uint64_t granularity = 1) const;
|
||||
bool clear();
|
||||
void clear_soft(bool keep_key_images=false);
|
||||
void pull_blocks(uint64_t start_height, uint64_t& blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::vector<cryptonote::block_complete_entry> &blocks, std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> &o_indices);
|
||||
void pull_blocks(uint64_t start_height, uint64_t& blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::vector<cryptonote::block_complete_entry> &blocks, std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> &o_indices, uint64_t ¤t_height);
|
||||
void pull_hashes(uint64_t start_height, uint64_t& blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::vector<crypto::hash> &hashes);
|
||||
void fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, bool force = false);
|
||||
void pull_and_parse_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, const std::vector<cryptonote::block_complete_entry> &prev_blocks, const std::vector<parsed_block> &prev_parsed_blocks, std::vector<cryptonote::block_complete_entry> &blocks, std::vector<parsed_block> &parsed_blocks, bool &error, std::exception_ptr &exception);
|
||||
void pull_and_parse_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, const std::vector<cryptonote::block_complete_entry> &prev_blocks, const std::vector<parsed_block> &prev_parsed_blocks, std::vector<cryptonote::block_complete_entry> &blocks, std::vector<parsed_block> &parsed_blocks, bool &last, bool &error, std::exception_ptr &exception);
|
||||
void process_parsed_blocks(uint64_t start_height, const std::vector<cryptonote::block_complete_entry> &blocks, const std::vector<parsed_block> &parsed_blocks, uint64_t& blocks_added, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache = NULL);
|
||||
uint64_t select_transfers(uint64_t needed_money, std::vector<size_t> unused_transfers_indices, std::vector<size_t>& selected_transfers) const;
|
||||
bool prepare_file_names(const std::string& file_path);
|
||||
|
|
|
@ -2438,7 +2438,10 @@ namespace tools
|
|||
|
||||
if (req.pool)
|
||||
{
|
||||
m_wallet->update_pool_state();
|
||||
std::vector<std::pair<cryptonote::transaction, bool>> process_txs;
|
||||
m_wallet->update_pool_state(process_txs);
|
||||
if (!process_txs.empty())
|
||||
m_wallet->process_pool_state(process_txs);
|
||||
|
||||
std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>> payments;
|
||||
m_wallet->get_unconfirmed_payments(payments, account_index, subaddr_indices);
|
||||
|
@ -2518,7 +2521,10 @@ namespace tools
|
|||
}
|
||||
}
|
||||
|
||||
m_wallet->update_pool_state();
|
||||
std::vector<std::pair<cryptonote::transaction, bool>> process_txs;
|
||||
m_wallet->update_pool_state(process_txs);
|
||||
if (!process_txs.empty())
|
||||
m_wallet->process_pool_state(process_txs);
|
||||
|
||||
std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>> pool_payments;
|
||||
m_wallet->get_unconfirmed_payments(pool_payments, req.account_index);
|
||||
|
|
Loading…
Reference in New Issue