Line data Source code
1 : // Copyright (c) 2016-2020 The PIVX Core developers 2 : // Distributed under the MIT/X11 software license, see the accompanying 3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : 5 : #include "txdb.h" 6 : 7 : // Db keys 8 : static const char DB_SAPLING_ANCHOR = 'Z'; 9 : static const char DB_SAPLING_NULLIFIER = 'S'; 10 : static const char DB_BEST_SAPLING_ANCHOR = 'z'; 11 : 12 : // Sapling 13 419 : bool CCoinsViewDB::GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const { 14 419 : if (rt == SaplingMerkleTree::empty_root()) { 15 692 : SaplingMerkleTree new_tree; 16 346 : tree = new_tree; 17 346 : return true; 18 : } 19 : 20 73 : bool read = db.Read(std::make_pair(DB_SAPLING_ANCHOR, rt), tree); 21 : 22 73 : return read; 23 : } 24 : 25 150 : bool CCoinsViewDB::GetNullifier(const uint256 &nf) const { 26 150 : bool spent = false; 27 150 : return db.Read(std::make_pair(DB_SAPLING_NULLIFIER, nf), spent); 28 : } 29 : 30 393 : uint256 CCoinsViewDB::GetBestAnchor() const { 31 393 : uint256 hashBestAnchor; 32 393 : if (!db.Read(DB_BEST_SAPLING_ANCHOR, hashBestAnchor)) 33 176 : return SaplingMerkleTree::empty_root(); 34 217 : return hashBestAnchor; 35 : } 36 : 37 810 : void BatchWriteNullifiers(CDBBatch& batch, CNullifiersMap& mapToUse, const char& dbChar) 38 : { 39 810 : size_t count = 0; 40 810 : size_t changed = 0; 41 959 : for (CNullifiersMap::iterator it = mapToUse.begin(); it != mapToUse.end();) { 42 149 : if (it->second.flags & CNullifiersCacheEntry::DIRTY) { 43 146 : if (!it->second.entered) 44 0 : batch.Erase(std::make_pair(dbChar, it->first)); 45 : else 46 146 : batch.Write(std::make_pair(dbChar, it->first), true); 47 146 : changed++; 48 : } 49 149 : count++; 50 149 : CNullifiersMap::iterator itOld = it++; 51 149 : mapToUse.erase(itOld); 52 : } 53 810 : LogPrint(BCLog::COINDB, "Committed %u changed nullifiers (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count); 54 810 : } 55 : 56 : template<typename Map, typename MapIterator, typename MapEntry, typename Tree> 57 810 : void BatchWriteAnchors(CDBBatch& batch, Map& mapToUse, const char& dbChar) 58 : { 59 810 : size_t count = 0; 60 810 : size_t changed = 0; 61 1392 : for (MapIterator it = mapToUse.begin(); it != mapToUse.end();) { 62 582 : if (it->second.flags & MapEntry::DIRTY) { 63 216 : if (!it->second.entered) 64 1 : batch.Erase(std::make_pair(dbChar, it->first)); 65 : else { 66 215 : if (it->first != Tree::empty_root()) { 67 215 : batch.Write(std::make_pair(dbChar, it->first), it->second.tree); 68 : } 69 : } 70 216 : changed++; 71 : } 72 582 : count++; 73 582 : MapIterator itOld = it++; 74 582 : mapToUse.erase(itOld); 75 : } 76 810 : LogPrint(BCLog::COINDB, "Committed %u changed sapling anchors (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count); 77 810 : } 78 : 79 810 : bool CCoinsViewDB::BatchWriteSapling(const uint256& hashSaplingAnchor, 80 : CAnchorsSaplingMap& mapSaplingAnchors, 81 : CNullifiersMap& mapSaplingNullifiers, 82 : CDBBatch& batch) { 83 : 84 810 : ::BatchWriteAnchors<CAnchorsSaplingMap, CAnchorsSaplingMap::iterator, CAnchorsSaplingCacheEntry, SaplingMerkleTree>(batch, mapSaplingAnchors, DB_SAPLING_ANCHOR); 85 810 : ::BatchWriteNullifiers(batch, mapSaplingNullifiers, DB_SAPLING_NULLIFIER); 86 1620 : if (!hashSaplingAnchor.IsNull()) 87 541 : batch.Write(DB_BEST_SAPLING_ANCHOR, hashSaplingAnchor); 88 810 : return true; 89 : }