From ae87d0594cb3da79ea2027c633085961975c98b2 Mon Sep 17 00:00:00 2001 From: Peter John Bushnell Date: Sat, 4 Mar 2023 00:30:25 +0800 Subject: [PATCH] Restore ForEachAccount. Calc owner reward on MN wallet addresses. (#1789) --- src/masternodes/accounts.cpp | 5 ++++ src/masternodes/accounts.h | 1 + src/masternodes/masternodes.cpp | 22 ++++++++++++++ src/masternodes/masternodes.h | 4 +++ src/masternodes/mn_rpc.cpp | 21 ++++++-------- src/masternodes/rpc_accounts.cpp | 49 ++++++++++++++------------------ 6 files changed, 62 insertions(+), 40 deletions(-) diff --git a/src/masternodes/accounts.cpp b/src/masternodes/accounts.cpp index b6babc7af8..16e2f3fc1e 100644 --- a/src/masternodes/accounts.cpp +++ b/src/masternodes/accounts.cpp @@ -67,6 +67,11 @@ Res CAccountsView::SubBalances(const CScript &owner, const CBalances &balances) return Res::Ok(); } +void CAccountsView::ForEachAccount(std::function callback, const CScript &start) { + ForEach( + [&callback](const CScript &owner, CLazySerialize) { return callback(owner); }, start); +} + Res CAccountsView::UpdateBalancesHeight(const CScript &owner, uint32_t height) { WriteBy(owner, height); return Res::Ok(); diff --git a/src/masternodes/accounts.h b/src/masternodes/accounts.h index e890b8bc29..5502657fda 100644 --- a/src/masternodes/accounts.h +++ b/src/masternodes/accounts.h @@ -55,6 +55,7 @@ struct CFuturesUserValue { class CAccountsView : public virtual CStorageView { public: + void ForEachAccount(std::function callback, const CScript &start = {}); void ForEachBalance(std::function callback, const BalanceKey &start = {}); CTokenAmount GetBalance(const CScript &owner, DCT_ID tokenID) const; diff --git a/src/masternodes/masternodes.cpp b/src/masternodes/masternodes.cpp index ad1b8a7f36..ad7cb82573 100644 --- a/src/masternodes/masternodes.cpp +++ b/src/masternodes/masternodes.cpp @@ -1324,3 +1324,25 @@ CAmount CCustomCSView::GetFeeBurnPctFromAttributes() const { return attributes->GetValue(feeBurnPctKey, Params().GetConsensus().props.feeBurnPct); } + +void CalcMissingRewardTempFix(CCustomCSView &mnview, const uint32_t targetHeight, const CWallet &wallet) { + mnview.ForEachMasternode([&](const uint256 &id, const CMasternode &node) { + if (node.rewardAddressType) { + const CScript rewardAddress = GetScriptForDestination(node.rewardAddressType == PKHashType ? + CTxDestination(PKHash(node.rewardAddress)) : + CTxDestination(WitnessV0KeyHash(node.rewardAddress))); + if (IsMineCached(wallet, rewardAddress) == ISMINE_SPENDABLE) { + mnview.CalculateOwnerRewards(rewardAddress, targetHeight); + } + } + + const CScript rewardAddress = GetScriptForDestination(node.ownerType == PKHashType ? + CTxDestination(PKHash(node.ownerAuthAddress)) : + CTxDestination(WitnessV0KeyHash(node.ownerAuthAddress))); + if (IsMineCached(wallet, rewardAddress) == ISMINE_SPENDABLE) { + mnview.CalculateOwnerRewards(rewardAddress, targetHeight); + } + + return true; + }); +} diff --git a/src/masternodes/masternodes.h b/src/masternodes/masternodes.h index 08f86e3ede..90f944c332 100644 --- a/src/masternodes/masternodes.h +++ b/src/masternodes/masternodes.h @@ -46,6 +46,10 @@ CAmount GetTokenCreationFee(int height); CAmount GetMnCollateralAmount(int height); CAmount GetProposalCreationFee(int height, const CCustomCSView &view, const CCreateProposalMessage &msg); +// Update owner rewards for MNs missing call to CalculateOwnerRewards after voter fee distributions. +// Missing call fixed in: https://github.com/DeFiCh/ain/pull/1766 +void CalcMissingRewardTempFix(CCustomCSView &mnview, const uint32_t targetHeight, const CWallet &wallet); + enum class UpdateMasternodeType : uint8_t { None = 0x00, OwnerAddress = 0x01, diff --git a/src/masternodes/mn_rpc.cpp b/src/masternodes/mn_rpc.cpp index 7bc90d6db7..8d5adffadb 100644 --- a/src/masternodes/mn_rpc.cpp +++ b/src/masternodes/mn_rpc.cpp @@ -19,20 +19,15 @@ CAccounts GetAllMineAccounts(CWallet * const pwallet) { CCustomCSView mnview(*pcustomcsview); auto targetHeight = ::ChainActive().Height() + 1; - // ForEachBalance is in account order, so we only need to check if the - // last record is the same as the current one to know whether we can skip - // CalculateOwnerRewards or if it needs to be called. - CScript lastCalculatedOwner; - - mnview.ForEachBalance([&](const CScript &owner, const CTokenAmount &balance) { - if (IsMineCached(*pwallet, owner) == ISMINE_SPENDABLE) { - if (lastCalculatedOwner != owner) { - mnview.CalculateOwnerRewards(owner, targetHeight); - lastCalculatedOwner = owner; - } - walletAccounts[owner].Add(balance); + CalcMissingRewardTempFix(mnview, targetHeight, *pwallet); + + mnview.ForEachAccount([&](CScript const & account) { + if (IsMineCached(*pwallet, account) == ISMINE_SPENDABLE) { + mnview.CalculateOwnerRewards(account, targetHeight); + mnview.ForEachBalance([&](CScript const & owner, CTokenAmount balance) { + return account == owner && walletAccounts[owner].Add(balance); + }, {account, DCT_ID{}}); } - return true; }); diff --git a/src/masternodes/rpc_accounts.cpp b/src/masternodes/rpc_accounts.cpp index 5a483291c8..6febb208e5 100644 --- a/src/masternodes/rpc_accounts.cpp +++ b/src/masternodes/rpc_accounts.cpp @@ -365,27 +365,28 @@ UniValue listaccounts(const JSONRPCRequest& request) { CCustomCSView mnview(*pcustomcsview); auto targetHeight = ::ChainActive().Height() + 1; - // ForEachBalance is in account order, so we only need to check if the - // last record is the same as the current one to know whether we can skip - // CalculateOwnerRewards or if it needs to be called. - CScript lastCalculatedOwner; + CalcMissingRewardTempFix(mnview, targetHeight, *pwallet); - mnview.ForEachBalance([&](const CScript &owner, const CTokenAmount &balance) { - if (isMineOnly && IsMineCached(*pwallet, owner) != ISMINE_SPENDABLE) { + mnview.ForEachAccount([&](CScript const & account) { + + if (isMineOnly && IsMineCached(*pwallet, account) != ISMINE_SPENDABLE) { return true; } - if (lastCalculatedOwner != owner) { - mnview.CalculateOwnerRewards(owner, targetHeight); - lastCalculatedOwner = owner; - } + mnview.CalculateOwnerRewards(account, targetHeight); - ret.push_back(accountToJSON(owner, balance, verbose, indexed_amounts)); + // output the relavant balances only for account + mnview.ForEachBalance([&](CScript const & owner, CTokenAmount balance) { + if (account != owner) { + return false; + } + ret.push_back(accountToJSON(owner, balance, verbose, indexed_amounts)); + return --limit != 0; + }, {account, start.tokenID}); start.tokenID = DCT_ID{}; // reset to start id - - return --limit != 0; - }, {start.owner, start.tokenID}); + return limit != 0; + }, start.owner); return GetRPCResultCache().Set(request, ret); } @@ -559,23 +560,17 @@ UniValue gettokenbalances(const JSONRPCRequest& request) { CCustomCSView mnview(*pcustomcsview); auto targetHeight = ::ChainActive().Height() + 1; - // ForEachBalance is in account order, so we only need to check if the - // last record is the same as the current one to know whether we can skip - // CalculateOwnerRewards or if it needs to be called. - CScript lastCalculatedOwner; + CalcMissingRewardTempFix(mnview, targetHeight, *pwallet); - mnview.ForEachBalance([&](const CScript &owner, CTokenAmount balance) { - if (IsMineCached(*pwallet, owner) == ISMINE_SPENDABLE) { - if (lastCalculatedOwner != owner) { - mnview.CalculateOwnerRewards(owner, targetHeight); - lastCalculatedOwner = owner; - } - totalBalances.Add(balance); + mnview.ForEachAccount([&](CScript const & account) { + if (IsMineCached(*pwallet, account) == ISMINE_SPENDABLE) { + mnview.CalculateOwnerRewards(account, targetHeight); + mnview.ForEachBalance([&](CScript const & owner, CTokenAmount balance) { + return account == owner && totalBalances.Add(balance); + }, {account, DCT_ID{}}); } - return true; }); - auto it = totalBalances.balances.lower_bound(start); for (size_t i = 0; it != totalBalances.balances.end() && i < limit; it++, i++) { auto bal = CTokenAmount{(*it).first, (*it).second};