diff options
author | luigi1111 <luigi1111w@gmail.com> | 2019-09-08 20:04:00 -0500 |
---|---|---|
committer | luigi1111 <luigi1111w@gmail.com> | 2019-09-08 20:04:00 -0500 |
commit | 93255017622bdfe65717b590ef4938f42f0ec0c8 (patch) | |
tree | 11b4a4baa8a35b69ae9addb6d53f73846c966bc4 | |
parent | Merge pull request #5851 (diff) | |
parent | wallet: fix mismatch between two concepts of "balance" (diff) | |
download | monero-93255017622bdfe65717b590ef4938f42f0ec0c8.tar.xz |
Merge pull request #5855
2ec455d wallet: fix mismatch between two concepts of 'balance' (moneromooo-monero)
-rw-r--r-- | src/simplewallet/simplewallet.cpp | 18 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 92 | ||||
-rw-r--r-- | src/wallet/wallet2.h | 16 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server.cpp | 16 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server_commands_defs.h | 4 | ||||
-rw-r--r-- | tests/functional_tests/transactions_flow_test.cpp | 8 | ||||
-rw-r--r-- | utils/python-rpc/framework/wallet.py | 3 |
7 files changed, 94 insertions, 63 deletions
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index e88421fb0..eee2fa61d 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -5335,14 +5335,14 @@ bool simple_wallet::show_balance_unlocked(bool detailed) const std::string tag = m_wallet->get_account_tags().second[m_current_subaddress_account]; success_msg_writer() << tr("Tag: ") << (tag.empty() ? std::string{tr("(No tag assigned)")} : tag); uint64_t blocks_to_unlock; - uint64_t unlocked_balance = m_wallet->unlocked_balance(m_current_subaddress_account, &blocks_to_unlock); + uint64_t unlocked_balance = m_wallet->unlocked_balance(m_current_subaddress_account, false, &blocks_to_unlock); std::string unlock_time_message; if (blocks_to_unlock > 0) unlock_time_message = (boost::format(" (%lu block(s) to unlock)") % blocks_to_unlock).str(); - success_msg_writer() << tr("Balance: ") << print_money(m_wallet->balance(m_current_subaddress_account)) << ", " + success_msg_writer() << tr("Balance: ") << print_money(m_wallet->balance(m_current_subaddress_account, false)) << ", " << tr("unlocked balance: ") << print_money(unlocked_balance) << unlock_time_message << extra; - std::map<uint32_t, uint64_t> balance_per_subaddress = m_wallet->balance_per_subaddress(m_current_subaddress_account); - std::map<uint32_t, std::pair<uint64_t, uint64_t>> unlocked_balance_per_subaddress = m_wallet->unlocked_balance_per_subaddress(m_current_subaddress_account); + std::map<uint32_t, uint64_t> balance_per_subaddress = m_wallet->balance_per_subaddress(m_current_subaddress_account, false); + std::map<uint32_t, std::pair<uint64_t, uint64_t>> unlocked_balance_per_subaddress = m_wallet->unlocked_balance_per_subaddress(m_current_subaddress_account, false); if (!detailed || balance_per_subaddress.empty()) return true; success_msg_writer() << tr("Balance per address:"); @@ -8743,7 +8743,7 @@ void simple_wallet::print_accounts() print_accounts(""); if (num_untagged_accounts < m_wallet->get_num_subaddress_accounts()) - success_msg_writer() << tr("\nGrand total:\n Balance: ") << print_money(m_wallet->balance_all()) << tr(", unlocked balance: ") << print_money(m_wallet->unlocked_balance_all()); + success_msg_writer() << tr("\nGrand total:\n Balance: ") << print_money(m_wallet->balance_all(false)) << tr(", unlocked balance: ") << print_money(m_wallet->unlocked_balance_all(false)); } //---------------------------------------------------------------------------------------------------- void simple_wallet::print_accounts(const std::string& tag) @@ -8773,11 +8773,11 @@ void simple_wallet::print_accounts(const std::string& tag) % (m_current_subaddress_account == account_index ? '*' : ' ') % account_index % m_wallet->get_subaddress_as_str({account_index, 0}).substr(0, 6) - % print_money(m_wallet->balance(account_index)) - % print_money(m_wallet->unlocked_balance(account_index)) + % print_money(m_wallet->balance(account_index, false)) + % print_money(m_wallet->unlocked_balance(account_index, false)) % m_wallet->get_subaddress_label({account_index, 0}); - total_balance += m_wallet->balance(account_index); - total_unlocked_balance += m_wallet->unlocked_balance(account_index); + total_balance += m_wallet->balance(account_index, false); + total_unlocked_balance += m_wallet->unlocked_balance(account_index, false); } success_msg_writer() << tr("----------------------------------------------------------------------------------"); success_msg_writer() << boost::format(tr("%15s %21s %21s")) % "Total" % print_money(total_balance) % print_money(total_unlocked_balance); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 0d133e3b9..476c68c74 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1543,6 +1543,7 @@ bool wallet2::is_deprecated() const //---------------------------------------------------------------------------------------------------- void wallet2::set_spent(size_t idx, uint64_t height) { + CHECK_AND_ASSERT_THROW_MES(idx < m_transfers.size(), "Invalid index"); transfer_details &td = m_transfers[idx]; LOG_PRINT_L2("Setting SPENT at " << height << ": ki " << td.m_key_image << ", amount " << print_money(td.m_amount)); td.m_spent = true; @@ -1551,12 +1552,32 @@ void wallet2::set_spent(size_t idx, uint64_t height) //---------------------------------------------------------------------------------------------------- void wallet2::set_unspent(size_t idx) { + CHECK_AND_ASSERT_THROW_MES(idx < m_transfers.size(), "Invalid index"); transfer_details &td = m_transfers[idx]; LOG_PRINT_L2("Setting UNSPENT: ki " << td.m_key_image << ", amount " << print_money(td.m_amount)); td.m_spent = false; td.m_spent_height = 0; } //---------------------------------------------------------------------------------------------------- +bool wallet2::is_spent(const transfer_details &td, bool strict) const +{ + if (strict) + { + return td.m_spent && td.m_spent_height > 0; + } + else + { + return td.m_spent; + } +} +//---------------------------------------------------------------------------------------------------- +bool wallet2::is_spent(size_t idx, bool strict) const +{ + CHECK_AND_ASSERT_THROW_MES(idx < m_transfers.size(), "Invalid index"); + const transfer_details &td = m_transfers[idx]; + return is_spent(td, strict); +} +//---------------------------------------------------------------------------------------------------- void wallet2::freeze(size_t idx) { CHECK_AND_ASSERT_THROW_MES(idx < m_transfers.size(), "Invalid transfer_details index"); @@ -3294,7 +3315,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo m_first_refresh_done = true; - LOG_PRINT_L1("Refresh done, blocks received: " << blocks_fetched << ", balance (all accounts): " << print_money(balance_all()) << ", unlocked: " << print_money(unlocked_balance_all())); + LOG_PRINT_L1("Refresh done, blocks received: " << blocks_fetched << ", balance (all accounts): " << print_money(balance_all(false)) << ", unlocked: " << print_money(unlocked_balance_all(false))); } //---------------------------------------------------------------------------------------------------- bool wallet2::refresh(bool trusted_daemon, uint64_t & blocks_fetched, bool& received_money, bool& ok) @@ -5594,24 +5615,24 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas } //---------------------------------------------------------------------------------------------------- -uint64_t wallet2::balance(uint32_t index_major) const +uint64_t wallet2::balance(uint32_t index_major, bool strict) const { uint64_t amount = 0; if(m_light_wallet) return m_light_wallet_unlocked_balance; - for (const auto& i : balance_per_subaddress(index_major)) + for (const auto& i : balance_per_subaddress(index_major, strict)) amount += i.second; return amount; } //---------------------------------------------------------------------------------------------------- -uint64_t wallet2::unlocked_balance(uint32_t index_major, uint64_t *blocks_to_unlock) const +uint64_t wallet2::unlocked_balance(uint32_t index_major, bool strict, uint64_t *blocks_to_unlock) const { uint64_t amount = 0; if (blocks_to_unlock) *blocks_to_unlock = 0; if(m_light_wallet) return m_light_wallet_balance; - for (const auto& i : unlocked_balance_per_subaddress(index_major)) + for (const auto& i : unlocked_balance_per_subaddress(index_major, strict)) { amount += i.second.first; if (blocks_to_unlock && i.second.second > *blocks_to_unlock) @@ -5620,12 +5641,12 @@ uint64_t wallet2::unlocked_balance(uint32_t index_major, uint64_t *blocks_to_unl return amount; } //---------------------------------------------------------------------------------------------------- -std::map<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_major) const +std::map<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_major, bool strict) const { std::map<uint32_t, uint64_t> amount_per_subaddr; for (const auto& td: m_transfers) { - if (td.m_subaddr_index.major == index_major && !td.m_spent && !td.m_frozen) + if (td.m_subaddr_index.major == index_major && !is_spent(td, strict) && !td.m_frozen) { auto found = amount_per_subaddr.find(td.m_subaddr_index.minor); if (found == amount_per_subaddr.end()) @@ -5634,8 +5655,10 @@ std::map<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_majo found->second += td.amount(); } } - for (const auto& utx: m_unconfirmed_txs) + if (!strict) { + for (const auto& utx: m_unconfirmed_txs) + { if (utx.second.m_subaddr_account == index_major && utx.second.m_state != wallet2::unconfirmed_transfer_details::failed) { // all changes go to 0-th subaddress (in the current subaddress account) @@ -5645,17 +5668,18 @@ std::map<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_majo else found->second += utx.second.m_change; } + } } return amount_per_subaddr; } //---------------------------------------------------------------------------------------------------- -std::map<uint32_t, std::pair<uint64_t, uint64_t>> wallet2::unlocked_balance_per_subaddress(uint32_t index_major) const +std::map<uint32_t, std::pair<uint64_t, uint64_t>> wallet2::unlocked_balance_per_subaddress(uint32_t index_major, bool strict) const { std::map<uint32_t, std::pair<uint64_t, uint64_t>> amount_per_subaddr; const uint64_t blockchain_height = get_blockchain_current_height(); for(const transfer_details& td: m_transfers) { - if(td.m_subaddr_index.major == index_major && !td.m_spent && !td.m_frozen) + if(td.m_subaddr_index.major == index_major && !is_spent(td, strict) && !td.m_frozen) { uint64_t amount = 0, blocks_to_unlock = 0; if (is_transfer_unlocked(td)) @@ -5684,15 +5708,15 @@ std::map<uint32_t, std::pair<uint64_t, uint64_t>> wallet2::unlocked_balance_per_ return amount_per_subaddr; } //---------------------------------------------------------------------------------------------------- -uint64_t wallet2::balance_all() const +uint64_t wallet2::balance_all(bool strict) const { uint64_t r = 0; for (uint32_t index_major = 0; index_major < get_num_subaddress_accounts(); ++index_major) - r += balance(index_major); + r += balance(index_major, strict); return r; } //---------------------------------------------------------------------------------------------------- -uint64_t wallet2::unlocked_balance_all(uint64_t *blocks_to_unlock) const +uint64_t wallet2::unlocked_balance_all(bool strict, uint64_t *blocks_to_unlock) const { uint64_t r = 0; if (blocks_to_unlock) @@ -5700,7 +5724,7 @@ uint64_t wallet2::unlocked_balance_all(uint64_t *blocks_to_unlock) const for (uint32_t index_major = 0; index_major < get_num_subaddress_accounts(); ++index_major) { uint64_t local_blocks_to_unlock; - r += unlocked_balance(index_major, blocks_to_unlock ? &local_blocks_to_unlock : NULL); + r += unlocked_balance(index_major, strict, blocks_to_unlock ? &local_blocks_to_unlock : NULL); if (blocks_to_unlock) *blocks_to_unlock = std::max(*blocks_to_unlock, local_blocks_to_unlock); } @@ -6177,8 +6201,8 @@ void wallet2::commit_tx(pending_tx& ptx) //fee includes dust if dust policy specified it. LOG_PRINT_L1("Transaction successfully sent. <" << txid << ">" << ENDL << "Commission: " << print_money(ptx.fee) << " (dust sent to dust addr: " << print_money((ptx.dust_added_to_fee ? 0 : ptx.dust)) << ")" << ENDL - << "Balance: " << print_money(balance(ptx.construction_data.subaddr_account)) << ENDL - << "Unlocked: " << print_money(unlocked_balance(ptx.construction_data.subaddr_account)) << ENDL + << "Balance: " << print_money(balance(ptx.construction_data.subaddr_account, false)) << ENDL + << "Unlocked: " << print_money(unlocked_balance(ptx.construction_data.subaddr_account, false)) << ENDL << "Please, wait for confirmation for your balance to be unlocked."); } @@ -8559,7 +8583,7 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui for (size_t i = 0; i < m_transfers.size(); ++i) { const transfer_details& td = m_transfers[i]; - if (!td.m_spent && !td.m_frozen && td.is_rct() && td.amount() >= needed_money && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1) + if (!is_spent(td, false) && !td.m_frozen && td.is_rct() && td.amount() >= needed_money && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1) { LOG_PRINT_L2("We can use " << i << " alone: " << print_money(td.amount())); picks.push_back(i); @@ -8574,13 +8598,13 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui for (size_t i = 0; i < m_transfers.size(); ++i) { const transfer_details& td = m_transfers[i]; - if (!td.m_spent && !td.m_frozen && !td.m_key_image_partial && td.is_rct() && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1) + if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && td.is_rct() && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1) { LOG_PRINT_L2("Considering input " << i << ", " << print_money(td.amount())); for (size_t j = i + 1; j < m_transfers.size(); ++j) { const transfer_details& td2 = m_transfers[j]; - if (!td2.m_spent && !td2.m_frozen && !td.m_key_image_partial && td2.is_rct() && td.amount() + td2.amount() >= needed_money && is_transfer_unlocked(td2) && td2.m_subaddr_index == td.m_subaddr_index) + if (!is_spent(td2, false) && !td2.m_frozen && !td.m_key_image_partial && td2.is_rct() && td.amount() + td2.amount() >= needed_money && is_transfer_unlocked(td2) && td2.m_subaddr_index == td.m_subaddr_index) { // update our picks if those outputs are less related than any we // already found. If the same, don't update, and oldest suitable outputs @@ -9235,8 +9259,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp // throw if attempting a transaction with no money THROW_WALLET_EXCEPTION_IF(needed_money == 0, error::zero_destination); - std::map<uint32_t, std::pair<uint64_t, uint64_t>> unlocked_balance_per_subaddr = unlocked_balance_per_subaddress(subaddr_account); - std::map<uint32_t, uint64_t> balance_per_subaddr = balance_per_subaddress(subaddr_account); + std::map<uint32_t, std::pair<uint64_t, uint64_t>> unlocked_balance_per_subaddr = unlocked_balance_per_subaddress(subaddr_account, false); + std::map<uint32_t, uint64_t> balance_per_subaddr = balance_per_subaddress(subaddr_account, false); if (subaddr_indices.empty()) // "index=<N1>[,<N2>,...]" wasn't specified -> use all the indices with non-zero unlocked balance { @@ -9282,7 +9306,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is below threshold " << print_money(fractional_threshold)); continue; } - if (!td.m_spent && !td.m_frozen && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1) + if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1) { const uint32_t index_minor = td.m_subaddr_index.minor; auto find_predicate = [&index_minor](const std::pair<uint32_t, std::vector<size_t>>& x) { return x.first == index_minor; }; @@ -9409,7 +9433,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp // if we need to spend money and don't have any left, we fail if (unused_dust_indices->empty() && unused_transfers_indices->empty()) { LOG_PRINT_L2("No more outputs to choose from"); - THROW_WALLET_EXCEPTION_IF(1, error::tx_not_possible, unlocked_balance(subaddr_account), needed_money, accumulated_fee + needed_fee); + THROW_WALLET_EXCEPTION_IF(1, error::tx_not_possible, unlocked_balance(subaddr_account, false), needed_money, accumulated_fee + needed_fee); } // get a random unspent output and use it to pay part (or all) of the current destination (and maybe next one, etc) @@ -9627,7 +9651,7 @@ skip_tx: if (adding_fee) { LOG_PRINT_L1("We ran out of outputs while trying to gather final fee"); - THROW_WALLET_EXCEPTION_IF(1, error::tx_not_possible, unlocked_balance(subaddr_account), needed_money, accumulated_fee + needed_fee); + THROW_WALLET_EXCEPTION_IF(1, error::tx_not_possible, unlocked_balance(subaddr_account, false), needed_money, accumulated_fee + needed_fee); } LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_money(accumulated_fee) << @@ -9762,7 +9786,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below std::vector<size_t> unused_dust_indices; const bool use_rct = use_fork_rules(4, 0); - THROW_WALLET_EXCEPTION_IF(unlocked_balance(subaddr_account) == 0, error::wallet_internal_error, "No unlocked balance in the entire wallet"); + THROW_WALLET_EXCEPTION_IF(unlocked_balance(subaddr_account, false) == 0, error::wallet_internal_error, "No unlocked balance in the entire wallet"); std::map<uint32_t, std::pair<std::vector<size_t>, std::vector<size_t>>> unused_transfer_dust_indices_per_subaddr; @@ -9771,7 +9795,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below for (size_t i = 0; i < m_transfers.size(); ++i) { const transfer_details& td = m_transfers[i]; - if (!td.m_spent && !td.m_frozen && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && (subaddr_indices.empty() || subaddr_indices.count(td.m_subaddr_index.minor) == 1)) + if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && (subaddr_indices.empty() || subaddr_indices.count(td.m_subaddr_index.minor) == 1)) { fund_found = true; if (below == 0 || td.amount() < below) @@ -9819,7 +9843,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypt for (size_t i = 0; i < m_transfers.size(); ++i) { const transfer_details& td = m_transfers[i]; - if (td.m_key_image_known && td.m_key_image == ki && !td.m_spent && !td.m_frozen && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td)) + if (td.m_key_image_known && td.m_key_image == ki && !is_spent(td, false) && !td.m_frozen && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td)) { if (td.is_rct() || is_valid_decomposed_amount(td.amount())) unused_transfers_indices.push_back(i); @@ -10185,7 +10209,7 @@ std::vector<size_t> wallet2::select_available_outputs(const std::function<bool(c size_t n = 0; for (transfer_container::const_iterator i = m_transfers.begin(); i != m_transfers.end(); ++i, ++n) { - if (i->m_spent) + if (is_spent(*i, false)) continue; if (i->m_frozen) continue; @@ -10199,12 +10223,12 @@ std::vector<size_t> wallet2::select_available_outputs(const std::function<bool(c return outputs; } //---------------------------------------------------------------------------------------------------- -std::vector<uint64_t> wallet2::get_unspent_amounts_vector() const +std::vector<uint64_t> wallet2::get_unspent_amounts_vector(bool strict) const { std::set<uint64_t> set; for (const auto &td: m_transfers) { - if (!td.m_spent && !td.m_frozen) + if (!is_spent(td, strict) && !td.m_frozen) set.insert(td.is_rct() ? 0 : td.amount()); } std::vector<uint64_t> vector; @@ -10222,7 +10246,7 @@ std::vector<size_t> wallet2::select_available_outputs_from_histogram(uint64_t co cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::response resp_t = AUTO_VAL_INIT(resp_t); m_daemon_rpc_mutex.lock(); if (is_trusted_daemon()) - req_t.amounts = get_unspent_amounts_vector(); + req_t.amounts = get_unspent_amounts_vector(false); req_t.min_count = count; req_t.max_count = 0; req_t.unlocked = unlocked; @@ -11120,8 +11144,8 @@ bool wallet2::check_tx_proof(const cryptonote::transaction &tx, const cryptonote std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t, uint64_t>> &account_minreserve, const std::string &message) { THROW_WALLET_EXCEPTION_IF(m_watch_only || m_multisig, error::wallet_internal_error, "Reserve proof can only be generated by a full wallet"); - THROW_WALLET_EXCEPTION_IF(balance_all() == 0, error::wallet_internal_error, "Zero balance"); - THROW_WALLET_EXCEPTION_IF(account_minreserve && balance(account_minreserve->first) < account_minreserve->second, error::wallet_internal_error, + THROW_WALLET_EXCEPTION_IF(balance_all(true) == 0, error::wallet_internal_error, "Zero balance"); + THROW_WALLET_EXCEPTION_IF(account_minreserve && balance(account_minreserve->first, true) < account_minreserve->second, error::wallet_internal_error, "Not enough balance in this account for the requested minimum reserve amount"); // determine which outputs to include in the proof @@ -11129,7 +11153,7 @@ std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t, for (size_t i = 0; i < m_transfers.size(); ++i) { const transfer_details &td = m_transfers[i]; - if (!td.m_spent && !td.m_frozen && (!account_minreserve || account_minreserve->first == td.m_subaddr_index.major)) + if (!is_spent(td, true) && !td.m_frozen && (!account_minreserve || account_minreserve->first == td.m_subaddr_index.major)) selected_transfers.push_back(i); } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 5607602e7..95f6f507a 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -804,14 +804,14 @@ private: bool reconnect_device(); // locked & unlocked balance of given or current subaddress account - uint64_t balance(uint32_t subaddr_index_major) const; - uint64_t unlocked_balance(uint32_t subaddr_index_major, uint64_t *blocks_to_unlock = NULL) const; + uint64_t balance(uint32_t subaddr_index_major, bool strict) const; + uint64_t unlocked_balance(uint32_t subaddr_index_major, bool strict, uint64_t *blocks_to_unlock = NULL) const; // locked & unlocked balance per subaddress of given or current subaddress account - std::map<uint32_t, uint64_t> balance_per_subaddress(uint32_t subaddr_index_major) const; - std::map<uint32_t, std::pair<uint64_t, uint64_t>> unlocked_balance_per_subaddress(uint32_t subaddr_index_major) const; + std::map<uint32_t, uint64_t> balance_per_subaddress(uint32_t subaddr_index_major, bool strict) const; + std::map<uint32_t, std::pair<uint64_t, uint64_t>> unlocked_balance_per_subaddress(uint32_t subaddr_index_major, bool strict) const; // all locked & unlocked balances of all subaddress accounts - uint64_t balance_all() const; - uint64_t unlocked_balance_all(uint64_t *blocks_to_unlock = NULL) const; + uint64_t balance_all(bool strict) const; + uint64_t unlocked_balance_all(bool strict, uint64_t *blocks_to_unlock = NULL) const; template<typename T> void transfer_selected(const std::vector<cryptonote::tx_destination_entry>& dsts, const std::vector<size_t>& selected_transfers, size_t fake_outputs_count, std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, @@ -1377,12 +1377,14 @@ private: void check_acc_out_precomp_once(const cryptonote::tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, const is_out_data *is_out_data, tx_scan_info_t &tx_scan_info, bool &already_seen) const; void parse_block_round(const cryptonote::blobdata &blob, cryptonote::block &bl, crypto::hash &bl_id, bool &error) const; uint64_t get_upper_transaction_weight_limit() const; - std::vector<uint64_t> get_unspent_amounts_vector() const; + std::vector<uint64_t> get_unspent_amounts_vector(bool strict) const; uint64_t get_dynamic_base_fee_estimate() const; float get_output_relatedness(const transfer_details &td0, const transfer_details &td1) const; std::vector<size_t> pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices) const; void set_spent(size_t idx, uint64_t height); void set_unspent(size_t idx); + bool is_spent(const transfer_details &td, bool strict = true) const; + bool is_spent(size_t idx, bool strict = true) const; void get_outs(std::vector<std::vector<get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count); bool tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, uint64_t global_index, const crypto::public_key& tx_public_key, const rct::key& mask, uint64_t real_index, bool unlocked) const; bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector<size_t> &unused_transfers_indices, const std::vector<size_t> &unused_dust_indices) const; diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 7c87e7114..896f8f48e 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -420,8 +420,8 @@ namespace tools if (!m_wallet) return not_open(er); try { - res.balance = req.all_accounts ? m_wallet->balance_all() : m_wallet->balance(req.account_index); - res.unlocked_balance = req.all_accounts ? m_wallet->unlocked_balance_all(&res.blocks_to_unlock) : m_wallet->unlocked_balance(req.account_index, &res.blocks_to_unlock); + res.balance = req.all_accounts ? m_wallet->balance_all(req.strict) : m_wallet->balance(req.account_index, req.strict); + res.unlocked_balance = req.all_accounts ? m_wallet->unlocked_balance_all(req.strict, &res.blocks_to_unlock) : m_wallet->unlocked_balance(req.account_index, req.strict, &res.blocks_to_unlock); res.multisig_import_needed = m_wallet->multisig() && m_wallet->has_multisig_partial_key_images(); std::map<uint32_t, std::map<uint32_t, uint64_t>> balance_per_subaddress_per_account; std::map<uint32_t, std::map<uint32_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddress_per_account; @@ -429,14 +429,14 @@ namespace tools { for (uint32_t account_index = 0; account_index < m_wallet->get_num_subaddress_accounts(); ++account_index) { - balance_per_subaddress_per_account[account_index] = m_wallet->balance_per_subaddress(account_index); - unlocked_balance_per_subaddress_per_account[account_index] = m_wallet->unlocked_balance_per_subaddress(account_index); + balance_per_subaddress_per_account[account_index] = m_wallet->balance_per_subaddress(account_index, req.strict); + unlocked_balance_per_subaddress_per_account[account_index] = m_wallet->unlocked_balance_per_subaddress(account_index, req.strict); } } else { - balance_per_subaddress_per_account[req.account_index] = m_wallet->balance_per_subaddress(req.account_index); - unlocked_balance_per_subaddress_per_account[req.account_index] = m_wallet->unlocked_balance_per_subaddress(req.account_index); + balance_per_subaddress_per_account[req.account_index] = m_wallet->balance_per_subaddress(req.account_index, req.strict); + unlocked_balance_per_subaddress_per_account[req.account_index] = m_wallet->unlocked_balance_per_subaddress(req.account_index, req.strict); } std::vector<tools::wallet2::transfer_details> transfers; m_wallet->get_transfers(transfers); @@ -594,8 +594,8 @@ namespace tools wallet_rpc::COMMAND_RPC_GET_ACCOUNTS::subaddress_account_info info; info.account_index = subaddr_index.major; info.base_address = m_wallet->get_subaddress_as_str(subaddr_index); - info.balance = m_wallet->balance(subaddr_index.major); - info.unlocked_balance = m_wallet->unlocked_balance(subaddr_index.major); + info.balance = m_wallet->balance(subaddr_index.major, req.strict_balances); + info.unlocked_balance = m_wallet->unlocked_balance(subaddr_index.major, req.strict_balances); info.label = m_wallet->get_subaddress_label(subaddr_index); info.tag = account_tags.second[subaddr_index.major]; res.subaddress_accounts.push_back(info); diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 2dfe6db85..e9b8b60f5 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -64,10 +64,12 @@ namespace wallet_rpc uint32_t account_index; std::set<uint32_t> address_indices; bool all_accounts; + bool strict; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(account_index) KV_SERIALIZE(address_indices) KV_SERIALIZE_OPT(all_accounts, false); + KV_SERIALIZE_OPT(strict, false); END_KV_SERIALIZE_MAP() }; typedef epee::misc_utils::struct_init<request_t> request; @@ -230,9 +232,11 @@ namespace wallet_rpc struct request_t { std::string tag; // all accounts if empty, otherwise those accounts with this tag + bool strict_balances; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tag) + KV_SERIALIZE_OPT(strict_balances, false) END_KV_SERIALIZE_MAP() }; typedef epee::misc_utils::struct_init<request_t> request; diff --git a/tests/functional_tests/transactions_flow_test.cpp b/tests/functional_tests/transactions_flow_test.cpp index 32b601d7a..2add66b8b 100644 --- a/tests/functional_tests/transactions_flow_test.cpp +++ b/tests/functional_tests/transactions_flow_test.cpp @@ -173,7 +173,7 @@ bool transactions_flow_test(std::string& working_folder, //wait for money, until balance will have enough money w1.refresh(true, blocks_fetched, received_money, ok); - while(w1.unlocked_balance(0) < amount_to_transfer) + while(w1.unlocked_balance(0, true) < amount_to_transfer) { misc_utils::sleep_no_w(1000); w1.refresh(true, blocks_fetched, received_money, ok); @@ -186,7 +186,7 @@ bool transactions_flow_test(std::string& working_folder, { tools::wallet2::transfer_container incoming_transfers; w1.get_transfers(incoming_transfers); - if(incoming_transfers.size() > FIRST_N_TRANSFERS && get_money_in_first_transfers(incoming_transfers, FIRST_N_TRANSFERS) < w1.unlocked_balance(0) ) + if(incoming_transfers.size() > FIRST_N_TRANSFERS && get_money_in_first_transfers(incoming_transfers, FIRST_N_TRANSFERS) < w1.unlocked_balance(0, true) ) { //lets go! size_t count = 0; @@ -221,7 +221,7 @@ bool transactions_flow_test(std::string& working_folder, for(i = 0; i != transactions_count; i++) { uint64_t amount_to_tx = (amount_to_transfer - transfered_money) > transfer_size ? transfer_size: (amount_to_transfer - transfered_money); - while(w1.unlocked_balance(0) < amount_to_tx + TEST_FEE) + while(w1.unlocked_balance(0, true) < amount_to_tx + TEST_FEE) { misc_utils::sleep_no_w(1000); LOG_PRINT_L0("not enough money, waiting for cashback or mining"); @@ -270,7 +270,7 @@ bool transactions_flow_test(std::string& working_folder, misc_utils::sleep_no_w(DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN*1000);//wait two blocks before sync on another wallet on another daemon } - uint64_t money_2 = w2.balance(0); + uint64_t money_2 = w2.balance(0, true); if(money_2 == transfered_money) { MGINFO_GREEN("-----------------------FINISHING TRANSACTIONS FLOW TEST OK-----------------------"); diff --git a/utils/python-rpc/framework/wallet.py b/utils/python-rpc/framework/wallet.py index 36ff3644f..3bbb8b151 100644 --- a/utils/python-rpc/framework/wallet.py +++ b/utils/python-rpc/framework/wallet.py @@ -140,13 +140,14 @@ class Wallet(object): } return self.rpc.send_json_rpc_request(create_wallet) - def get_balance(self, account_index = 0, address_indices = [], all_accounts = False): + def get_balance(self, account_index = 0, address_indices = [], all_accounts = False, strict = False): get_balance = { 'method': 'get_balance', 'params': { 'account_index': account_index, 'address_indices': address_indices, 'all_accounts': all_accounts, + 'strict': strict, }, 'jsonrpc': '2.0', 'id': '0' |