Branch data Line data Source code
1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : : // Copyright (c) 2009-present The Bitcoin Core developers
3 : : // Distributed under the MIT software license, see the accompanying
4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 : :
6 : : #include <txdb.h>
7 : :
8 : : #include <coins.h>
9 : : #include <dbwrapper.h>
10 : : #include <logging/timer.h>
11 : : #include <primitives/transaction.h>
12 : : #include <random.h>
13 : : #include <serialize.h>
14 : : #include <uint256.h>
15 : : #include <util/log.h>
16 : : #include <util/vector.h>
17 : :
18 : : #include <cassert>
19 : : #include <cstdlib>
20 : : #include <iterator>
21 : : #include <utility>
22 : :
23 : : static constexpr uint8_t DB_COIN{'C'};
24 : : static constexpr uint8_t DB_BEST_BLOCK{'B'};
25 : : static constexpr uint8_t DB_HEAD_BLOCKS{'H'};
26 : : // Keys used in previous version that might still be found in the DB:
27 : : static constexpr uint8_t DB_COINS{'c'};
28 : :
29 : : // Threshold for warning when writing this many dirty cache entries to disk.
30 : : static constexpr size_t WARN_FLUSH_COINS_COUNT{10'000'000};
31 : :
32 : 2211 : bool CCoinsViewDB::NeedsUpgrade()
33 : : {
34 [ + - ]: 2211 : std::unique_ptr<CDBIterator> cursor{m_db->NewIterator()};
35 : : // DB_COINS was deprecated in v0.15.0, commit
36 : : // 1088b02f0ccd7358d2b7076bb9e122d59d502d02
37 [ + - ]: 2211 : cursor->Seek(std::make_pair(DB_COINS, uint256{}));
38 [ + - ]: 4422 : return cursor->Valid();
39 : 2211 : }
40 : :
41 : : namespace {
42 : :
43 : : struct CoinEntry {
44 : : COutPoint* outpoint;
45 : : uint8_t key{DB_COIN};
46 [ + - ]: 3215340 : explicit CoinEntry(const COutPoint* ptr) : outpoint(const_cast<COutPoint*>(ptr)) {}
47 : :
48 : 15613314 : SERIALIZE_METHODS(CoinEntry, obj) { READWRITE(obj.key, obj.outpoint->hash, VARINT(obj.outpoint->n)); }
49 : : };
50 : :
51 : : } // namespace
52 : :
53 : 7984 : CCoinsViewDB::CCoinsViewDB(DBParams db_params, CoinsViewOptions options) :
54 : 7984 : m_db_params{std::move(db_params)},
55 : 7984 : m_options{std::move(options)},
56 [ + - ]: 7984 : m_db{std::make_unique<CDBWrapper>(m_db_params)} { }
57 : :
58 : 4446 : void CCoinsViewDB::ResizeCache(size_t new_cache_size)
59 : : {
60 : : // We can't do this operation with an in-memory DB since we'll lose all the coins upon
61 : : // reset.
62 [ - + ]: 4446 : if (!m_db_params.memory_only) {
63 : : // Have to do a reset first to get the original `m_db` state to release its
64 : : // filesystem lock.
65 [ # # ]: 0 : m_db.reset();
66 : 0 : m_db_params.cache_bytes = new_cache_size;
67 : 0 : m_db_params.wipe_data = false;
68 : 0 : m_db = std::make_unique<CDBWrapper>(m_db_params);
69 : : }
70 : 4446 : }
71 : :
72 : 3212683 : std::optional<Coin> CCoinsViewDB::GetCoin(const COutPoint& outpoint) const
73 : : {
74 [ + - + + ]: 3212683 : if (Coin coin; m_db->Read(CoinEntry(&outpoint), coin)) {
75 [ - + ]: 244180 : Assert(!coin.IsSpent()); // The UTXO database should never contain spent coins
76 : 244180 : return coin;
77 : 244180 : }
78 : 2968503 : return std::nullopt;
79 : : }
80 : :
81 : 833527 : std::optional<Coin> CCoinsViewDB::PeekCoin(const COutPoint& outpoint) const
82 : : {
83 : 833527 : return GetCoin(outpoint);
84 : : }
85 : :
86 : 2657 : bool CCoinsViewDB::HaveCoin(const COutPoint& outpoint) const
87 : : {
88 : 2657 : return m_db->Exists(CoinEntry(&outpoint));
89 : : }
90 : :
91 : 3470069 : uint256 CCoinsViewDB::GetBestBlock() const {
92 : 3470069 : uint256 hashBestChain;
93 [ + + ]: 3470069 : if (!m_db->Read(DB_BEST_BLOCK, hashBestChain))
94 : 13444 : return uint256();
95 : 3456625 : return hashBestChain;
96 : : }
97 : :
98 : 12956 : std::vector<uint256> CCoinsViewDB::GetHeadBlocks() const {
99 : 12956 : std::vector<uint256> vhashHeadBlocks;
100 [ + - + - ]: 12956 : if (!m_db->Read(DB_HEAD_BLOCKS, vhashHeadBlocks)) {
101 : 12956 : return std::vector<uint256>();
102 : : }
103 : 0 : return vhashHeadBlocks;
104 : 12956 : }
105 : :
106 : 3363935 : void CCoinsViewDB::BatchWrite(CoinsViewCacheCursor& cursor, const uint256& block_hash)
107 : : {
108 : 3363935 : CDBBatch batch(*m_db);
109 : 3363935 : size_t count = 0;
110 : 3363935 : const size_t dirty_count{cursor.GetDirtyCount()};
111 [ - + ]: 6727870 : assert(!block_hash.IsNull());
112 : :
113 [ + - ]: 3363935 : uint256 old_tip = GetBestBlock();
114 [ + + ]: 3363935 : if (old_tip.IsNull()) {
115 : : // We may be in the middle of replaying.
116 [ + - ]: 5431 : std::vector<uint256> old_heads = GetHeadBlocks();
117 [ - + - + ]: 5431 : if (old_heads.size() == 2) {
118 [ # # ]: 0 : if (old_heads[0] != block_hash) {
119 [ # # ]: 0 : LogError("The coins database detected an inconsistent state, likely due to a previous crash or shutdown. You will need to restart bitcoind with the -reindex-chainstate or -reindex configuration option.\n");
120 : : }
121 [ # # ]: 0 : assert(old_heads[0] == block_hash);
122 : 0 : old_tip = old_heads[1];
123 : : }
124 : 5431 : }
125 : :
126 [ - + - - ]: 3363935 : if (dirty_count > WARN_FLUSH_COINS_COUNT) LogWarning("Flushing large (%d entries) UTXO set to disk, it may take several minutes", dirty_count);
127 [ + - + - : 6727870 : LOG_TIME_MILLIS_WITH_CATEGORY(strprintf("write coins cache to disk (%d out of %d cached coins)",
+ - ]
128 : : dirty_count, cursor.GetTotalCount()), BCLog::BENCH);
129 : :
130 : : // In the first batch, mark the database as being in the middle of a
131 : : // transition from old_tip to block_hash.
132 : : // A vector is used for future extensibility, as we may want to support
133 : : // interrupting after partial writes from multiple independent reorgs.
134 [ + - ]: 3363935 : batch.Erase(DB_BEST_BLOCK);
135 [ + - + - ]: 3363935 : batch.Write(DB_HEAD_BLOCKS, Vector(block_hash, old_tip));
136 : :
137 [ + + ]: 3550410 : for (auto it{cursor.Begin()}; it != cursor.End();) {
138 [ + - ]: 186475 : if (it->second.IsDirty()) {
139 : 186475 : CoinEntry entry(&it->first);
140 [ + + ]: 186475 : if (it->second.coin.IsSpent()) {
141 [ + - ]: 15326 : batch.Erase(entry);
142 : : } else {
143 [ + - ]: 171149 : batch.Write(entry, it->second.coin);
144 : : }
145 : : }
146 : 186475 : count++;
147 : 186475 : it = cursor.NextAndMaybeErase(*it);
148 [ + - - + ]: 186475 : if (batch.ApproximateSize() > m_options.batch_write_bytes) {
149 [ # # # # : 0 : LogDebug(BCLog::COINDB, "Writing partial batch of %.2f MiB\n", batch.ApproximateSize() * (1.0 / 1048576.0));
# # # # ]
150 : :
151 [ # # ]: 0 : m_db->WriteBatch(batch);
152 [ # # ]: 0 : batch.Clear();
153 [ # # ]: 0 : if (m_options.simulate_crash_ratio) {
154 [ # # # # ]: 0 : static FastRandomContext rng;
155 [ # # ]: 0 : if (rng.randrange(m_options.simulate_crash_ratio) == 0) {
156 [ # # ]: 0 : LogError("Simulating a crash. Goodbye.");
157 : 0 : _Exit(0);
158 : : }
159 : : }
160 : : }
161 : : }
162 : :
163 : : // In the last batch, mark the database as consistent with block_hash again.
164 [ + - ]: 3363935 : batch.Erase(DB_HEAD_BLOCKS);
165 [ + - ]: 3363935 : batch.Write(DB_BEST_BLOCK, block_hash);
166 : :
167 [ + - + + : 3363935 : LogDebug(BCLog::COINDB, "Writing final batch of %.2f MiB\n", batch.ApproximateSize() * (1.0 / 1048576.0));
+ - + - ]
168 [ + - ]: 3363935 : m_db->WriteBatch(batch);
169 [ + - + + : 3363935 : LogDebug(BCLog::COINDB, "Committed %u changed transaction outputs (out of %u) to coin database...", (unsigned int)dirty_count, (unsigned int)count);
+ - ]
170 : 3363935 : }
171 : :
172 : 99320 : size_t CCoinsViewDB::EstimateSize() const
173 : : {
174 : 99320 : return m_db->EstimateSize(DB_COIN, uint8_t(DB_COIN + 1));
175 : : }
176 : :
177 : : /** Specialization of CCoinsViewCursor to iterate over a CCoinsViewDB */
178 : : class CCoinsViewDBCursor: public CCoinsViewCursor
179 : : {
180 : : public:
181 : : // Prefer using CCoinsViewDB::Cursor() since we want to perform some
182 : : // cache warmup on instantiation.
183 : 96817 : CCoinsViewDBCursor(CDBIterator* pcursorIn, const uint256& in_block_hash):
184 : 96817 : CCoinsViewCursor(in_block_hash), pcursor(pcursorIn) {}
185 : 96817 : ~CCoinsViewDBCursor() = default;
186 : :
187 : : bool GetKey(COutPoint &key) const override;
188 : : bool GetValue(Coin &coin) const override;
189 : :
190 : : bool Valid() const override;
191 : : void Next() override;
192 : :
193 : : private:
194 : : std::unique_ptr<CDBIterator> pcursor;
195 : : std::pair<char, COutPoint> keyTmp;
196 : :
197 : : friend class CCoinsViewDB;
198 : : };
199 : :
200 : 96817 : std::unique_ptr<CCoinsViewCursor> CCoinsViewDB::Cursor() const
201 : : {
202 : 96817 : auto i = std::make_unique<CCoinsViewDBCursor>(
203 : 96817 : const_cast<CDBWrapper&>(*m_db).NewIterator(), GetBestBlock());
204 : : /* It seems that there are no "const iterators" for LevelDB. Since we
205 : : only need read operations on it, use a const-cast to get around
206 : : that restriction. */
207 [ + - ]: 96817 : i->pcursor->Seek(DB_COIN);
208 : : // Cache key of first record
209 [ + - + + ]: 96817 : if (i->pcursor->Valid()) {
210 [ + - ]: 93626 : CoinEntry entry(&i->keyTmp.second);
211 [ + - ]: 93626 : i->pcursor->GetKey(entry);
212 : 93626 : i->keyTmp.first = entry.key;
213 : : } else {
214 : 3191 : i->keyTmp.first = 0; // Make sure Valid() and GetKey() return false
215 : : }
216 : 96817 : return i;
217 : 96817 : }
218 : :
219 : 4404027 : bool CCoinsViewDBCursor::GetKey(COutPoint &key) const
220 : : {
221 : : // Return cached key
222 [ + - ]: 4404027 : if (keyTmp.first == DB_COIN) {
223 : 4404027 : key = keyTmp.second;
224 : 4404027 : return true;
225 : : }
226 : : return false;
227 : : }
228 : :
229 : 4404027 : bool CCoinsViewDBCursor::GetValue(Coin &coin) const
230 : : {
231 : 4404027 : return pcursor->GetValue(coin);
232 : : }
233 : :
234 : 4498187 : bool CCoinsViewDBCursor::Valid() const
235 : : {
236 : 4498187 : return keyTmp.first == DB_COIN;
237 : : }
238 : :
239 : 4404027 : void CCoinsViewDBCursor::Next()
240 : : {
241 : 4404027 : pcursor->Next();
242 : 4404027 : CoinEntry entry(&keyTmp.second);
243 [ + + - + ]: 4404027 : if (!pcursor->Valid() || !pcursor->GetKey(entry)) {
244 : 92811 : keyTmp.first = 0; // Invalidate cached key after last record so that Valid() and GetKey() return false
245 : : } else {
246 : 4311216 : keyTmp.first = entry.key;
247 : : }
248 : 4404027 : }
|