From db2c0b67a196ed45ecab1a8d4506241b2ed25bde Mon Sep 17 00:00:00 2001 From: Anthony Fieroni Date: Wed, 13 Jan 2021 11:06:33 +0200 Subject: [PATCH] Fix auto selecting balances Signed-off-by: Anthony Fieroni --- src/masternodes/balances.h | 10 ++++------ src/masternodes/mn_rpc.cpp | 36 ++++++++++++++++++++---------------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/masternodes/balances.h b/src/masternodes/balances.h index be82dae0da..1ded2837a5 100644 --- a/src/masternodes/balances.h +++ b/src/masternodes/balances.h @@ -88,7 +88,7 @@ struct CBalances return Res::Ok(); } - CAmount GetAllTokensAmount() { + CAmount GetAllTokensAmount() const { CAmount sum = 0; for (auto& balance : balances) { sum += balance.second; @@ -125,12 +125,10 @@ struct CBalances friend bool operator<(const CBalances& a, const CBalances& b) { for (const auto& a_kv : a.balances) { const auto b_value_it = b.balances.find(a_kv.first); - CAmount b_value = 0; if (b_value_it != b.balances.end()) { - b_value = b_value_it->second; - } - if (a_kv.second >= b_value) { - return false; + if (a_kv.second >= b_value_it->second) { + return false; + } } } return true; diff --git a/src/masternodes/mn_rpc.cpp b/src/masternodes/mn_rpc.cpp index 3163690cb9..af9ac2e672 100644 --- a/src/masternodes/mn_rpc.cpp +++ b/src/masternodes/mn_rpc.cpp @@ -110,57 +110,61 @@ static AccountSelectionMode ParseAccountSelectionParam(const std::string selecti } static CAccounts SelectAccountsByTargetBalances(const CAccounts& accounts, const CBalances& targetBalances, AccountSelectionMode selectionMode) { - CAccounts selectedAccountsBalances; + std::vector> foundAccountsBalances; - CBalances residualBalances(targetBalances); // iterate at all accounts to finding all accounts with neccessaru token balances - for (auto accIt = accounts.begin(); accIt != accounts.end(); accIt++) { + for (const auto& account : accounts) { // selectedBalances accumulates overlap between account balances and residual balances CBalances selectedBalances; // iterate at residual balances to find neccessary tokens in account - for (auto balIt = residualBalances.balances.begin(); balIt != residualBalances.balances.end(); balIt++) { + for (const auto& balance : targetBalances.balances) { // find neccessary token amount from current account - auto foundTokenAmount = accIt->second.balances.find(balIt->first); + const auto& accountBalances = account.second.balances; + auto foundTokenAmount = accountBalances.find(balance.first); // account balance has neccessary token - if (foundTokenAmount != accIt->second.balances.end()) { + if (foundTokenAmount != accountBalances.end()) { // add token amount to selected balances from current account selectedBalances.Add(CTokenAmount{foundTokenAmount->first, foundTokenAmount->second}); } } if (!selectedBalances.balances.empty()) { // added account and selected balances from account to selected accounts - foundAccountsBalances.emplace_back(accIt->first, selectedBalances); + foundAccountsBalances.emplace_back(account.first, selectedBalances); } } if (selectionMode != SelectionForward) { // we need sort vector by ascending or descending sum of token amounts - std::sort(foundAccountsBalances.begin(), foundAccountsBalances.end(), [&](std::pair p1, std::pair p2) { + std::sort(foundAccountsBalances.begin(), foundAccountsBalances.end(), [&](const std::pair& p1, const std::pair& p2) { return (selectionMode == SelectionCrumbs) ? p1.second.GetAllTokensAmount() > p2.second.GetAllTokensAmount() : - p1.second.GetAllTokensAmount() < p2.second.GetAllTokensAmount(); + p1.second.GetAllTokensAmount() < p2.second.GetAllTokensAmount(); }); } + CAccounts selectedAccountsBalances; + CBalances residualBalances(targetBalances); // selecting accounts balances - for (auto accIt = foundAccountsBalances.begin(); accIt != foundAccountsBalances.end(); accIt++) { + for (const auto& accountBalances : foundAccountsBalances) { // Substract residualBalances and selectedBalances with remainder. // Substraction with remainder will remove tokenAmount from balances if remainder // of token's amount is not zero (we got negative result of substraction) - CBalances remainder = residualBalances.SubBalancesWithRemainder(accIt->second.balances); + CBalances finalBalances(accountBalances.second); + CBalances remainder = residualBalances.SubBalancesWithRemainder(finalBalances.balances); // calculate final balances by substraction account balances with remainder // it is necessary to get rid of excess - CBalances finalBalances(accIt->second); finalBalances.SubBalances(remainder.balances); - if (!finalBalances.balances.empty()) - selectedAccountsBalances.emplace(accIt->first, finalBalances); + if (!finalBalances.balances.empty()) { + selectedAccountsBalances.emplace(accountBalances.first, finalBalances); + } // if residual balances is empty we found all neccessary token amounts and can stop selecting - if (residualBalances.balances.empty()) + if (residualBalances.balances.empty()) { break; + } } const auto selectedBalancesSum = SumAllTransfers(selectedAccountsBalances); - if (selectedBalancesSum != targetBalances) { + if (selectedBalancesSum < targetBalances) { // we have not enough tokens balance to transfer return {}; }