Bitcoin Core  22.0.0
P2P Digital Currency
txdb.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2020 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 <node/ui_interface.h>
9 #include <pow.h>
10 #include <random.h>
11 #include <shutdown.h>
12 #include <uint256.h>
13 #include <util/system.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_COINS{'c'};
21 static constexpr uint8_t DB_BLOCK_FILES{'f'};
22 static constexpr uint8_t DB_BLOCK_INDEX{'b'};
23 
24 static constexpr uint8_t DB_BEST_BLOCK{'B'};
25 static constexpr uint8_t DB_HEAD_BLOCKS{'H'};
26 static constexpr uint8_t DB_FLAG{'F'};
27 static constexpr uint8_t DB_REINDEX_FLAG{'R'};
28 static constexpr uint8_t DB_LAST_BLOCK{'l'};
29 
30 namespace {
31 
32 struct CoinEntry {
33  COutPoint* outpoint;
34  uint8_t key;
35  explicit CoinEntry(const COutPoint* ptr) : outpoint(const_cast<COutPoint*>(ptr)), key(DB_COIN) {}
36 
37  SERIALIZE_METHODS(CoinEntry, obj) { READWRITE(obj.key, obj.outpoint->hash, VARINT(obj.outpoint->n)); }
38 };
39 
40 }
41 
42 CCoinsViewDB::CCoinsViewDB(fs::path ldb_path, size_t nCacheSize, bool fMemory, bool fWipe) :
43  m_db(std::make_unique<CDBWrapper>(ldb_path, nCacheSize, fMemory, fWipe, true)),
44  m_ldb_path(ldb_path),
45  m_is_memory(fMemory) { }
46 
47 void CCoinsViewDB::ResizeCache(size_t new_cache_size)
48 {
49  // We can't do this operation with an in-memory DB since we'll lose all the coins upon
50  // reset.
51  if (!m_is_memory) {
52  // Have to do a reset first to get the original `m_db` state to release its
53  // filesystem lock.
54  m_db.reset();
55  m_db = std::make_unique<CDBWrapper>(
56  m_ldb_path, new_cache_size, m_is_memory, /*fWipe*/ false, /*obfuscate*/ true);
57  }
58 }
59 
60 bool CCoinsViewDB::GetCoin(const COutPoint &outpoint, Coin &coin) const {
61  return m_db->Read(CoinEntry(&outpoint), coin);
62 }
63 
64 bool CCoinsViewDB::HaveCoin(const COutPoint &outpoint) const {
65  return m_db->Exists(CoinEntry(&outpoint));
66 }
67 
69  uint256 hashBestChain;
70  if (!m_db->Read(DB_BEST_BLOCK, hashBestChain))
71  return uint256();
72  return hashBestChain;
73 }
74 
75 std::vector<uint256> CCoinsViewDB::GetHeadBlocks() const {
76  std::vector<uint256> vhashHeadBlocks;
77  if (!m_db->Read(DB_HEAD_BLOCKS, vhashHeadBlocks)) {
78  return std::vector<uint256>();
79  }
80  return vhashHeadBlocks;
81 }
82 
83 bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
84  CDBBatch batch(*m_db);
85  size_t count = 0;
86  size_t changed = 0;
87  size_t batch_size = (size_t)gArgs.GetArg("-dbbatchsize", nDefaultDbBatchSize);
88  int crash_simulate = gArgs.GetArg("-dbcrashratio", 0);
89  assert(!hashBlock.IsNull());
90 
91  uint256 old_tip = GetBestBlock();
92  if (old_tip.IsNull()) {
93  // We may be in the middle of replaying.
94  std::vector<uint256> old_heads = GetHeadBlocks();
95  if (old_heads.size() == 2) {
96  assert(old_heads[0] == hashBlock);
97  old_tip = old_heads[1];
98  }
99  }
100 
101  // In the first batch, mark the database as being in the middle of a
102  // transition from old_tip to hashBlock.
103  // A vector is used for future extensibility, as we may want to support
104  // interrupting after partial writes from multiple independent reorgs.
105  batch.Erase(DB_BEST_BLOCK);
106  batch.Write(DB_HEAD_BLOCKS, Vector(hashBlock, old_tip));
107 
108  for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
109  if (it->second.flags & CCoinsCacheEntry::DIRTY) {
110  CoinEntry entry(&it->first);
111  if (it->second.coin.IsSpent())
112  batch.Erase(entry);
113  else
114  batch.Write(entry, it->second.coin);
115  changed++;
116  }
117  count++;
118  CCoinsMap::iterator itOld = it++;
119  mapCoins.erase(itOld);
120  if (batch.SizeEstimate() > batch_size) {
121  LogPrint(BCLog::COINDB, "Writing partial batch of %.2f MiB\n", batch.SizeEstimate() * (1.0 / 1048576.0));
122  m_db->WriteBatch(batch);
123  batch.Clear();
124  if (crash_simulate) {
125  static FastRandomContext rng;
126  if (rng.randrange(crash_simulate) == 0) {
127  LogPrintf("Simulating a crash. Goodbye.\n");
128  _Exit(0);
129  }
130  }
131  }
132  }
133 
134  // In the last batch, mark the database as consistent with hashBlock again.
135  batch.Erase(DB_HEAD_BLOCKS);
136  batch.Write(DB_BEST_BLOCK, hashBlock);
137 
138  LogPrint(BCLog::COINDB, "Writing final batch of %.2f MiB\n", batch.SizeEstimate() * (1.0 / 1048576.0));
139  bool ret = m_db->WriteBatch(batch);
140  LogPrint(BCLog::COINDB, "Committed %u changed transaction outputs (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
141  return ret;
142 }
143 
145 {
146  return m_db->EstimateSize(DB_COIN, uint8_t(DB_COIN + 1));
147 }
148 
149 CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(gArgs.GetDataDirNet() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
150 }
151 
153  return Read(std::make_pair(DB_BLOCK_FILES, nFile), info);
154 }
155 
156 bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
157  if (fReindexing)
158  return Write(DB_REINDEX_FLAG, uint8_t{'1'});
159  else
160  return Erase(DB_REINDEX_FLAG);
161 }
162 
163 void CBlockTreeDB::ReadReindexing(bool &fReindexing) {
164  fReindexing = Exists(DB_REINDEX_FLAG);
165 }
166 
168  return Read(DB_LAST_BLOCK, nFile);
169 }
170 
173 {
174 public:
175  // Prefer using CCoinsViewDB::Cursor() since we want to perform some
176  // cache warmup on instantiation.
177  CCoinsViewDBCursor(CDBIterator* pcursorIn, const uint256&hashBlockIn):
178  CCoinsViewCursor(hashBlockIn), pcursor(pcursorIn) {}
180 
181  bool GetKey(COutPoint &key) const override;
182  bool GetValue(Coin &coin) const override;
183  unsigned int GetValueSize() const override;
184 
185  bool Valid() const override;
186  void Next() override;
187 
188 private:
189  std::unique_ptr<CDBIterator> pcursor;
190  std::pair<char, COutPoint> keyTmp;
191 
192  friend class CCoinsViewDB;
193 };
194 
195 std::unique_ptr<CCoinsViewCursor> CCoinsViewDB::Cursor() const
196 {
197  auto i = std::make_unique<CCoinsViewDBCursor>(
198  const_cast<CDBWrapper&>(*m_db).NewIterator(), GetBestBlock());
199  /* It seems that there are no "const iterators" for LevelDB. Since we
200  only need read operations on it, use a const-cast to get around
201  that restriction. */
202  i->pcursor->Seek(DB_COIN);
203  // Cache key of first record
204  if (i->pcursor->Valid()) {
205  CoinEntry entry(&i->keyTmp.second);
206  i->pcursor->GetKey(entry);
207  i->keyTmp.first = entry.key;
208  } else {
209  i->keyTmp.first = 0; // Make sure Valid() and GetKey() return false
210  }
211  return i;
212 }
213 
215 {
216  // Return cached key
217  if (keyTmp.first == DB_COIN) {
218  key = keyTmp.second;
219  return true;
220  }
221  return false;
222 }
223 
225 {
226  return pcursor->GetValue(coin);
227 }
228 
230 {
231  return pcursor->GetValueSize();
232 }
233 
235 {
236  return keyTmp.first == DB_COIN;
237 }
238 
240 {
241  pcursor->Next();
242  CoinEntry entry(&keyTmp.second);
243  if (!pcursor->Valid() || !pcursor->GetKey(entry)) {
244  keyTmp.first = 0; // Invalidate cached key after last record so that Valid() and GetKey() return false
245  } else {
246  keyTmp.first = entry.key;
247  }
248 }
249 
250 bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
251  CDBBatch batch(*this);
252  for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
253  batch.Write(std::make_pair(DB_BLOCK_FILES, it->first), *it->second);
254  }
255  batch.Write(DB_LAST_BLOCK, nLastFile);
256  for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
257  batch.Write(std::make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
258  }
259  return WriteBatch(batch, true);
260 }
261 
262 bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
263  return Write(std::make_pair(DB_FLAG, name), fValue ? uint8_t{'1'} : uint8_t{'0'});
264 }
265 
266 bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
267  uint8_t ch;
268  if (!Read(std::make_pair(DB_FLAG, name), ch))
269  return false;
270  fValue = ch == uint8_t{'1'};
271  return true;
272 }
273 
274 bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex)
275 {
276  std::unique_ptr<CDBIterator> pcursor(NewIterator());
277 
278  pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, uint256()));
279 
280  // Load m_block_index
281  while (pcursor->Valid()) {
282  if (ShutdownRequested()) return false;
283  std::pair<uint8_t, uint256> key;
284  if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) {
285  CDiskBlockIndex diskindex;
286  if (pcursor->GetValue(diskindex)) {
287  // Construct block index object
288  CBlockIndex* pindexNew = insertBlockIndex(diskindex.GetBlockHash());
289  pindexNew->pprev = insertBlockIndex(diskindex.hashPrev);
290  pindexNew->nHeight = diskindex.nHeight;
291  pindexNew->nFile = diskindex.nFile;
292  pindexNew->nDataPos = diskindex.nDataPos;
293  pindexNew->nUndoPos = diskindex.nUndoPos;
294  pindexNew->nVersion = diskindex.nVersion;
295  pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
296  pindexNew->nTime = diskindex.nTime;
297  pindexNew->nBits = diskindex.nBits;
298  pindexNew->nNonce = diskindex.nNonce;
299  pindexNew->nStatus = diskindex.nStatus;
300  pindexNew->nTx = diskindex.nTx;
301 
302  if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, consensusParams))
303  return error("%s: CheckProofOfWork failed: %s", __func__, pindexNew->ToString());
304 
305  pcursor->Next();
306  } else {
307  return error("%s: failed to read value", __func__);
308  }
309  } else {
310  break;
311  }
312  }
313 
314  return true;
315 }
316 
317 namespace {
318 
320 class CCoins
321 {
322 public:
324  bool fCoinBase;
325 
327  std::vector<CTxOut> vout;
328 
330  int nHeight;
331 
333  CCoins() : fCoinBase(false), vout(0), nHeight(0) { }
334 
335  template<typename Stream>
336  void Unserialize(Stream &s) {
337  unsigned int nCode = 0;
338  // version
339  unsigned int nVersionDummy;
340  ::Unserialize(s, VARINT(nVersionDummy));
341  // header code
342  ::Unserialize(s, VARINT(nCode));
343  fCoinBase = nCode & 1;
344  std::vector<bool> vAvail(2, false);
345  vAvail[0] = (nCode & 2) != 0;
346  vAvail[1] = (nCode & 4) != 0;
347  unsigned int nMaskCode = (nCode / 8) + ((nCode & 6) != 0 ? 0 : 1);
348  // spentness bitmask
349  while (nMaskCode > 0) {
350  unsigned char chAvail = 0;
351  ::Unserialize(s, chAvail);
352  for (unsigned int p = 0; p < 8; p++) {
353  bool f = (chAvail & (1 << p)) != 0;
354  vAvail.push_back(f);
355  }
356  if (chAvail != 0)
357  nMaskCode--;
358  }
359  // txouts themself
360  vout.assign(vAvail.size(), CTxOut());
361  for (unsigned int i = 0; i < vAvail.size(); i++) {
362  if (vAvail[i])
363  ::Unserialize(s, Using<TxOutCompression>(vout[i]));
364  }
365  // coinbase height
367  }
368 };
369 
370 }
371 
377  std::unique_ptr<CDBIterator> pcursor(m_db->NewIterator());
378  pcursor->Seek(std::make_pair(DB_COINS, uint256()));
379  if (!pcursor->Valid()) {
380  return true;
381  }
382 
383  int64_t count = 0;
384  LogPrintf("Upgrading utxo-set database...\n");
385  LogPrintf("[0%%]..."); /* Continued */
386  uiInterface.ShowProgress(_("Upgrading UTXO database").translated, 0, true);
387  size_t batch_size = 1 << 24;
388  CDBBatch batch(*m_db);
389  int reportDone = 0;
390  std::pair<unsigned char, uint256> key;
391  std::pair<unsigned char, uint256> prev_key = {DB_COINS, uint256()};
392  while (pcursor->Valid()) {
393  if (ShutdownRequested()) {
394  break;
395  }
396  if (pcursor->GetKey(key) && key.first == DB_COINS) {
397  if (count++ % 256 == 0) {
398  uint32_t high = 0x100 * *key.second.begin() + *(key.second.begin() + 1);
399  int percentageDone = (int)(high * 100.0 / 65536.0 + 0.5);
400  uiInterface.ShowProgress(_("Upgrading UTXO database").translated, percentageDone, true);
401  if (reportDone < percentageDone/10) {
402  // report max. every 10% step
403  LogPrintf("[%d%%]...", percentageDone); /* Continued */
404  reportDone = percentageDone/10;
405  }
406  }
407  CCoins old_coins;
408  if (!pcursor->GetValue(old_coins)) {
409  return error("%s: cannot parse CCoins record", __func__);
410  }
411  COutPoint outpoint(key.second, 0);
412  for (size_t i = 0; i < old_coins.vout.size(); ++i) {
413  if (!old_coins.vout[i].IsNull() && !old_coins.vout[i].scriptPubKey.IsUnspendable()) {
414  Coin newcoin(std::move(old_coins.vout[i]), old_coins.nHeight, old_coins.fCoinBase);
415  outpoint.n = i;
416  CoinEntry entry(&outpoint);
417  batch.Write(entry, newcoin);
418  }
419  }
420  batch.Erase(key);
421  if (batch.SizeEstimate() > batch_size) {
422  m_db->WriteBatch(batch);
423  batch.Clear();
424  m_db->CompactRange(prev_key, key);
425  prev_key = key;
426  }
427  pcursor->Next();
428  } else {
429  break;
430  }
431  }
432  m_db->WriteBatch(batch);
433  m_db->CompactRange({DB_COINS, uint256()}, key);
434  uiInterface.ShowProgress("", 100, false);
435  LogPrintf("[%s].\n", ShutdownRequested() ? "CANCELLED" : "DONE");
436  return !ShutdownRequested();
437 }
bool Exists(const K &key) const
Definition: dbwrapper.h:265
bool GetValue(Coin &coin) const override
Definition: txdb.cpp:224
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
Definition: txdb.cpp:60
#define VARINT(obj)
Definition: serialize.h:443
std::string ToString() const
Definition: chain.h:286
void Clear()
Definition: dbwrapper.h:66
bool ShutdownRequested()
Returns true if a shutdown is requested, false otherwise.
Definition: shutdown.cpp:87
std::unique_ptr< CCoinsViewCursor > Cursor() const override
Get a cursor to iterate over the whole state.
Definition: txdb.cpp:195
bool Upgrade()
Attempt to update from an older database format. Returns whether an error occurred.
Definition: txdb.cpp:376
#define LogPrint(category,...)
Definition: logging.h:188
Specialization of CCoinsViewCursor to iterate over a CCoinsViewDB.
Definition: txdb.cpp:172
assert(!tx.IsCoinBase())
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:144
Batch of changes queued to be written to a CDBWrapper.
Definition: dbwrapper.h:47
uint32_t nStatus
Verification status of this block.
Definition: chain.h:187
A UTXO entry.
Definition: coins.h:30
static constexpr uint8_t DB_BLOCK_INDEX
Definition: txdb.cpp:22
bool ReadLastBlockFile(int &nFile)
Definition: txdb.cpp:167
CCoinsViewDB(fs::path ldb_path, size_t nCacheSize, bool fMemory, bool fWipe)
Definition: txdb.cpp:42
unsigned int nHeight
void Erase(const K &key)
Definition: dbwrapper.h:98
std::unique_ptr< CDBIterator > pcursor
Definition: txdb.cpp:189
void ReadReindexing(bool &fReindexing)
Definition: txdb.cpp:163
void ResizeCache(size_t new_cache_size) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Dynamically alter the underlying leveldb cache size.
Definition: txdb.cpp:47
uint32_t nTime
Definition: chain.h:192
static constexpr uint8_t DB_BEST_BLOCK
Definition: txdb.cpp:24
int nFile
Which # file this block is stored in (blk?????.dat)
Definition: chain.h:153
static constexpr uint8_t DB_HEAD_BLOCKS
Definition: txdb.cpp:25
bool GetKey(COutPoint &key) const override
Definition: txdb.cpp:214
unsigned char * begin()
Definition: uint256.h:58
static constexpr uint8_t DB_LAST_BLOCK
Definition: txdb.cpp:28
bool IsNull() const
Definition: uint256.h:31
bool WriteReindexing(bool fReindexing)
Definition: txdb.cpp:156
CDBIterator * NewIterator()
Definition: dbwrapper.h:296
DIRTY means the CCoinsCacheEntry is potentially different from the version in the parent cache...
Definition: coins.h:116
std::vector< typename std::common_type< Args... >::type > Vector(Args &&... args)
Construct a vector with the specified elements.
Definition: vector.h:20
uint256 GetBlockHash() const
Definition: chain.h:246
static constexpr uint8_t DB_FLAG
Definition: txdb.cpp:26
#define VARINT_MODE(obj, mode)
Definition: serialize.h:442
bool Erase(const K &key, bool fSync=false)
Definition: dbwrapper.h:284
uint32_t nNonce
Definition: chain.h:194
unsigned int nDataPos
Byte offset within blk?????.dat where this block&#39;s data is stored.
Definition: chain.h:156
static constexpr uint8_t DB_REINDEX_FLAG
Definition: txdb.cpp:27
const char * name
Definition: rest.cpp:43
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:57
Fast randomness source.
Definition: random.h:119
uint32_t n
Definition: transaction.h:30
std::unordered_map< COutPoint, CCoinsCacheEntry, SaltedOutpointHasher > CCoinsMap
Definition: coins.h:134
uint256 hashMerkleRoot
Definition: chain.h:191
static constexpr uint8_t DB_COINS
Definition: txdb.cpp:20
void Write(const K &key, const V &value)
Definition: dbwrapper.h:73
size_t SizeEstimate() const
Definition: dbwrapper.h:114
CCoinsViewDBCursor(CDBIterator *pcursorIn, const uint256 &hashBlockIn)
Definition: txdb.cpp:177
An output of a transaction.
Definition: transaction.h:128
Used to marshal pointers into hashes for db storage.
Definition: chain.h:333
static const int64_t nDefaultDbBatchSize
-dbbatchsize default (bytes)
Definition: txdb.h:26
size_t EstimateSize() const override
Estimate database size (0 if not implemented)
Definition: txdb.cpp:144
Parameters that influence chain consensus.
Definition: params.h:70
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:74
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:26
std::pair< char, COutPoint > keyTmp
Definition: txdb.cpp:190
bool Read(const K &key, V &value) const
Definition: dbwrapper.h:231
bool m_is_memory
Definition: txdb.h:51
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether a given outpoint is unspent.
Definition: txdb.cpp:64
bool ReadFlag(const std::string &name, bool &fValue)
Definition: txdb.cpp:266
CBlockTreeDB(size_t nCacheSize, bool fMemory=false, bool fWipe=false)
Definition: txdb.cpp:149
bool WriteBatchSync(const std::vector< std::pair< int, const CBlockFileInfo *> > &fileInfo, int nLastFile, const std::vector< const CBlockIndex *> &blockinfo)
Definition: txdb.cpp:250
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &info)
Definition: txdb.cpp:152
#define SERIALIZE_METHODS(cls, obj)
Implement the Serialize and Unserialize methods by delegating to a single templated static method tha...
Definition: serialize.h:183
unsigned int nUndoPos
Byte offset within rev?????.dat where this block&#39;s undo data is stored.
Definition: chain.h:159
uint256 GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: txdb.cpp:68
int32_t nVersion
block header
Definition: chain.h:190
256-bit opaque blob.
Definition: uint256.h:124
uint256 hashPrev
Definition: chain.h:336
bool Write(const K &key, const V &value, bool fSync=false)
Definition: dbwrapper.h:257
static constexpr uint8_t DB_COIN
Definition: txdb.cpp:19
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:137
CCoinsView backed by the coin database (chainstate/)
Definition: txdb.h:46
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:588
ArgsManager gArgs
Definition: system.cpp:84
static int count
Definition: tests.c:41
void Unserialize(Stream &s, char &a)
Definition: serialize.h:215
bool LoadBlockIndexGuts(const Consensus::Params &consensusParams, std::function< CBlockIndex *(const uint256 &)> insertBlockIndex)
Definition: txdb.cpp:274
bool WriteFlag(const std::string &name, bool fValue)
Definition: txdb.cpp:262
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override
Do a bulk modification (multiple Coin changes + BestBlock change).
Definition: txdb.cpp:83
void Next() override
Definition: txdb.cpp:239
bool WriteBatch(CDBBatch &batch, bool fSync=false)
Definition: dbwrapper.cpp:183
static constexpr uint8_t DB_BLOCK_FILES
Definition: txdb.cpp:21
fs::path m_ldb_path
Definition: txdb.h:50
bool Valid() const override
Definition: txdb.cpp:234
CClientUIInterface uiInterface
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:150
uint256 GetBlockHash() const
Definition: chain.h:367
#define READWRITE(...)
Definition: serialize.h:147
#define LogPrintf(...)
Definition: logging.h:184
unsigned int GetValueSize() const override
Definition: txdb.cpp:229
bool error(const char *fmt, const Args &... args)
Definition: system.h:49
std::vector< uint256 > GetHeadBlocks() const override
Retrieve the range of blocks that may have been only partially written.
Definition: txdb.cpp:75
uint32_t nBits
Definition: chain.h:193
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
Definition: random.h:190
unsigned int nTx
Number of transactions in this block.
Definition: chain.h:169
std::unique_ptr< CDBWrapper > m_db
Definition: txdb.h:49
Cursor for iterating over CoinsView state.
Definition: coins.h:137