From b6914e812509d2d1212ca5cb106ac87043ffc730 Mon Sep 17 00:00:00 2001 From: Peter John Bushnell Date: Sat, 4 Mar 2023 00:30:01 +0800 Subject: [PATCH 1/2] Add missing CalculateOwnerRewards calls (#1766) * Add missing calc pool rewards * Add other missing CalculateOwnerRewards calls * Add fork guards --------- Co-authored-by: Jouzo <15011228+Jouzo@users.noreply.github.com> --- src/masternodes/mn_checks.cpp | 8 ++++++++ src/masternodes/validation.cpp | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/src/masternodes/mn_checks.cpp b/src/masternodes/mn_checks.cpp index 6fc1ad4c09..5eea4abb8f 100644 --- a/src/masternodes/mn_checks.cpp +++ b/src/masternodes/mn_checks.cpp @@ -1570,6 +1570,10 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor { Require(token->symbol == "BTC" && token->name == "Bitcoin" && token->IsDAT(), "Only Bitcoin can be swapped in " + obj.name); + if (height >= static_cast(consensus.NextNetworkUpgradeHeight)) { + mnview.CalculateOwnerRewards(script, height); + } + Require(mnview.SubBalance(script, {id, amount})); const CTokenCurrencyPair btcUsd{"BTC", "USD"}; @@ -3130,6 +3134,10 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor { } } + if (height >= static_cast(consensus.NextNetworkUpgradeHeight)) { + mnview.CalculateOwnerRewards(obj.to, height); + } + return mnview.AddBalance(obj.to, obj.amount); } diff --git a/src/masternodes/validation.cpp b/src/masternodes/validation.cpp index 01f63ad240..6256e958d7 100644 --- a/src/masternodes/validation.cpp +++ b/src/masternodes/validation.cpp @@ -2186,6 +2186,11 @@ static void ProcessProposalEvents(const CBlockIndex* pindex, CCustomCSView& cach if (!res) { LogPrintf("Proposal fee redistribution failed: %s Address: %s Amount: %d\n", res.msg, scriptPubKey.GetHex(), amountPerVoter); } + + if (pindex->nHeight >= chainparams.GetConsensus().NextNetworkUpgradeHeight) { + subView.CalculateOwnerRewards(scriptPubKey, pindex->nHeight); + } + subView.Flush(); } From ae87d0594cb3da79ea2027c633085961975c98b2 Mon Sep 17 00:00:00 2001 From: Peter John Bushnell Date: Sat, 4 Mar 2023 00:30:25 +0800 Subject: [PATCH 2/2] 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};