Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2014 The Bitcoin developers
3 : // Copyright (c) 2016-2021 The PIVX Core developers
4 : // Distributed under the MIT software license, see the accompanying
5 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 :
7 : #ifndef PIVX_TXDB_H
8 : #define PIVX_TXDB_H
9 :
10 : #include "coins.h"
11 : #include "chain.h"
12 : #include "dbwrapper.h"
13 : #include "libzerocoin/Coin.h"
14 : #include "libzerocoin/CoinSpend.h"
15 :
16 : #include <map>
17 : #include <string>
18 : #include <utility>
19 : #include <vector>
20 :
21 : class CCoinsViewDBCursor;
22 : class uint256;
23 :
24 : //! No need to periodic flush if at least this much space still available.
25 : static constexpr int MAX_BLOCK_COINSDB_USAGE = 10;
26 : //! -dbcache default (MiB)
27 : static const int64_t nDefaultDbCache = 300;
28 : //! -dbbatchsize default (bytes)
29 : static const int64_t nDefaultDbBatchSize = 16 << 20;
30 : //! max. -dbcache (MiB)
31 : static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024;
32 : //! min. -dbcache (MiB)
33 : static const int64_t nMinDbCache = 4;
34 : //! Max memory allocated to block tree DB specific cache, if no -txindex (MiB)
35 : static const int64_t nMaxBlockDBCache = 2;
36 : //! Max memory allocated to block tree DB specific cache, if -txindex (MiB)
37 : // Unlike for the UTXO database, for the txindex scenario the leveldb cache make
38 : // a meaningful difference: https://github.com/bitcoin/bitcoin/pull/8273#issuecomment-229601991
39 : static const int64_t nMaxBlockDBAndTxIndexCache = 1024;
40 : //! Max memory allocated to coin DB specific cache (MiB)
41 : static const int64_t nMaxCoinsDBCache = 8;
42 :
43 : struct CDiskTxPos : public FlatFilePos
44 : {
45 : unsigned int nTxOffset; // after header
46 :
47 1008655 : SERIALIZE_METHODS(CDiskTxPos, obj)
48 : {
49 504322 : READWRITEAS(FlatFilePos, obj);
50 504322 : READWRITE(VARINT(obj.nTxOffset));
51 504322 : }
52 :
53 56443 : CDiskTxPos(const FlatFilePos& blockIn, unsigned int nTxOffsetIn) : FlatFilePos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn)
54 : {
55 : }
56 :
57 204081 : CDiskTxPos()
58 204081 : {
59 204081 : SetNull();
60 : }
61 :
62 204081 : void SetNull()
63 : {
64 204081 : FlatFilePos::SetNull();
65 204081 : nTxOffset = 0;
66 : }
67 : };
68 :
69 : /** CCoinsView backed by the LevelDB coin database (chainstate/) */
70 : class CCoinsViewDB : public CCoinsView
71 : {
72 : protected:
73 : CDBWrapper db;
74 :
75 : public:
76 : explicit CCoinsViewDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
77 :
78 : bool GetCoin(const COutPoint& outpoint, Coin& coin) const override;
79 : bool HaveCoin(const COutPoint& outpoint) const override;
80 : uint256 GetBestBlock() const override;
81 : std::vector<uint256> GetHeadBlocks() const override;
82 : CCoinsViewCursor* Cursor() const override;
83 :
84 : //! Attempt to update from an older database format. Returns whether an error occurred.
85 : bool Upgrade();
86 : size_t EstimateSize() const override;
87 :
88 : bool BatchWrite(CCoinsMap& mapCoins,
89 : const uint256& hashBlock,
90 : const uint256& hashSaplingAnchor,
91 : CAnchorsSaplingMap& mapSaplingAnchors,
92 : CNullifiersMap& mapSaplingNullifiers) override;
93 :
94 : // Sapling, the implementation of the following functions can be found in sapling_txdb.cpp.
95 : bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const override;
96 : bool GetNullifier(const uint256 &nf) const override;
97 : uint256 GetBestAnchor() const override;
98 : bool BatchWriteSapling(const uint256& hashSaplingAnchor,
99 : CAnchorsSaplingMap& mapSaplingAnchors,
100 : CNullifiersMap& mapSaplingNullifiers,
101 : CDBBatch& batch);
102 : };
103 :
104 : /** Specialization of CCoinsViewCursor to iterate over a CCoinsViewDB */
105 : class CCoinsViewDBCursor: public CCoinsViewCursor
106 : {
107 : public:
108 518 : ~CCoinsViewDBCursor() {}
109 :
110 : bool GetKey(COutPoint& key) const;
111 : bool GetValue(Coin& coin) const;
112 : unsigned int GetValueSize() const;
113 :
114 : bool Valid() const;
115 : void Next();
116 :
117 : private:
118 518 : CCoinsViewDBCursor(CDBIterator* pcursorIn, const uint256& hashBlockIn):
119 518 : CCoinsViewCursor(hashBlockIn), pcursor(pcursorIn) {}
120 : std::unique_ptr<CDBIterator> pcursor;
121 : std::pair<char, COutPoint> keyTmp;
122 :
123 : friend class CCoinsViewDB;
124 : };
125 :
126 : /** Access to the block database (blocks/index/) */
127 475 : class CBlockTreeDB : public CDBWrapper
128 : {
129 : public:
130 : explicit CBlockTreeDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
131 :
132 : CBlockTreeDB(const CBlockTreeDB&) = delete;
133 : CBlockTreeDB& operator=(const CBlockTreeDB&) = delete;
134 :
135 : bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
136 : bool WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo);
137 : bool ReadBlockFileInfo(int nFile, CBlockFileInfo& info);
138 : bool ReadLastBlockFile(int& nFile);
139 : bool WriteReindexing(bool fReindexing);
140 : bool ReadReindexing(bool& fReindexing);
141 : bool ReadTxIndex(const uint256& txid, CDiskTxPos& pos);
142 : bool WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >& vect);
143 : bool WriteFlag(const std::string& name, bool fValue);
144 : bool ReadFlag(const std::string& name, bool& fValue);
145 : bool WriteInt(const std::string& name, int nValue);
146 : bool ReadInt(const std::string& name, int& nValue);
147 : bool LoadBlockIndexGuts(std::function<CBlockIndex*(const uint256&)> insertBlockIndex);
148 : };
149 :
150 : /** Zerocoin database (zerocoin/) */
151 475 : class CZerocoinDB : public CDBWrapper
152 : {
153 : public:
154 : explicit CZerocoinDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
155 :
156 : private:
157 : CZerocoinDB(const CZerocoinDB&);
158 : void operator=(const CZerocoinDB&);
159 :
160 : public:
161 : /** Write zPIV spends to the zerocoinDB in a batch
162 : * Pair of: CBigNum -> coinSerialNumber and uint256 -> txHash.
163 : */
164 : bool WriteCoinSpendBatch(const std::vector<std::pair<CBigNum, uint256> >& spendInfo);
165 : bool ReadCoinSpend(const CBigNum& bnSerial, uint256& txHash);
166 : bool EraseCoinSpend(const CBigNum& bnSerial);
167 :
168 : /** Accumulators (only for zPoS IBD): [checksum, denom] --> block height **/
169 : bool WriteAccChecksum(const uint32_t nChecksum, const libzerocoin::CoinDenomination denom, const int nHeight);
170 : bool ReadAccChecksum(const uint32_t nChecksum, const libzerocoin::CoinDenomination denom, int& nHeightRet);
171 : bool ReadAll(std::map<std::pair<uint32_t, libzerocoin::CoinDenomination>, int>& mapCheckpoints);
172 : bool EraseAccChecksum(const uint32_t nChecksum, const libzerocoin::CoinDenomination denom);
173 : void WipeAccChecksums();
174 : };
175 :
176 357 : class AccumulatorCache
177 : {
178 : private:
179 : // underlying database
180 : CZerocoinDB* db{nullptr};
181 : // in-memory map [checksum, denom] --> block height
182 : std::map<std::pair<uint32_t, libzerocoin::CoinDenomination>, int> mapCheckpoints;
183 :
184 : public:
185 357 : explicit AccumulatorCache(CZerocoinDB* _db) : db(_db)
186 : {
187 357 : assert(db != nullptr);
188 357 : bool res = db->ReadAll(mapCheckpoints);
189 357 : assert(res);
190 357 : }
191 :
192 : Optional<int> Get(uint32_t checksum, libzerocoin::CoinDenomination denom);
193 : void Set(uint32_t checksum, libzerocoin::CoinDenomination denom, int height);
194 : void Erase(uint32_t checksum, libzerocoin::CoinDenomination denom);
195 : void Flush();
196 : void Wipe();
197 : };
198 :
199 : #endif // PIVX_TXDB_H
|