diff --git a/src/flushablestorage.h b/src/flushablestorage.h index b584327be44..d017b8cb5ee 100644 --- a/src/flushablestorage.h +++ b/src/flushablestorage.h @@ -59,6 +59,7 @@ class CStorageKV { virtual bool Read(const TBytes& key, TBytes& value) const = 0; virtual std::unique_ptr NewIterator() = 0; virtual size_t SizeEstimate() const = 0; + virtual void Discard() = 0; virtual bool Flush() = 0; }; @@ -153,6 +154,11 @@ class CStorageLevelDB : public CStorageKV { begin.clear(); return result; } + void Discard() override { + end.clear(); + begin.clear(); + batch.Clear(); + } size_t SizeEstimate() const override { return batch.SizeEstimate(); } @@ -300,6 +306,9 @@ class CFlushableStorageKV : public CStorageKV { changed.clear(); return true; } + void Discard() override { + changed.clear(); + } size_t SizeEstimate() const override { return memusage::DynamicUsage(changed); } @@ -478,7 +487,7 @@ class CStorageView { } bool Flush() { return DB().Flush(); } - + void Discard() { DB().Discard(); } size_t SizeEstimate() const { return DB().SizeEstimate(); } protected: diff --git a/src/init.cpp b/src/init.cpp index 8e461d57a9a..2cce7b7d2ea 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1600,6 +1600,12 @@ bool AppInitMain(InitInterfaces& interfaces) // Ensure we are on latest DB version pcustomcsview->SetDbVersion(CCustomCSView::DbVersion); + // make account history db + paccountHistoryDB.reset(); + if (gArgs.GetBoolArg("-acindex", DEFAULT_ACINDEX)) { + paccountHistoryDB = MakeUnique(GetDataDir() / "history", nCustomCacheSize, false, fReset || fReindexChainState); + } + // If necessary, upgrade from older database format. // This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate if (!::ChainstateActive().CoinsDB().Upgrade()) { diff --git a/src/masternodes/accountshistory.cpp b/src/masternodes/accountshistory.cpp index 3880f2e44cb..b56b3b3744a 100644 --- a/src/masternodes/accountshistory.cpp +++ b/src/masternodes/accountshistory.cpp @@ -7,9 +7,7 @@ #include #include -#include - -/// @attention make sure that it does not overlap with those in masternodes.cpp/tokens.cpp/undos.cpp/accounts.cpp !!! +/// @Note it's in own database const unsigned char CAccountsHistoryView::ByAccountHistoryKey::prefix = 'h'; void CAccountsHistoryView::ForEachAccountHistory(std::function)> callback, AccountHistoryKey const & start) @@ -17,8 +15,85 @@ void CAccountsHistoryView::ForEachAccountHistory(std::function(callback, start); } -Res CAccountsHistoryView::SetAccountHistory(const AccountHistoryKey& key, const AccountHistoryValue& value) +Res CAccountsHistoryView::WriteAccountHistory(const AccountHistoryKey& key, const AccountHistoryValue& value) { WriteBy(key, value); return Res::Ok(); } + +Res CAccountsHistoryView::EraseAccountHistory(const AccountHistoryKey& key) +{ + EraseBy(key); + return Res::Ok(); +} + +CAccountHistoryStorage::CAccountHistoryStorage(const fs::path& dbName, std::size_t cacheSize, bool fMemory, bool fWipe) + : CStorageView(new CStorageLevelDB(dbName, cacheSize, fMemory, fWipe)) +{ +} + +CAccountsHistoryWriter::CAccountsHistoryWriter(CCustomCSView & storage, uint32_t height, uint32_t txn, const uint256& txid, uint8_t type, CAccountsHistoryView* historyView) + : CStorageView(new CFlushableStorageKV(storage.GetRaw())), height(height), txn(txn), txid(txid), type(type), historyView(historyView) +{ +} + +Res CAccountsHistoryWriter::AddBalance(CScript const & owner, CTokenAmount amount) +{ + auto res = CCustomCSView::AddBalance(owner, amount); + if (historyView && res.ok && amount.nValue != 0) { + diffs[owner][amount.nTokenId] += amount.nValue; + } + return res; +} + +Res CAccountsHistoryWriter::SubBalance(CScript const & owner, CTokenAmount amount) +{ + auto res = CCustomCSView::SubBalance(owner, amount); + if (historyView && res.ok && amount.nValue != 0) { + diffs[owner][amount.nTokenId] -= amount.nValue; + } + return res; +} + +bool CAccountsHistoryWriter::Flush() +{ + if (historyView) { + for (const auto& diff : diffs) { + historyView->WriteAccountHistory({diff.first, height, txn}, {txid, type, diff.second}); + } + } + return CCustomCSView::Flush(); +} + +CAccountsHistoryEraser::CAccountsHistoryEraser(CCustomCSView & storage, uint32_t height, uint32_t txn, CAccountsHistoryView* historyView) + : CStorageView(new CFlushableStorageKV(storage.GetRaw())), height(height), txn(txn), historyView(historyView) +{ +} + +Res CAccountsHistoryEraser::AddBalance(CScript const & owner, CTokenAmount) +{ + if (historyView) { + accounts.insert(owner); + } + return Res::Ok(); +} + +Res CAccountsHistoryEraser::SubBalance(CScript const & owner, CTokenAmount) +{ + if (historyView) { + accounts.insert(owner); + } + return Res::Ok(); +} + +bool CAccountsHistoryEraser::Flush() +{ + if (historyView) { + for (const auto& account : accounts) { + historyView->EraseAccountHistory({account, height, txn}); + } + } + return CCustomCSView::Flush(); +} + +std::unique_ptr paccountHistoryDB; diff --git a/src/masternodes/accountshistory.h b/src/masternodes/accountshistory.h index 13005cb7c45..3e0066a20e3 100644 --- a/src/masternodes/accountshistory.h +++ b/src/masternodes/accountshistory.h @@ -7,10 +7,10 @@ #include #include +#include #include