From d48988ee4fb7a4e6393934cc86d0e1d11592ffdc Mon Sep 17 00:00:00 2001 From: DeFiDev M Date: Wed, 28 Oct 2020 18:10:55 +0700 Subject: [PATCH] core modifications to make tracking account balances changes possible; rpc listaccounthistory --- src/Makefile.am | 2 + src/consensus/tx_verify.cpp | 2 +- src/init.cpp | 1 + src/masternodes/accounts.cpp | 1 + src/masternodes/accountshistory.cpp | 59 +++++++++++++ src/masternodes/accountshistory.h | 67 ++++++++++++++ src/masternodes/balances.h | 1 - src/masternodes/masternodes.h | 2 + src/masternodes/mn_checks.cpp | 7 +- src/masternodes/mn_checks.h | 32 ++++++- src/masternodes/mn_rpc.cpp | 130 ++++++++++++++++++++++++++++ src/rpc/client.cpp | 2 + src/test/storage_tests.cpp | 71 +++++++++++++++ src/validation.cpp | 5 +- test/functional/feature_poolswap.py | 13 ++- 15 files changed, 383 insertions(+), 12 deletions(-) create mode 100644 src/masternodes/accountshistory.cpp create mode 100644 src/masternodes/accountshistory.h diff --git a/src/Makefile.am b/src/Makefile.am index fcae772511..82d1cba427 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -153,6 +153,7 @@ DEFI_CORE_H = \ limitedmap.h \ logging.h \ masternodes/accounts.h \ + masternodes/accountshistory.h \ masternodes/anchors.h \ masternodes/balances.h \ masternodes/communityaccounttypes.h \ @@ -362,6 +363,7 @@ libdefi_server_a_SOURCES = \ init.cpp \ dbwrapper.cpp \ masternodes/accounts.cpp \ + masternodes/accountshistory.cpp \ masternodes/anchors.cpp \ masternodes/criminals.cpp \ masternodes/govvariables/lp_daily_dfi_reward.cpp \ diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp index 36e2b0a437..480328cc74 100644 --- a/src/consensus/tx_verify.cpp +++ b/src/consensus/tx_verify.cpp @@ -220,7 +220,7 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c const auto txType = GuessCustomTxType(tx, dummy); if (NotAllowedToFail(txType)) { - auto res = ApplyCustomTx(const_cast(*mnview), inputs, tx, Params(), nSpendHeight, true); // note for 'isCheck == true' here + auto res = ApplyCustomTx(const_cast(*mnview), inputs, tx, Params(), nSpendHeight, 0, true); // note for 'isCheck == true' here; 'zero' for txn is dummy value if (!res.ok && (res.code & CustomTxErrCodes::Fatal)) { return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-customtx", res.msg); } diff --git a/src/init.cpp b/src/init.cpp index ad9b66d17a..35029c2814 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -415,6 +415,7 @@ void SetupServerArgs() hidden_args.emplace_back("-sysperms"); #endif gArgs.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + gArgs.AddArg("-acindex", strprintf("Maintain a full account history index, tracking all accounts balances changes. Used by the listaccounthistory rpc call (default: %u)", false), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); gArgs.AddArg("-blockfilterindex=", strprintf("Maintain an index of compact filters by block (default: %s, values: %s).", DEFAULT_BLOCKFILTERINDEX, ListBlockFilterTypes()) + " If is not supplied or if = 1, indexes for all known types are enabled.", diff --git a/src/masternodes/accounts.cpp b/src/masternodes/accounts.cpp index f783eb7c40..de3d35347c 100644 --- a/src/masternodes/accounts.cpp +++ b/src/masternodes/accounts.cpp @@ -81,3 +81,4 @@ Res CAccountsView::SubBalances(CScript const & owner, CBalances const & balances } return Res::Ok(); } + diff --git a/src/masternodes/accountshistory.cpp b/src/masternodes/accountshistory.cpp new file mode 100644 index 0000000000..92dc8abc96 --- /dev/null +++ b/src/masternodes/accountshistory.cpp @@ -0,0 +1,59 @@ +// Copyright (c) 2020 DeFi Blockchain Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include + +/// @attention make sure that it does not overlap with those in masternodes.cpp/tokens.cpp/undos.cpp/accounts.cpp !!! +const unsigned char CAccountsHistoryView::ByAccountHistoryKey::prefix = 'h'; // don't intersects with CMintedHeadersView::MintedHeaders::prefix due to different DB + +void CAccountsHistoryView::ForEachAccountHistory(std::function callback, AccountHistoryKey start) const +{ + ForEach([&callback] (AccountHistoryKey const & key, AccountHistoryValue const & val) { + return callback(key.owner,key.blockHeight, key.txn, val.txid, val.category, val.diff); + }, start); +} + +Res CAccountsHistoryView::SetAccountHistory(const CScript & owner, uint32_t height, uint32_t txn, const uint256 & txid, unsigned char category, TAmounts const & diff) +{ +//// left for debug: +// std::string ownerStr; +// CTxDestination dest; +// if (!ExtractDestination(owner, dest)) { +// ownerStr = owner.GetHex(); +// } else +// ownerStr = EncodeDestination(dest); +// LogPrintf("DEBUG: SetAccountHistory: owner: %s, ownerStr: %s, block: %i, txn: %d, txid: %s, diffs: %ld\n", owner.GetHex().c_str(), ownerStr.c_str(), height, txn, txid.ToString().c_str(), diff.size()); + + WriteBy(AccountHistoryKey{owner, height, txn}, AccountHistoryValue{txid, category, diff}); + return Res::Ok(); +} + +bool CAccountsHistoryView::TrackAffectedAccounts(CStorageKV const & before, MapKV const & diff, uint32_t height, uint32_t txn, const uint256 & txid, unsigned char category) { + if (!gArgs.GetBoolArg("-acindex", false)) + return false; + + std::map balancesDiff; + using TKey = std::pair; + + for (auto it = diff.lower_bound({CAccountsView::ByBalanceKey::prefix}); it != diff.end() && it->first.at(0) == CAccountsView::ByBalanceKey::prefix; ++it) { + CAmount oldAmount = 0, newAmount = 0; + + if (it->second) { + BytesToDbType(*it->second, newAmount); + } + TBytes beforeVal; + if (before.Read(it->first, beforeVal)) { + BytesToDbType(beforeVal, oldAmount); + } + TKey balanceKey; + BytesToDbType(it->first, balanceKey); + balancesDiff[balanceKey.second.owner][balanceKey.second.tokenID] = newAmount - oldAmount; + } + for (auto const & kv : balancesDiff) { + SetAccountHistory(kv.first, height, txn, txid, category, kv.second); + } + return true; +} diff --git a/src/masternodes/accountshistory.h b/src/masternodes/accountshistory.h new file mode 100644 index 0000000000..6b5514b523 --- /dev/null +++ b/src/masternodes/accountshistory.h @@ -0,0 +1,67 @@ +// Copyright (c) 2020 DeFi Blockchain Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef DEFI_MASTERNODES_ACCOUNTSHISTORY_H +#define DEFI_MASTERNODES_ACCOUNTSHISTORY_H + +#include +#include +#include +#include