diff --git a/.gitignore b/.gitignore index 8d4f18b260971..3141961d149c7 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ src/config/bitcoin-config.h src/config/bitcoin-config.h.in src/config/stamp-h1 src/obj +src/omnicore/res/omnicore-setup-win.nsi share/setup.nsi share/qt/Info.plist @@ -171,3 +172,7 @@ dist/ /guix-build-* /ci/scratch/ + +# clangd language server +compile_commands.json +./cache/clangd/* diff --git a/src/Makefile.omnicore.include b/src/Makefile.omnicore.include index a468b1a897ab8..f6f38a2a81035 100644 --- a/src/Makefile.omnicore.include +++ b/src/Makefile.omnicore.include @@ -1,9 +1,11 @@ OMNICORE_H = \ omnicore/activation.h \ + omnicore/coinscache.h \ omnicore/consensushash.h \ omnicore/convert.h \ omnicore/createpayload.h \ omnicore/createtx.h \ + omnicore/dbaddress.h \ omnicore/dbbase.h \ omnicore/dbfees.h \ omnicore/dbspinfo.h \ @@ -16,6 +18,7 @@ OMNICORE_H = \ omnicore/errors.h \ omnicore/log.h \ omnicore/mdex.h \ + omnicore/mempool.h \ omnicore/nftdb.h \ omnicore/notifications.h \ omnicore/omnicore.h \ @@ -38,6 +41,7 @@ OMNICORE_H = \ omnicore/uint256_extensions.h \ omnicore/utilsbitcoin.h \ omnicore/utilsui.h \ + omnicore/validationinterface.h \ omnicore/version.h \ omnicore/walletfetchtxs.h \ omnicore/wallettxbuilder.h \ @@ -45,10 +49,12 @@ OMNICORE_H = \ OMNICORE_CPP = \ omnicore/activation.cpp \ + omnicore/coinscache.cpp \ omnicore/consensushash.cpp \ omnicore/convert.cpp \ omnicore/createpayload.cpp \ omnicore/createtx.cpp \ + omnicore/dbaddress.cpp \ omnicore/dbbase.cpp \ omnicore/dbfees.cpp \ omnicore/dbspinfo.cpp \ @@ -60,6 +66,7 @@ OMNICORE_CPP = \ omnicore/encoding.cpp \ omnicore/log.cpp \ omnicore/mdex.cpp \ + omnicore/mempool.cpp \ omnicore/nftdb.cpp \ omnicore/notifications.cpp \ omnicore/misc.cpp \ @@ -84,6 +91,7 @@ OMNICORE_CPP = \ omnicore/tx.cpp \ omnicore/utilsbitcoin.cpp \ omnicore/utilsui.cpp \ + omnicore/validationinterface.cpp \ omnicore/version.cpp \ omnicore/walletfetchtxs.cpp \ omnicore/wallettxbuilder.cpp \ diff --git a/src/Makefile.omnitest.include b/src/Makefile.omnitest.include index 8cb2c01322bc3..9ff3ba7442de0 100644 --- a/src/Makefile.omnitest.include +++ b/src/Makefile.omnitest.include @@ -12,6 +12,7 @@ OMNICORE_TEST_CPP = \ omnicore/test/encoding_b_tests.cpp \ omnicore/test/encoding_c_tests.cpp \ omnicore/test/exodus_tests.cpp \ + omnicore/test/iterator_tests.cpp \ omnicore/test/lock_tests.cpp \ omnicore/test/marker_tests.cpp \ omnicore/test/mbstring_tests.cpp \ diff --git a/src/coins.h b/src/coins.h index 4370b805a157d..f590050b65e43 100644 --- a/src/coins.h +++ b/src/coins.h @@ -20,69 +20,6 @@ #include #include -struct CSpentIndexKey { - uint256 txid; - unsigned int outputIndex; - - SERIALIZE_METHODS(CSpentIndexKey, obj) { - READWRITE(obj.txid, obj.outputIndex); - } - - CSpentIndexKey(uint256 t, unsigned int i) { - txid = t; - outputIndex = i; - } - - CSpentIndexKey() { - SetNull(); - } - - void SetNull() { - txid.SetNull(); - outputIndex = 0; - } -}; - -struct CSpentIndexValue { - uint256 txid; - unsigned int inputIndex; - int blockHeight; - CAmount satoshis; - int addressType; - uint256 addressHash; - - SERIALIZE_METHODS(CSpentIndexValue, obj) { - READWRITE(obj.txid, obj.inputIndex, obj.blockHeight, - obj.satoshis, obj.addressType, obj.addressHash); - } - - CSpentIndexValue(uint256 t, unsigned int i, int h, CAmount s, int type, uint256 a) { - txid = t; - inputIndex = i; - blockHeight = h; - satoshis = s; - addressType = type; - addressHash = a; - } - - CSpentIndexValue() { - SetNull(); - } - - void SetNull() { - txid.SetNull(); - inputIndex = 0; - blockHeight = 0; - satoshis = 0; - addressType = 0; - addressHash.SetNull(); - } - - bool IsNull() const { - return txid.IsNull(); - } -}; - /** * A UTXO entry. * diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 665eaa0e98673..d0482fae25936 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -182,6 +182,7 @@ class CDBIterator class CDBWrapper { + friend class COmniCoinsCache; friend const std::vector& dbwrapper_private::GetObfuscateKey(const CDBWrapper &w); private: //! custom environment this database is using (may be nullptr in case of default environment) @@ -235,15 +236,18 @@ class CDBWrapper CDBWrapper& operator=(const CDBWrapper&) = delete; template - bool Read(const K& key, V& value) const + bool Read(const K& key, V& value, const leveldb::Snapshot* snapshot = nullptr) const { CDataStream ssKey(SER_DISK, CLIENT_VERSION); ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE); ssKey << key; leveldb::Slice slKey((const char*)ssKey.data(), ssKey.size()); + auto options = readoptions; + options.snapshot = snapshot; + std::string strValue; - leveldb::Status status = pdb->Get(readoptions, slKey, &strValue); + leveldb::Status status = pdb->Get(options, slKey, &strValue); if (!status.ok()) { if (status.IsNotFound()) return false; diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 07f6c68a279aa..2a73450f87798 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -13,8 +13,6 @@ #include #include -#include // SanitizeInvalidUTF8 - #include #include #include @@ -23,9 +21,6 @@ #include #include -/** Sanitize UTF-8 encoded strings in RPC responses */ -static bool fSanitizeResponse = true; - /** WWW-Authenticate to present with 401 Unauthorized response */ static const char* WWW_AUTH_HEADER_DATA = "Basic realm=\"jsonrpc\""; @@ -148,6 +143,10 @@ static bool RPCAuthorized(const std::string& strAuth, std::string& strAuthUserna return multiUserAuthorized(strUserPass); } +namespace mastercore { + extern std::string SanitizeInvalidUTF8(const std::string&); +} + static bool HTTPReq_JSONRPC(const std::any& context, HTTPRequest* req) { // JSONRPC handles only POST @@ -207,10 +206,6 @@ static bool HTTPReq_JSONRPC(const std::any& context, HTTPRequest* req) // Send reply strReply = JSONRPCReply(result, NullUniValue, jreq.id); - if (fSanitizeResponse) { - strReply = mastercore::SanitizeInvalidUTF8(strReply); - } - // array of requests } else if (valRequest.isArray()) { if (user_has_whitelist) { @@ -235,7 +230,7 @@ static bool HTTPReq_JSONRPC(const std::any& context, HTTPRequest* req) throw JSONRPCError(RPC_PARSE_ERROR, "Top-level object parse error"); req->WriteHeader("Content-Type", "application/json"); - req->WriteReply(HTTP_OK, strReply); + req->WriteReply(HTTP_OK, mastercore::SanitizeInvalidUTF8(strReply)); } catch (const UniValue& objError) { JSONErrorReply(req, objError, jreq.id); return false; diff --git a/src/init.cpp b/src/init.cpp index ebeab21dd5b63..f3dc1f8412173 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -143,10 +143,8 @@ static const bool DEFAULT_REST_ENABLE = false; static const char* DEFAULT_ASMAP_FILENAME="ip_asn.map"; // Omni Core initialization and shutdown handlers -extern int mastercore_init(); +extern int mastercore_init(node::NodeContext&); extern int mastercore_shutdown(); -extern int CheckWalletUpdate(); -extern std::optional> g_context; /** * The PID file facilities. @@ -333,7 +331,6 @@ void Shutdown(NodeContext& node) node.fee_estimator.reset(); node.chainman.reset(); node.scheduler.reset(); - g_context.reset(); try { if (!fs::remove(GetPidFile(*node.args))) { @@ -360,7 +357,6 @@ static void HandleSIGTERM(int) static void HandleSIGHUP(int) { LogInstance().m_reopen_file = true; - fReopenOmniCoreLog = true; } #else static BOOL WINAPI consoleCtrlHandler(DWORD dwCtrlType) @@ -610,7 +606,6 @@ void SetupServerArgs(ArgsManager& argsman) argsman.AddArg("-server", "Accept command line and JSON-RPC commands", ArgsManager::ALLOW_ANY, OptionsCategory::RPC); argsman.AddArg("-startclean", "Clear all persistence files on startup; triggers reparsing of Omni transactions (default: 0)", false, OptionsCategory::OMNI); - argsman.AddArg("-omnitxcache", "The maximum number of transactions in the input transaction cache (default: 500000)", false, OptionsCategory::OMNI); argsman.AddArg("-omniprogressfrequency", "Time in seconds after which the initial scanning progress is reported (default: 30)", false, OptionsCategory::OMNI); argsman.AddArg("-omniseedblockfilter", "Set skipping of blocks without Omni transactions during initial scan (default: 1)", false, OptionsCategory::OMNI); argsman.AddArg("-omniskipstoringstate", "Don't store state during initial synchronization until block n (faster, but may have to restart syncing after a shutdown)(default: 770000)", false, OptionsCategory::OMNI); @@ -912,44 +907,6 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb nLocalServices = ServiceFlags(nLocalServices | NODE_COMPACT_FILTERS); } - if (!gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) { - const fs::path configPathInfo = GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME).c_str()); - // ask the user if they would like us to modify their config file for them - auto msg = _("Disabled transaction index detected.\n\n" - "Omni Core requires an enabled transaction index. To enable " - "transaction indexing, please use the \"-txindex\" option as " - "command line argument or add \"txindex=1\" to your client " - "configuration file within your data directory.\n\n" - "Configuration file: "); // allow translation of main text body while still allowing differing config file string - msg += _((configPathInfo.string() + "\n\n").c_str()); - msg += _("Would you like Omni Core to attempt to update your configuration file accordingly?"); - bool fRet = uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_INFORMATION | CClientUIInterface::BTN_OK | CClientUIInterface::MODAL | CClientUIInterface::BTN_ABORT); - if (fRet) { - // add txindex=1 to config file in GetConfigFile() - FILE *fp = fopen(configPathInfo.string().c_str(), "at"); - if (!fp) { - auto failMsg = _("Unable to update configuration file at:\n"); - failMsg += _((configPathInfo.string() + "\n\n").c_str()); - failMsg += _("The file may be write protected or you may not have the required permissions to edit it.\n"); - failMsg += _("Please add txindex=1 to your configuration file manually.\n\nOmni Core will now shutdown."); - return InitError(failMsg); - } - fprintf(fp, "\ntxindex=1\n"); - fflush(fp); - fclose(fp); - auto strUpdated = _("Your configuration file has been updated.\n\n" - "Omni Core will now shutdown - please restart the client for your new configuration to take effect."); - uiInterface.ThreadSafeMessageBox(strUpdated, "", CClientUIInterface::MSG_INFORMATION | CClientUIInterface::BTN_OK | CClientUIInterface::MODAL); - return false; - } else { - return InitError(_("Please add txindex=1 to your configuration file manually.\n\nOmni Core will now shutdown.")); - } - } - - if (args.GetIntArg("-prune", 0) || args.GetBoolArg("-reindex-chainstate", false)) { - gArgs.SoftSetBoolArg("-txindex", false); - } - if (args.GetIntArg("-prune", 0)) { if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) return InitError(_("Prune mode is incompatible with -txindex.")); @@ -1469,9 +1426,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) } #endif - // restore txindex - gArgs.SoftSetBoolArg("-txindex", true); - // ********************************************************* Step 7: load block chain fReindex = args.GetBoolArg("-reindex", false); @@ -1589,10 +1543,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) return false; } - if (fAddressIndex != args.GetBoolArg("-experimental-btc-balances", DEFAULT_ADDRINDEX)) { - return InitError(_("You need to rebuild the database using -reindex-chainstate to change -experimental-btc-balances")); - } - ChainstateManager& chainman = *Assert(node.chainman); assert(!node.peerman); @@ -1626,12 +1576,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) } } - g_context = std::ref(node); - - uiInterface.InitMessage(_("Parsing Omni Layer transactions...").translated); - - mastercore_init(); - // ********************************************************* Step 9: load wallet for (const auto& client : node.chain_clients) { if (!client->load()) { @@ -1639,8 +1583,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) } } - // Omni Core code should be initialized and wallet should now be loaded, perform an initial populat$ - CheckWalletUpdate(); + mastercore_init(node); // ********************************************************* Step 10: data directory maintenance diff --git a/src/key_io.cpp b/src/key_io.cpp index 5b375e267bafd..d77829e04669e 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -306,42 +306,3 @@ bool IsValidDestinationString(const std::string& str) { return IsValidDestinationString(str, Params()); } - -bool DecodeIndexKey(const std::string &str, uint256 &hashBytes, int &type) -{ - CTxDestination dest = DecodeDestination(str); - if (IsValidDestination(dest)) - { - const PKHash *keyID = std::get_if(&dest); - if(keyID) - { - memcpy(&hashBytes, keyID, 20); - type = 1; - return true; - } - - const ScriptHash *scriptID = std::get_if(&dest); - if(scriptID) - { - memcpy(&hashBytes, scriptID, 20); - type = 2; - return true; - } - - const WitnessV0ScriptHash *witnessV0ScriptID = std::get_if(&dest); - if (witnessV0ScriptID) { - memcpy(&hashBytes, witnessV0ScriptID, 32); - type = 3; - return true; - } - - const WitnessV0KeyHash *witnessV0KeyID = std::get_if(&dest); - if (witnessV0KeyID) { - memcpy(&hashBytes, witnessV0KeyID, 20); - type = 4; - return true; - } - } - - return false; -} diff --git a/src/key_io.h b/src/key_io.h index 53294453f8bd3..07b80c4b859fe 100644 --- a/src/key_io.h +++ b/src/key_io.h @@ -27,6 +27,4 @@ CTxDestination DecodeDestination(const std::string& str, std::string& error_msg, bool IsValidDestinationString(const std::string& str); bool IsValidDestinationString(const std::string& str, const CChainParams& params); -bool DecodeIndexKey(const std::string& str, uint256& hashBytes, int& type); - #endif // BITCOIN_KEY_IO_H diff --git a/src/logging.cpp b/src/logging.cpp index 8e7162926bc0c..f979ff83ec5cd 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -40,12 +40,6 @@ BCLog::Logger& LogInstance() bool fLogIPs = DEFAULT_LOGIPS; -/** Flag to indicate, whether the Omni Core log file should be reopened. */ -std::atomic fReopenOmniCoreLog(false); - -/** override to print to omni log to console */ -std::atomic fOmniCoreConsoleLog(false); - static int FileWriteStr(const std::string &str, FILE *fp) { return fwrite(str.data(), 1, str.size(), fp); @@ -290,8 +284,6 @@ std::string LogCategoryToStr(BCLog::LogFlags category) case BCLog::LogFlags::LOCK: return "lock"; #endif - case BCLog::HANDLER: - return "handler"; case BCLog::LogFlags::UTIL: return "util"; case BCLog::LogFlags::BLOCKSTORE: diff --git a/src/logging.h b/src/logging.h index 7c96280b48f76..fe91ee43a5805 100644 --- a/src/logging.h +++ b/src/logging.h @@ -34,12 +34,6 @@ struct LogCategory { bool active; }; -/** Flag to indicate, whether the Omni Core log file should be reopened. */ -extern std::atomic fReopenOmniCoreLog; - -/** override to print to omni log to console */ -extern std::atomic fOmniCoreConsoleLog; - namespace BCLog { enum LogFlags : uint32_t { NONE = 0, @@ -72,7 +66,6 @@ namespace BCLog { #endif UTIL = (1 << 25), BLOCKSTORE = (1 << 26), - HANDLER = (1 << 27), ALL = ~(uint32_t)0, }; enum class Level { diff --git a/src/omnicore/activation.cpp b/src/omnicore/activation.cpp index cd3d6cf53a8a7..1466972940c75 100644 --- a/src/omnicore/activation.cpp +++ b/src/omnicore/activation.cpp @@ -9,10 +9,10 @@ #include #include +#include #include #include -#include #include #include @@ -89,12 +89,7 @@ void CheckLiveActivations(int blockHeight) std::string msgText = strprintf("Shutting down due to unsupported feature activation (%d: %s)", liveActivation.featureId, liveActivation.featureName); PrintToLog(msgText); PrintToConsole(msgText); - if (!gArgs.GetBoolArg("-overrideforcedshutdown", false)) { - fs::path persistPath = gArgs.GetDataDirNet() / "MP_persist"; - if (fs::exists(persistPath)) fs::remove_all(persistPath); // prevent the node being restarted without a reparse after forced shutdown - BlockValidationState state; - AbortNode(state, msgText); - } + MayAbortNode(msgText); } PendingActivationCompleted(liveActivation); } diff --git a/src/omnicore/coinscache.cpp b/src/omnicore/coinscache.cpp new file mode 100644 index 0000000000000..e239905af43b5 --- /dev/null +++ b/src/omnicore/coinscache.cpp @@ -0,0 +1,111 @@ + +#include +#include +#include + +#include +#include + +COmniCoinsCache::COmniCoinsCache(CCoinsViewDB& db, const fs::path& path, bool fWipe) : coinsDB(db) +{ + UpdateSnapshot(); + leveldb::Status status = Open(path, fWipe); + PrintToConsole("Loading coins cache database: %s\n", status.ToString()); +} + +void COmniCoinsCache::UpdateSnapshot() +{ + if (snapshot) { + coinsDB.m_db->pdb->ReleaseSnapshot(snapshot); + } + snapshot = coinsDB.m_db->pdb->GetSnapshot(); +} + +COmniCoinsCache::~COmniCoinsCache() +{ + // coinsDB is already closed here, snapshot is released + if (msc_debug_persistence) PrintToLog("COmniCoinsCache closed\n"); +} + +struct CCoinKey { + const COutPoint& outpoint; + static constexpr uint8_t prefix = 'c'; + SERIALIZE_METHODS(CCoinKey, obj) { + READWRITE(obj.outpoint.hash); + READWRITE(VARINT(obj.outpoint.n)); + } +}; + +/** Stores inputs to the database. */ +void COmniCoinsCache::AddInputs(const std::vector& vin) +{ + Coin coin; + CDBWriteBatch batch; + for (auto& txin : vin) { + if (GetCoin(txin.prevout, coin)) { + batch.Write(CCoinKey{txin.prevout}, coin); + } + } + WriteBatch(batch); +} + +/** Stores coins to the cache. */ +void COmniCoinsCache::AddCoins(const CTransaction& tx, int block) +{ + for (auto& txin : tx.vin) { + Uncache(txin.prevout); + } + for (auto i = 0u; i < tx.vout.size(); ++i) { + AddCoin({tx.GetHash(), i}, Coin(tx.vout[i], block, false)); + } +} + +/** Stores coin to the cache. */ +void COmniCoinsCache::AddCoin(const COutPoint& outpoint, Coin&& coin) +{ + cacheCoins.insert_or_assign(outpoint, std::move(coin)); +} + +/** Deletes coins from the cache. */ +void COmniCoinsCache::Uncache(const COutPoint& outpoint) +{ + cacheCoins.erase(outpoint); +} + +struct CCoinEntry { + const COutPoint& outpoint; + static constexpr uint8_t DB_COIN{'C'}; // txdb.cpp + SERIALIZE_METHODS(CCoinEntry, obj) { + READWRITE(DB_COIN, obj.outpoint.hash); + READWRITE(VARINT(obj.outpoint.n)); + } +}; + +/** Returns coin for given outpoint. */ +bool COmniCoinsCache::GetCoin(const COutPoint& outpoint, Coin& coin) const +{ + auto it = cacheCoins.find(outpoint); + if (it != cacheCoins.end() && !it->second.IsSpent()) { + coin = it->second; + return true; + } + return Read(CCoinKey{outpoint}, coin) + || coinsDB.m_db->Read(CCoinEntry{outpoint}, coin, snapshot); +} + +/** Block is added to the cache. */ +void COmniCoinsCache::BlockCached(const CBlockIndex* pindex) +{ + if (pindex->GetBlockHash() == coinsDB.GetBestBlock()) { + UpdateSnapshot(); + cacheCoins.clear(); + } +} + +/** Deletes all entries of the database and the cache. */ +void COmniCoinsCache::Clear() +{ + CDBBase::Clear(); + UpdateSnapshot(); + cacheCoins.clear(); +} diff --git a/src/omnicore/coinscache.h b/src/omnicore/coinscache.h new file mode 100644 index 0000000000000..8e13b927813a8 --- /dev/null +++ b/src/omnicore/coinscache.h @@ -0,0 +1,60 @@ +#ifndef BITCOIN_OMNICORE_COINSCACHE_H +#define BITCOIN_OMNICORE_COINSCACHE_H + +#include + +#include + +#include + +class CBlockIndex; +class CCoinsViewDB; +class Coin; +class COutPoint; +class CTransaction; + +/** LevelDB snapshot based storage for storing coins cache. + */ +class COmniCoinsCache : public CDBBase +{ + CCoinsViewDB& coinsDB; + const leveldb::Snapshot* snapshot = nullptr; + std::unordered_map cacheCoins; + + /** Release old snapshot and take new one. */ + void UpdateSnapshot(); + +public: + COmniCoinsCache(CCoinsViewDB& db, const fs::path& path, bool fWipe); + virtual ~COmniCoinsCache(); + + /** Deletes all entries of the database and the cache. */ + void Clear(); + + /** Stores inputs to the database. */ + void AddInputs(const std::vector& vin); + + /** Stores coins to the cache. */ + void AddCoins(const CTransaction& tx, int block); + + /** Stores coin to the cache. */ + void AddCoin(const COutPoint& outpoint, Coin&& coin); + + /** Deletes coins from the cache. */ + void Uncache(const COutPoint& outpoint); + + /** Returns coin for given outpoint. */ + bool GetCoin(const COutPoint& outpoint, Coin& coin) const; + + /** Block is added to the cache. */ + void BlockCached(const CBlockIndex* pindex); +}; + +namespace mastercore +{ + //! LevelDB snapshot based storage for storing coins cache. + extern COmniCoinsCache* pCoinsCache; +} + +#endif // BITCOIN_OMNICORE_COINSCACHE_H + diff --git a/src/omnicore/consensushash.cpp b/src/omnicore/consensushash.cpp index 172b2f946d7e3..40db4107494bb 100644 --- a/src/omnicore/consensushash.cpp +++ b/src/omnicore/consensushash.cpp @@ -27,20 +27,17 @@ bool ShouldConsensusHashBlock(int block) { return true; } - if (!gArgs.IsArgSet("-omnishowblockconsensushash")) { - return false; - } - - const std::vector& vecBlocks = gArgs.GetArgs("-omnishowblockconsensushash"); - for (std::vector::const_iterator it = vecBlocks.begin(); it != vecBlocks.end(); ++it) { - int64_t paramBlock = StrToInt64(*it, false); - if (paramBlock < 1) continue; // ignore non numeric values - if (paramBlock == block) { - return true; + static const auto vecBlocks = []() { + std::set vblocks; + for (auto& block : gArgs.GetArgs("-omnishowblockconsensushash")) { + auto paramBlock = StrToInt64(block, false); + if (paramBlock < 1) continue; // ignore non numeric values + vblocks.insert(paramBlock); } - } + return vblocks; + }(); - return false; + return vecBlocks.count(block); } // Generates a consensus string for hashing based on a tally object @@ -158,7 +155,7 @@ uint256 GetConsensusHash() // Sort alphabetically first std::map tallyMapSorted; for (std::unordered_map::iterator uoit = mp_tally_map.begin(); uoit != mp_tally_map.end(); ++uoit) { - tallyMapSorted.insert(std::make_pair(uoit->first,uoit->second)); + tallyMapSorted.emplace(uoit->first, uoit->second); } for (std::map::iterator my_it = tallyMapSorted.begin(); my_it != tallyMapSorted.end(); ++my_it) { const std::string& address = my_it->first; @@ -181,7 +178,7 @@ uint256 GetConsensusHash() const std::string& sellCombo = it->first; std::string seller = sellCombo.substr(0, sellCombo.size() - 2); std::string dataStr = GenerateConsensusString(selloffer, seller); - vecDExOffers.push_back(std::make_pair(arith_uint256(selloffer.getHash().ToString()), dataStr)); + vecDExOffers.emplace_back(UintToArith256(selloffer.getHash()), dataStr); } std::sort (vecDExOffers.begin(), vecDExOffers.end()); for (std::vector >::iterator it = vecDExOffers.begin(); it != vecDExOffers.end(); ++it) { @@ -199,7 +196,7 @@ uint256 GetConsensusHash() std::string buyer = acceptCombo.substr((acceptCombo.find("+") + 1), (acceptCombo.size()-(acceptCombo.find("+") + 1))); std::string dataStr = GenerateConsensusString(accept, buyer); std::string sortKey = strprintf("%s-%s", accept.getHash().GetHex(), buyer); - vecAccepts.push_back(std::make_pair(sortKey, dataStr)); + vecAccepts.emplace_back(sortKey, dataStr); } std::sort (vecAccepts.begin(), vecAccepts.end()); for (std::vector >::iterator it = vecAccepts.begin(); it != vecAccepts.end(); ++it) { @@ -218,7 +215,7 @@ uint256 GetConsensusHash() for (md_Set::const_iterator it = indexes.begin(); it != indexes.end(); ++it) { const CMPMetaDEx& obj = *it; std::string dataStr = GenerateConsensusString(obj); - vecMetaDExTrades.push_back(std::make_pair(arith_uint256(obj.getHash().ToString()), dataStr)); + vecMetaDExTrades.emplace_back(UintToArith256(obj.getHash()), dataStr); } } } @@ -238,7 +235,7 @@ uint256 GetConsensusHash() const CMPCrowd& crowd = it->second; uint32_t propertyId = crowd.getPropertyId(); std::string dataStr = GenerateConsensusString(crowd); - vecCrowds.push_back(std::make_pair(propertyId, dataStr)); + vecCrowds.emplace_back(propertyId, dataStr); } std::sort (vecCrowds.begin(), vecCrowds.end()); for (std::vector >::iterator it = vecCrowds.begin(); it != vecCrowds.end(); ++it) { @@ -288,7 +285,7 @@ uint256 GetMetaDExHash(const uint32_t propertyId) for (md_Set::const_iterator it = indexes.begin(); it != indexes.end(); ++it) { const CMPMetaDEx& obj = *it; std::string dataStr = GenerateConsensusString(obj); - vecMetaDExTrades.push_back(std::make_pair(arith_uint256(obj.getHash().ToString()), dataStr)); + vecMetaDExTrades.emplace_back(UintToArith256(obj.getHash()), dataStr); } } } @@ -314,7 +311,7 @@ uint256 GetBalancesHash(const uint32_t hashPropertyId) std::map tallyMapSorted; for (std::unordered_map::iterator uoit = mp_tally_map.begin(); uoit != mp_tally_map.end(); ++uoit) { - tallyMapSorted.insert(std::make_pair(uoit->first,uoit->second)); + tallyMapSorted.emplace(uoit->first, uoit->second); } for (std::map::iterator my_it = tallyMapSorted.begin(); my_it != tallyMapSorted.end(); ++my_it) { const std::string& address = my_it->first; diff --git a/src/omnicore/dbaddress.cpp b/src/omnicore/dbaddress.cpp new file mode 100644 index 0000000000000..04aba1cd7960a --- /dev/null +++ b/src/omnicore/dbaddress.cpp @@ -0,0 +1,170 @@ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include + +COmniAddressDB::COmniAddressDB(const fs::path& path, bool fWipe) +{ + leveldb::Status status = Open(path, fWipe); + PrintToConsole("Loading address index database: %s\n", status.ToString()); +} + +COmniAddressDB::~COmniAddressDB() +{ + if (msc_debug_persistence) PrintToLog("COmniAddressDB closed\n"); +} + +bool COmniAddressDB::WriteAddressIndex(const std::vector>& vect) +{ + CDBWriteBatch batch; + for (auto it = vect.begin(); it != vect.end(); it++) + batch.Write(it->first, it->second); + return WriteBatch(batch); +} + +bool COmniAddressDB::EraseAddressIndex(const std::vector>& vect) +{ + CDBWriteBatch batch; + for (auto it = vect.begin(); it != vect.end(); it++) + batch.Delete(it->first); + return WriteBatch(batch); +} + +bool COmniAddressDB::ReadAddressIndex(const uint256& addressHash, unsigned int type, + std::vector>& addressIndex, + int start, int end) +{ + if (start < 0) start = 0; + const auto checkAddress = !addressHash.IsNull(); + CDBaseIterator it{NewIterator(), CAddressIndexKey{type, addressHash, start}}; + for (; it; ++it) { + auto key = it.Key(); + if (key.type != type) break; + if (end > 0 && key.blockHeight > end) break; + if (checkAddress && key.hashBytes != addressHash) break; + if (key.blockHeight >= start) { + addressIndex.emplace_back(key, it.Value()); + } + } + return true; +} + +bool COmniAddressDB::UpdateAddressUnspentIndex(const std::vector>& vect) +{ + CDBWriteBatch batch; + for (auto it = vect.begin(); it != vect.end(); it++) { + if (it->second.IsNull()) { + batch.Delete(it->first); + } else { + batch.Write(it->first, it->second); + } + } + return WriteBatch(batch); +} + +bool COmniAddressDB::ReadAddressUnspentIndex(const uint256& addressHash, unsigned int type, + std::vector>& unspentOutputs) +{ + const auto checkAddress = !addressHash.IsNull(); + + CDBaseIterator it{NewIterator(), CAddressUnspentKey{type, addressHash}}; + for (; it; ++it) { + auto key = it.Key(); + if (key.type != type) break; + if (checkAddress && key.hashBytes != addressHash) break; + unspentOutputs.emplace_back(key, it.Value()); + } + return true; +} + +bool COmniAddressDB::WriteTimestampIndex(const CTimestampIndexKey& timestampIndex) +{ + return Write(timestampIndex, ""); +} + +bool COmniAddressDB::ReadTimestampIndex(const unsigned int high, const unsigned int low, const bool fActiveOnly, std::vector>& hashes) +{ + CDBaseIterator it{NewIterator(), CTimestampIndexKey{low}}; + for (; it; ++it) { + auto key = it.Key(); + if (key.timestamp > high) { + break; + } + hashes.emplace_back(key.blockHash, key.timestamp); + } + return true; +} + +struct CTimestampBlockIndexKey { + static constexpr uint8_t prefix = 'z'; + const uint256& hash; + template + void Serialize(Stream& s) const { + ::Serialize(s, hash); + } +}; + +bool COmniAddressDB::WriteTimestampBlockIndex(const uint256& hash, unsigned int logicalts) +{ + return Write(CTimestampBlockIndexKey{hash}, logicalts); +} + +bool COmniAddressDB::ReadTimestampBlockIndex(const uint256& hash, unsigned int& ltimestamp) +{ + return Read(CTimestampBlockIndexKey{hash}, ltimestamp); +} + +bool COmniAddressDB::ReadSpentIndex(const CSpentIndexKey& key, CSpentIndexValue& value) +{ + return Read(key, value); +} + +bool COmniAddressDB::UpdateSpentIndex(const std::vector>& vect) +{ + CDBWriteBatch batch; + for (auto it = vect.begin(); it != vect.end(); it++) { + if (it->second.IsNull()) { + batch.Delete(it->first); + } else { + batch.Write(it->first, it->second); + } + } + return WriteBatch(batch); +} + +struct CFlagKey { + static constexpr uint8_t prefix = 'F'; + const std::string& name; + template + void Serialize(Stream& s) const { + ::Serialize(s, name); + } +}; + +bool COmniAddressDB::WriteFlag(const std::string& name, bool fValue) +{ + return Write(CFlagKey{name}, fValue ? uint8_t{1} : uint8_t{0}); +} + +bool COmniAddressDB::ReadFlag(const std::string& name, bool& fValue) { + uint8_t ch; + if (!Read(CFlagKey{name}, ch)) + return false; + fValue = ch == uint8_t{1}; + return true; +} diff --git a/src/omnicore/dbaddress.h b/src/omnicore/dbaddress.h new file mode 100644 index 0000000000000..af0c968cba68c --- /dev/null +++ b/src/omnicore/dbaddress.h @@ -0,0 +1,185 @@ +#ifndef BITCOIN_OMNICORE_DBADDRESS_H +#define BITCOIN_OMNICORE_DBADDRESS_H + +#include + +#include +#include