Bitcoin Core  24.99.0
P2P Digital Currency
txdb.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2022 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 <chain.h>
9 #include <logging.h>
10 #include <pow.h>
11 #include <random.h>
12 #include <shutdown.h>
13 #include <uint256.h>
14 #include <util/translation.h>
15 #include <util/vector.h>
16 
17 #include <stdint.h>
18 
19 static constexpr uint8_t DB_COIN{'C'};
20 static constexpr uint8_t DB_BLOCK_FILES{'f'};
21 static constexpr uint8_t DB_BLOCK_INDEX{'b'};
22 
23 static constexpr uint8_t DB_BEST_BLOCK{'B'};
24 static constexpr uint8_t DB_HEAD_BLOCKS{'H'};
25 static constexpr uint8_t DB_FLAG{'F'};
26 static constexpr uint8_t DB_REINDEX_FLAG{'R'};
27 static constexpr uint8_t DB_LAST_BLOCK{'l'};
28 
29 // Keys used in previous version that might still be found in the DB:
30 static constexpr uint8_t DB_COINS{'c'};
31 static constexpr uint8_t DB_TXINDEX_BLOCK{'T'};
32 // uint8_t DB_TXINDEX{'t'}
33 
34 std::optional<bilingual_str> CheckLegacyTxindex(CBlockTreeDB& block_tree_db)
35 {
36  CBlockLocator ignored{};
37  if (block_tree_db.Read(DB_TXINDEX_BLOCK, ignored)) {
38  return _("The -txindex upgrade started by a previous version cannot be completed. Restart with the previous version or run a full -reindex.");
39  }
40  bool txindex_legacy_flag{false};
41  block_tree_db.ReadFlag("txindex", txindex_legacy_flag);
42  if (txindex_legacy_flag) {
43  // Disable legacy txindex and warn once about occupied disk space
44  if (!block_tree_db.WriteFlag("txindex", false)) {
45  return Untranslated("Failed to write block index db flag 'txindex'='0'");
46  }
47  return _("The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.");
48  }
49  return std::nullopt;
50 }
51 
53 {
54  std::unique_ptr<CDBIterator> cursor{m_db->NewIterator()};
55  // DB_COINS was deprecated in v0.15.0, commit
56  // 1088b02f0ccd7358d2b7076bb9e122d59d502d02
57  cursor->Seek(std::make_pair(DB_COINS, uint256{}));
58  return cursor->Valid();
59 }
60 
61 namespace {
62 
63 struct CoinEntry {
64  COutPoint* outpoint;
65  uint8_t key;
66  explicit CoinEntry(const COutPoint* ptr) : outpoint(const_cast<COutPoint*>(ptr)), key(DB_COIN) {}
67 
68  SERIALIZE_METHODS(CoinEntry, obj) { READWRITE(obj.key, obj.outpoint->hash, VARINT(obj.outpoint->n)); }
69 };
70 
71 } // namespace
72 
74  m_db_params{std::move(db_params)},
75  m_options{std::move(options)},
76  m_db{std::make_unique<CDBWrapper>(m_db_params)} { }
77 
78 void CCoinsViewDB::ResizeCache(size_t new_cache_size)
79 {
80  // We can't do this operation with an in-memory DB since we'll lose all the coins upon
81  // reset.
82  if (!m_db_params.memory_only) {
83  // Have to do a reset first to get the original `m_db` state to release its
84  // filesystem lock.
85  m_db.reset();
86  m_db_params.cache_bytes = new_cache_size;
87  m_db_params.wipe_data = false;
88  m_db = std::make_unique<CDBWrapper>(m_db_params);
89  }
90 }
91 
92 bool CCoinsViewDB::GetCoin(const COutPoint &outpoint, Coin &coin) const {
93  return m_db->Read(CoinEntry(&outpoint), coin);
94 }
95 
96 bool CCoinsViewDB::HaveCoin(const COutPoint &outpoint) const {
97  return m_db->Exists(CoinEntry(&outpoint));
98 }
99 
101  uint256 hashBestChain;
102  if (!m_db->Read(DB_BEST_BLOCK, hashBestChain))
103  return uint256();
104  return hashBestChain;
105 }
106 
107 std::vector<uint256> CCoinsViewDB::GetHeadBlocks() const {
108  std::vector<uint256> vhashHeadBlocks;
109  if (!m_db->Read(DB_HEAD_BLOCKS, vhashHeadBlocks)) {
110  return std::vector<uint256>();
111  }
112  return vhashHeadBlocks;
113 }
114 
115 bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, bool erase) {
116  CDBBatch batch(*m_db);
117  size_t count = 0;
118  size_t changed = 0;
119  assert(!hashBlock.IsNull());
120 
121  uint256 old_tip = GetBestBlock();
122  if (old_tip.IsNull()) {
123  // We may be in the middle of replaying.
124  std::vector<uint256> old_heads = GetHeadBlocks();
125  if (old_heads.size() == 2) {
126  assert(old_heads[0] == hashBlock);
127  old_tip = old_heads[1];
128  }
129  }
130 
131  // In the first batch, mark the database as being in the middle of a
132  // transition from old_tip to hashBlock.
133  // A vector is used for future extensibility, as we may want to support
134  // interrupting after partial writes from multiple independent reorgs.
135  batch.Erase(DB_BEST_BLOCK);
136  batch.Write(DB_HEAD_BLOCKS, Vector(hashBlock, old_tip));
137 
138  for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
139  if (it->second.flags & CCoinsCacheEntry::DIRTY) {
140  CoinEntry entry(&it->first);
141  if (it->second.coin.IsSpent())
142  batch.Erase(entry);
143  else
144  batch.Write(entry, it->second.coin);
145  changed++;
146  }
147  count++;
148  it = erase ? mapCoins.erase(it) : std::next(it);
149  if (batch.SizeEstimate() > m_options.batch_write_bytes) {
150  LogPrint(BCLog::COINDB, "Writing partial batch of %.2f MiB\n", batch.SizeEstimate() * (1.0 / 1048576.0));
151  m_db->WriteBatch(batch);
152  batch.Clear();
154  static FastRandomContext rng;
155  if (rng.randrange(m_options.simulate_crash_ratio) == 0) {
156  LogPrintf("Simulating a crash. Goodbye.\n");
157  _Exit(0);
158  }
159  }
160  }
161  }
162 
163  // In the last batch, mark the database as consistent with hashBlock again.
164  batch.Erase(DB_HEAD_BLOCKS);
165  batch.Write(DB_BEST_BLOCK, hashBlock);
166 
167  LogPrint(BCLog::COINDB, "Writing final batch of %.2f MiB\n", batch.SizeEstimate() * (1.0 / 1048576.0));
168  bool ret = m_db->WriteBatch(batch);
169  LogPrint(BCLog::COINDB, "Committed %u changed transaction outputs (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
170  return ret;
171 }
172 
174 {
175  return m_db->EstimateSize(DB_COIN, uint8_t(DB_COIN + 1));
176 }
177 
179  return Read(std::make_pair(DB_BLOCK_FILES, nFile), info);
180 }
181 
182 bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
183  if (fReindexing)
184  return Write(DB_REINDEX_FLAG, uint8_t{'1'});
185  else
186  return Erase(DB_REINDEX_FLAG);
187 }
188 
189 void CBlockTreeDB::ReadReindexing(bool &fReindexing) {
190  fReindexing = Exists(DB_REINDEX_FLAG);
191 }
192 
194  return Read(DB_LAST_BLOCK, nFile);
195 }
196 
199 {
200 public:
201  // Prefer using CCoinsViewDB::Cursor() since we want to perform some
202  // cache warmup on instantiation.
203  CCoinsViewDBCursor(CDBIterator* pcursorIn, const uint256&hashBlockIn):
204  CCoinsViewCursor(hashBlockIn), pcursor(pcursorIn) {}
205  ~CCoinsViewDBCursor() = default;
206 
207  bool GetKey(COutPoint &key) const override;
208  bool GetValue(Coin &coin) const override;
209 
210  bool Valid() const override;
211  void Next() override;
212 
213 private:
214  std::unique_ptr<CDBIterator> pcursor;
215  std::pair<char, COutPoint> keyTmp;
216 
217  friend class CCoinsViewDB;
218 };
219 
220 std::unique_ptr<CCoinsViewCursor> CCoinsViewDB::Cursor() const
221 {
222  auto i = std::make_unique<CCoinsViewDBCursor>(
223  const_cast<CDBWrapper&>(*m_db).NewIterator(), GetBestBlock());
224  /* It seems that there are no "const iterators" for LevelDB. Since we
225  only need read operations on it, use a const-cast to get around
226  that restriction. */
227  i->pcursor->Seek(DB_COIN);
228  // Cache key of first record
229  if (i->pcursor->Valid()) {
230  CoinEntry entry(&i->keyTmp.second);
231  i->pcursor->GetKey(entry);
232  i->keyTmp.first = entry.key;
233  } else {
234  i->keyTmp.first = 0; // Make sure Valid() and GetKey() return false
235  }
236  return i;
237 }
238 
240 {
241  // Return cached key
242  if (keyTmp.first == DB_COIN) {
243  key = keyTmp.second;
244  return true;
245  }
246  return false;
247 }
248 
250 {
251  return pcursor->GetValue(coin);
252 }
253 
255 {
256  return keyTmp.first == DB_COIN;
257 }
258 
260 {
261  pcursor->Next();
262  CoinEntry entry(&keyTmp.second);
263  if (!pcursor->Valid() || !pcursor->GetKey(entry)) {
264  keyTmp.first = 0; // Invalidate cached key after last record so that Valid() and GetKey() return false
265  } else {
266  keyTmp.first = entry.key;
267  }
268 }
269 
270 bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
271  CDBBatch batch(*this);
272  for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
273  batch.Write(std::make_pair(DB_BLOCK_FILES, it->first), *it->second);
274  }
275  batch.Write(DB_LAST_BLOCK, nLastFile);
276  for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
277  batch.Write(std::make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
278  }
279  return WriteBatch(batch, true);
280 }
281 
282 bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
283  return Write(std::make_pair(DB_FLAG, name), fValue ? uint8_t{'1'} : uint8_t{'0'});
284 }
285 
286 bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
287  uint8_t ch;
288  if (!Read(std::make_pair(DB_FLAG, name), ch))
289  return false;
290  fValue = ch == uint8_t{'1'};
291  return true;
292 }
293 
294 bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex)
295 {
297  std::unique_ptr<CDBIterator> pcursor(NewIterator());
298  pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, uint256()));
299 
300  // Load m_block_index
301  while (pcursor->Valid()) {
302  if (ShutdownRequested()) return false;
303  std::pair<uint8_t, uint256> key;
304  if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) {
305  CDiskBlockIndex diskindex;
306  if (pcursor->GetValue(diskindex)) {
307  // Construct block index object
308  CBlockIndex* pindexNew = insertBlockIndex(diskindex.ConstructBlockHash());
309  pindexNew->pprev = insertBlockIndex(diskindex.hashPrev);
310  pindexNew->nHeight = diskindex.nHeight;
311  pindexNew->nFile = diskindex.nFile;
312  pindexNew->nDataPos = diskindex.nDataPos;
313  pindexNew->nUndoPos = diskindex.nUndoPos;
314  pindexNew->nVersion = diskindex.nVersion;
315  pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
316  pindexNew->nTime = diskindex.nTime;
317  pindexNew->nBits = diskindex.nBits;
318  pindexNew->nNonce = diskindex.nNonce;
319  pindexNew->nStatus = diskindex.nStatus;
320  pindexNew->nTx = diskindex.nTx;
321 
322  if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, consensusParams)) {
323  return error("%s: CheckProofOfWork failed: %s", __func__, pindexNew->ToString());
324  }
325 
326  pcursor->Next();
327  } else {
328  return error("%s: failed to read value", __func__);
329  }
330  } else {
331  break;
332  }
333  }
334 
335  return true;
336 }
int ret
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:151
uint256 hashMerkleRoot
Definition: chain.h:204
std::string ToString() const
Definition: chain.cpp:15
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:157
uint32_t nTime
Definition: chain.h:205
uint32_t nNonce
Definition: chain.h:207
uint256 GetBlockHash() const
Definition: chain.h:259
uint32_t nBits
Definition: chain.h:206
unsigned int nTx
Number of transactions in this block.
Definition: chain.h:182
int32_t nVersion
block header
Definition: chain.h:203
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:163
Access to the block database (blocks/index/)
Definition: txdb.h:87
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &info)
Definition: txdb.cpp:178
bool WriteReindexing(bool fReindexing)
Definition: txdb.cpp:182
void ReadReindexing(bool &fReindexing)
Definition: txdb.cpp:189
bool WriteBatchSync(const std::vector< std::pair< int, const CBlockFileInfo * > > &fileInfo, int nLastFile, const std::vector< const CBlockIndex * > &blockinfo)
Definition: txdb.cpp:270
bool ReadFlag(const std::string &name, bool &fValue)
Definition: txdb.cpp:286
bool ReadLastBlockFile(int &nFile)
Definition: txdb.cpp:193
bool WriteFlag(const std::string &name, bool fValue)
Definition: txdb.cpp:282
Cursor for iterating over CoinsView state.
Definition: coins.h:138
Specialization of CCoinsViewCursor to iterate over a CCoinsViewDB.
Definition: txdb.cpp:199
std::unique_ptr< CDBIterator > pcursor
Definition: txdb.cpp:214
bool GetKey(COutPoint &key) const override
Definition: txdb.cpp:239
~CCoinsViewDBCursor()=default
bool GetValue(Coin &coin) const override
Definition: txdb.cpp:249
CCoinsViewDBCursor(CDBIterator *pcursorIn, const uint256 &hashBlockIn)
Definition: txdb.cpp:203
bool Valid() const override
Definition: txdb.cpp:254
void Next() override
Definition: txdb.cpp:259
std::pair< char, COutPoint > keyTmp
Definition: txdb.cpp:215
CCoinsView backed by the coin database (chainstate/)
Definition: txdb.h:59
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
Definition: txdb.cpp:92
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether a given outpoint is unspent.
Definition: txdb.cpp:96
std::unique_ptr< CDBWrapper > m_db
Definition: txdb.h:63
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, bool erase=true) override
Do a bulk modification (multiple Coin changes + BestBlock change).
Definition: txdb.cpp:115
CCoinsViewDB(DBParams db_params, CoinsViewOptions options)
Definition: txdb.cpp:73
uint256 GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: txdb.cpp:100
std::unique_ptr< CCoinsViewCursor > Cursor() const override
Get a cursor to iterate over the whole state.
Definition: txdb.cpp:220
void ResizeCache(size_t new_cache_size) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Dynamically alter the underlying leveldb cache size.
Definition: txdb.cpp:78
CoinsViewOptions m_options
Definition: txdb.h:62
std::vector< uint256 > GetHeadBlocks() const override
Retrieve the range of blocks that may have been only partially written.
Definition: txdb.cpp:107
bool NeedsUpgrade()
Whether an unsupported database format is used.
Definition: txdb.cpp:52
size_t EstimateSize() const override
Estimate database size (0 if not implemented)
Definition: txdb.cpp:173
DBParams m_db_params
Definition: txdb.h:61
Batch of changes queued to be written to a CDBWrapper.
Definition: dbwrapper.h:87
void Erase(const K &key)
Definition: dbwrapper.h:137
size_t SizeEstimate() const
Definition: dbwrapper.h:153
void Write(const K &key, const V &value)
Definition: dbwrapper.h:112
void Clear()
Definition: dbwrapper.h:105
CDBIterator * NewIterator()
Definition: dbwrapper.h:336
bool WriteBatch(CDBBatch &batch, bool fSync=false)
Definition: dbwrapper.cpp:200
bool Read(const K &key, V &value) const
Definition: dbwrapper.h:263
bool Erase(const K &key, bool fSync=false)
Definition: dbwrapper.h:324
bool Write(const K &key, const V &value, bool fSync=false)
Definition: dbwrapper.h:289
bool Exists(const K &key) const
Definition: dbwrapper.h:305
Used to marshal pointers into hashes for db storage.
Definition: chain.h:382
uint256 hashPrev
Definition: chain.h:384
uint256 ConstructBlockHash() const
Definition: chain.h:418
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:36
A UTXO entry.
Definition: coins.h:31
Fast randomness source.
Definition: random.h:144
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
Definition: random.h:202
constexpr bool IsNull() const
Definition: uint256.h:41
256-bit opaque blob.
Definition: uint256.h:105
std::unordered_map< COutPoint, CCoinsCacheEntry, SaltedOutpointHasher > CCoinsMap
Definition: coins.h:134
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:8
#define LogPrint(category,...)
Definition: logging.h:245
bool error(const char *fmt, const Args &... args)
Definition: logging.h:261
#define LogPrintf(...)
Definition: logging.h:236
@ COINDB
Definition: logging.h:58
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params &params)
Check whether a block hash satisfies the proof-of-work requirement specified by nBits.
Definition: pow.cpp:125
const char * name
Definition: rest.cpp:46
#define VARINT(obj)
Definition: serialize.h:436
#define SERIALIZE_METHODS(cls, obj)
Implement the Serialize and Unserialize methods by delegating to a single templated static method tha...
Definition: serialize.h:176
#define READWRITE(...)
Definition: serialize.h:140
bool ShutdownRequested()
Returns true if a shutdown is requested, false otherwise.
Definition: shutdown.cpp:89
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
Definition: block.h:121
@ DIRTY
DIRTY means the CCoinsCacheEntry is potentially different from the version in the parent cache.
Definition: coins.h:116
User-controlled performance and debug options.
Definition: txdb.h:49
int simulate_crash_ratio
If non-zero, randomly exit when the database is flushed with (1/ratio) probability.
Definition: txdb.h:54
size_t batch_write_bytes
Maximum database write batch size in bytes.
Definition: txdb.h:51
Parameters that influence chain consensus.
Definition: params.h:74
Application-specific storage settings.
Definition: dbwrapper.h:41
bool wipe_data
If true, remove all existing data.
Definition: dbwrapper.h:49
size_t cache_bytes
Configures various leveldb cache settings.
Definition: dbwrapper.h:45
bool memory_only
If true, use leveldb's memory environment.
Definition: dbwrapper.h:47
static int count
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:78
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:48
static constexpr uint8_t DB_TXINDEX_BLOCK
Definition: txdb.cpp:31
static constexpr uint8_t DB_LAST_BLOCK
Definition: txdb.cpp:27
static constexpr uint8_t DB_HEAD_BLOCKS
Definition: txdb.cpp:24
static constexpr uint8_t DB_REINDEX_FLAG
Definition: txdb.cpp:26
std::optional< bilingual_str > CheckLegacyTxindex(CBlockTreeDB &block_tree_db)
Definition: txdb.cpp:34
static constexpr uint8_t DB_BEST_BLOCK
Definition: txdb.cpp:23
static constexpr uint8_t DB_COIN
Definition: txdb.cpp:19
static constexpr uint8_t DB_FLAG
Definition: txdb.cpp:25
static constexpr uint8_t DB_COINS
Definition: txdb.cpp:30
static constexpr uint8_t DB_BLOCK_FILES
Definition: txdb.cpp:20
static constexpr uint8_t DB_BLOCK_INDEX
Definition: txdb.cpp:21
AssertLockHeld(pool.cs)
assert(!tx.IsCoinBase())
std::vector< typename std::common_type< Args... >::type > Vector(Args &&... args)
Construct a vector with the specified elements.
Definition: vector.h:21