Line data Source code
1 : // Copyright (c) 2026 The Dash Core developers 2 : // Distributed under the MIT software license, see the accompanying 3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : 5 : #include <index/timestampindex.h> 6 : 7 : #include <chain.h> 8 : #include <logging.h> 9 : #include <tinyformat.h> 10 : #include <util/system.h> 11 : 12 : constexpr uint8_t DB_TIMESTAMPINDEX{'s'}; 13 : 14 : std::unique_ptr<TimestampIndex> g_timestampindex; 15 : 16 12 : TimestampIndex::DB::DB(size_t n_cache_size, bool f_memory, bool f_wipe) : 17 6 : BaseIndex::DB(gArgs.GetDataDirNet() / "indexes" / "timestampindex", n_cache_size, f_memory, f_wipe) 18 6 : { 19 12 : } 20 : 21 416 : bool TimestampIndex::DB::Write(const CTimestampIndexKey& key) 22 : { 23 416 : return CDBWrapper::Write(std::make_pair(DB_TIMESTAMPINDEX, key), true); 24 : } 25 : 26 4 : bool TimestampIndex::DB::ReadRange(uint32_t high, uint32_t low, std::vector<uint256>& hashes) 27 : { 28 4 : std::unique_ptr<CDBIterator> pcursor(NewIterator()); 29 : 30 : // Seek to the starting timestamp 31 4 : pcursor->Seek(std::make_pair(DB_TIMESTAMPINDEX, CTimestampIndexIteratorKey(low))); 32 : 33 : // Iterate through all entries in the timestamp range 34 22 : while (pcursor->Valid()) { 35 18 : std::pair<uint8_t, CTimestampIndexKey> key; 36 18 : if (pcursor->GetKey(key) && key.first == DB_TIMESTAMPINDEX && key.second.m_block_time <= high) { 37 18 : hashes.push_back(key.second.m_block_hash); 38 18 : pcursor->Next(); 39 18 : } else { 40 0 : break; 41 : } 42 : } 43 : 44 : return true; 45 4 : } 46 : 47 4 : bool TimestampIndex::DB::EraseTimestampIndex(const CTimestampIndexKey& key) 48 : { 49 4 : return CDBWrapper::Erase(std::make_pair(DB_TIMESTAMPINDEX, key)); 50 : } 51 : 52 12 : TimestampIndex::TimestampIndex(size_t n_cache_size, bool f_memory, bool f_wipe) : 53 6 : m_db(std::make_unique<TimestampIndex::DB>(n_cache_size, f_memory, f_wipe)) 54 12 : { 55 12 : } 56 : 57 12 : TimestampIndex::~TimestampIndex() = default; 58 : 59 420 : bool TimestampIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex) 60 : { 61 : // Skip genesis block 62 420 : if (pindex->nHeight == 0) return true; 63 : 64 : // Create timestamp index key from block metadata 65 416 : CTimestampIndexKey key(pindex->nTime, pindex->GetBlockHash()); 66 : 67 : // Write to database 68 416 : return m_db->Write(key); 69 420 : } 70 : 71 4 : bool TimestampIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip) 72 : { 73 4 : assert(current_tip->GetAncestor(new_tip->nHeight) == new_tip); 74 : 75 : // Erase timestamp index entries for blocks being rewound 76 8 : for (const CBlockIndex* pindex = current_tip; pindex != new_tip; pindex = pindex->pprev) { 77 : // Skip genesis block 78 4 : if (pindex->nHeight == 0) continue; 79 : 80 4 : CTimestampIndexKey key(pindex->nTime, pindex->GetBlockHash()); 81 4 : if (!m_db->EraseTimestampIndex(key)) { 82 0 : return error("%s: Failed to erase timestamp index for block %s during rewind", __func__, 83 0 : pindex->GetBlockHash().ToString()); 84 : } 85 4 : } 86 : 87 : // Call base class Rewind to update the best block pointer 88 4 : return BaseIndex::Rewind(current_tip, new_tip); 89 4 : } 90 : 91 60 : BaseIndex::DB& TimestampIndex::GetDB() const { return *m_db; } 92 : 93 4 : bool TimestampIndex::GetBlockHashes(uint32_t high, uint32_t low, std::vector<uint256>& hashes) const 94 : { 95 4 : return m_db->ReadRange(high, low, hashes); 96 : }