Bitcoin Core  22.99.0
P2P Digital Currency
blockfilterindex.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018-2020 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <map>
6 
7 #include <dbwrapper.h>
9 #include <node/blockstorage.h>
10 #include <util/system.h>
11 
12 /* The index database stores three items for each block: the disk location of the encoded filter,
13  * its dSHA256 hash, and the header. Those belonging to blocks on the active chain are indexed by
14  * height, and those belonging to blocks that have been reorganized out of the active chain are
15  * indexed by block hash. This ensures that filter data for any block that becomes part of the
16  * active chain can always be retrieved, alleviating timing concerns.
17  *
18  * The filters themselves are stored in flat files and referenced by the LevelDB entries. This
19  * minimizes the amount of data written to LevelDB and keeps the database values constant size. The
20  * disk location of the next block filter to be written (represented as a FlatFilePos) is stored
21  * under the DB_FILTER_POS key.
22  *
23  * Keys for the height index have the type [DB_BLOCK_HEIGHT, uint32 (BE)]. The height is represented
24  * as big-endian so that sequential reads of filters by height are fast.
25  * Keys for the hash index have the type [DB_BLOCK_HASH, uint256].
26  */
27 constexpr uint8_t DB_BLOCK_HASH{'s'};
28 constexpr uint8_t DB_BLOCK_HEIGHT{'t'};
29 constexpr uint8_t DB_FILTER_POS{'P'};
30 
31 constexpr unsigned int MAX_FLTR_FILE_SIZE = 0x1000000; // 16 MiB
33 constexpr unsigned int FLTR_FILE_CHUNK_SIZE = 0x100000; // 1 MiB
39 constexpr size_t CF_HEADERS_CACHE_MAX_SZ{2000};
40 
41 namespace {
42 
43 struct DBVal {
44  uint256 hash;
45  uint256 header;
46  FlatFilePos pos;
47 
48  SERIALIZE_METHODS(DBVal, obj) { READWRITE(obj.hash, obj.header, obj.pos); }
49 };
50 
51 struct DBHeightKey {
52  int height;
53 
54  explicit DBHeightKey(int height_in) : height(height_in) {}
55 
56  template<typename Stream>
57  void Serialize(Stream& s) const
58  {
60  ser_writedata32be(s, height);
61  }
62 
63  template<typename Stream>
64  void Unserialize(Stream& s)
65  {
66  const uint8_t prefix{ser_readdata8(s)};
67  if (prefix != DB_BLOCK_HEIGHT) {
68  throw std::ios_base::failure("Invalid format for block filter index DB height key");
69  }
70  height = ser_readdata32be(s);
71  }
72 };
73 
74 struct DBHashKey {
75  uint256 hash;
76 
77  explicit DBHashKey(const uint256& hash_in) : hash(hash_in) {}
78 
79  SERIALIZE_METHODS(DBHashKey, obj) {
80  uint8_t prefix{DB_BLOCK_HASH};
82  if (prefix != DB_BLOCK_HASH) {
83  throw std::ios_base::failure("Invalid format for block filter index DB hash key");
84  }
85 
86  READWRITE(obj.hash);
87  }
88 };
89 
90 }; // namespace
91 
92 static std::map<BlockFilterType, BlockFilterIndex> g_filter_indexes;
93 
95  size_t n_cache_size, bool f_memory, bool f_wipe)
96  : m_filter_type(filter_type)
97 {
98  const std::string& filter_name = BlockFilterTypeName(filter_type);
99  if (filter_name.empty()) throw std::invalid_argument("unknown filter_type");
100 
101  fs::path path = gArgs.GetDataDirNet() / "indexes" / "blockfilter" / filter_name;
102  fs::create_directories(path);
103 
104  m_name = filter_name + " block filter index";
105  m_db = std::make_unique<BaseIndex::DB>(path / "db", n_cache_size, f_memory, f_wipe);
106  m_filter_fileseq = std::make_unique<FlatFileSeq>(std::move(path), "fltr", FLTR_FILE_CHUNK_SIZE);
107 }
108 
110 {
111  if (!m_db->Read(DB_FILTER_POS, m_next_filter_pos)) {
112  // Check that the cause of the read failure is that the key does not exist. Any other errors
113  // indicate database corruption or a disk failure, and starting the index would cause
114  // further corruption.
115  if (m_db->Exists(DB_FILTER_POS)) {
116  return error("%s: Cannot read current %s state; index may be corrupted",
117  __func__, GetName());
118  }
119 
120  // If the DB_FILTER_POS is not set, then initialize to the first location.
123  }
124  return BaseIndex::Init();
125 }
126 
128 {
129  const FlatFilePos& pos = m_next_filter_pos;
130 
131  // Flush current filter file to disk.
133  if (file.IsNull()) {
134  return error("%s: Failed to open filter file %d", __func__, pos.nFile);
135  }
136  if (!FileCommit(file.Get())) {
137  return error("%s: Failed to commit filter file %d", __func__, pos.nFile);
138  }
139 
140  batch.Write(DB_FILTER_POS, pos);
141  return BaseIndex::CommitInternal(batch);
142 }
143 
145 {
146  CAutoFile filein(m_filter_fileseq->Open(pos, true), SER_DISK, CLIENT_VERSION);
147  if (filein.IsNull()) {
148  return false;
149  }
150 
151  uint256 block_hash;
152  std::vector<uint8_t> encoded_filter;
153  try {
154  filein >> block_hash >> encoded_filter;
155  filter = BlockFilter(GetFilterType(), block_hash, std::move(encoded_filter));
156  }
157  catch (const std::exception& e) {
158  return error("%s: Failed to deserialize block filter from disk: %s", __func__, e.what());
159  }
160 
161  return true;
162 }
163 
165 {
166  assert(filter.GetFilterType() == GetFilterType());
167 
168  size_t data_size =
171 
172  // If writing the filter would overflow the file, flush and move to the next one.
173  if (pos.nPos + data_size > MAX_FLTR_FILE_SIZE) {
174  CAutoFile last_file(m_filter_fileseq->Open(pos), SER_DISK, CLIENT_VERSION);
175  if (last_file.IsNull()) {
176  LogPrintf("%s: Failed to open filter file %d\n", __func__, pos.nFile);
177  return 0;
178  }
179  if (!TruncateFile(last_file.Get(), pos.nPos)) {
180  LogPrintf("%s: Failed to truncate filter file %d\n", __func__, pos.nFile);
181  return 0;
182  }
183  if (!FileCommit(last_file.Get())) {
184  LogPrintf("%s: Failed to commit filter file %d\n", __func__, pos.nFile);
185  return 0;
186  }
187 
188  pos.nFile++;
189  pos.nPos = 0;
190  }
191 
192  // Pre-allocate sufficient space for filter data.
193  bool out_of_space;
194  m_filter_fileseq->Allocate(pos, data_size, out_of_space);
195  if (out_of_space) {
196  LogPrintf("%s: out of disk space\n", __func__);
197  return 0;
198  }
199 
200  CAutoFile fileout(m_filter_fileseq->Open(pos), SER_DISK, CLIENT_VERSION);
201  if (fileout.IsNull()) {
202  LogPrintf("%s: Failed to open filter file %d\n", __func__, pos.nFile);
203  return 0;
204  }
205 
206  fileout << filter.GetBlockHash() << filter.GetEncodedFilter();
207  return data_size;
208 }
209 
210 bool BlockFilterIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
211 {
212  CBlockUndo block_undo;
213  uint256 prev_header;
214 
215  if (pindex->nHeight > 0) {
216  if (!UndoReadFromDisk(block_undo, pindex)) {
217  return false;
218  }
219 
220  std::pair<uint256, DBVal> read_out;
221  if (!m_db->Read(DBHeightKey(pindex->nHeight - 1), read_out)) {
222  return false;
223  }
224 
225  uint256 expected_block_hash = pindex->pprev->GetBlockHash();
226  if (read_out.first != expected_block_hash) {
227  return error("%s: previous block header belongs to unexpected block %s; expected %s",
228  __func__, read_out.first.ToString(), expected_block_hash.ToString());
229  }
230 
231  prev_header = read_out.second.header;
232  }
233 
234  BlockFilter filter(m_filter_type, block, block_undo);
235 
236  size_t bytes_written = WriteFilterToDisk(m_next_filter_pos, filter);
237  if (bytes_written == 0) return false;
238 
239  std::pair<uint256, DBVal> value;
240  value.first = pindex->GetBlockHash();
241  value.second.hash = filter.GetHash();
242  value.second.header = filter.ComputeHeader(prev_header);
243  value.second.pos = m_next_filter_pos;
244 
245  if (!m_db->Write(DBHeightKey(pindex->nHeight), value)) {
246  return false;
247  }
248 
249  m_next_filter_pos.nPos += bytes_written;
250  return true;
251 }
252 
254  const std::string& index_name,
255  int start_height, int stop_height)
256 {
257  DBHeightKey key(start_height);
258  db_it.Seek(key);
259 
260  for (int height = start_height; height <= stop_height; ++height) {
261  if (!db_it.GetKey(key) || key.height != height) {
262  return error("%s: unexpected key in %s: expected (%c, %d)",
263  __func__, index_name, DB_BLOCK_HEIGHT, height);
264  }
265 
266  std::pair<uint256, DBVal> value;
267  if (!db_it.GetValue(value)) {
268  return error("%s: unable to read value in %s at key (%c, %d)",
269  __func__, index_name, DB_BLOCK_HEIGHT, height);
270  }
271 
272  batch.Write(DBHashKey(value.first), std::move(value.second));
273 
274  db_it.Next();
275  }
276  return true;
277 }
278 
279 bool BlockFilterIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip)
280 {
281  assert(current_tip->GetAncestor(new_tip->nHeight) == new_tip);
282 
283  CDBBatch batch(*m_db);
284  std::unique_ptr<CDBIterator> db_it(m_db->NewIterator());
285 
286  // During a reorg, we need to copy all filters for blocks that are getting disconnected from the
287  // height index to the hash index so we can still find them when the height index entries are
288  // overwritten.
289  if (!CopyHeightIndexToHashIndex(*db_it, batch, m_name, new_tip->nHeight, current_tip->nHeight)) {
290  return false;
291  }
292 
293  // The latest filter position gets written in Commit by the call to the BaseIndex::Rewind.
294  // But since this creates new references to the filter, the position should get updated here
295  // atomically as well in case Commit fails.
297  if (!m_db->WriteBatch(batch)) return false;
298 
299  return BaseIndex::Rewind(current_tip, new_tip);
300 }
301 
302 static bool LookupOne(const CDBWrapper& db, const CBlockIndex* block_index, DBVal& result)
303 {
304  // First check if the result is stored under the height index and the value there matches the
305  // block hash. This should be the case if the block is on the active chain.
306  std::pair<uint256, DBVal> read_out;
307  if (!db.Read(DBHeightKey(block_index->nHeight), read_out)) {
308  return false;
309  }
310  if (read_out.first == block_index->GetBlockHash()) {
311  result = std::move(read_out.second);
312  return true;
313  }
314 
315  // If value at the height index corresponds to an different block, the result will be stored in
316  // the hash index.
317  return db.Read(DBHashKey(block_index->GetBlockHash()), result);
318 }
319 
320 static bool LookupRange(CDBWrapper& db, const std::string& index_name, int start_height,
321  const CBlockIndex* stop_index, std::vector<DBVal>& results)
322 {
323  if (start_height < 0) {
324  return error("%s: start height (%d) is negative", __func__, start_height);
325  }
326  if (start_height > stop_index->nHeight) {
327  return error("%s: start height (%d) is greater than stop height (%d)",
328  __func__, start_height, stop_index->nHeight);
329  }
330 
331  size_t results_size = static_cast<size_t>(stop_index->nHeight - start_height + 1);
332  std::vector<std::pair<uint256, DBVal>> values(results_size);
333 
334  DBHeightKey key(start_height);
335  std::unique_ptr<CDBIterator> db_it(db.NewIterator());
336  db_it->Seek(DBHeightKey(start_height));
337  for (int height = start_height; height <= stop_index->nHeight; ++height) {
338  if (!db_it->Valid() || !db_it->GetKey(key) || key.height != height) {
339  return false;
340  }
341 
342  size_t i = static_cast<size_t>(height - start_height);
343  if (!db_it->GetValue(values[i])) {
344  return error("%s: unable to read value in %s at key (%c, %d)",
345  __func__, index_name, DB_BLOCK_HEIGHT, height);
346  }
347 
348  db_it->Next();
349  }
350 
351  results.resize(results_size);
352 
353  // Iterate backwards through block indexes collecting results in order to access the block hash
354  // of each entry in case we need to look it up in the hash index.
355  for (const CBlockIndex* block_index = stop_index;
356  block_index && block_index->nHeight >= start_height;
357  block_index = block_index->pprev) {
358  uint256 block_hash = block_index->GetBlockHash();
359 
360  size_t i = static_cast<size_t>(block_index->nHeight - start_height);
361  if (block_hash == values[i].first) {
362  results[i] = std::move(values[i].second);
363  continue;
364  }
365 
366  if (!db.Read(DBHashKey(block_hash), results[i])) {
367  return error("%s: unable to read value in %s at key (%c, %s)",
368  __func__, index_name, DB_BLOCK_HASH, block_hash.ToString());
369  }
370  }
371 
372  return true;
373 }
374 
375 bool BlockFilterIndex::LookupFilter(const CBlockIndex* block_index, BlockFilter& filter_out) const
376 {
377  DBVal entry;
378  if (!LookupOne(*m_db, block_index, entry)) {
379  return false;
380  }
381 
382  return ReadFilterFromDisk(entry.pos, filter_out);
383 }
384 
385 bool BlockFilterIndex::LookupFilterHeader(const CBlockIndex* block_index, uint256& header_out)
386 {
388 
389  bool is_checkpoint{block_index->nHeight % CFCHECKPT_INTERVAL == 0};
390 
391  if (is_checkpoint) {
392  // Try to find the block in the headers cache if this is a checkpoint height.
393  auto header = m_headers_cache.find(block_index->GetBlockHash());
394  if (header != m_headers_cache.end()) {
395  header_out = header->second;
396  return true;
397  }
398  }
399 
400  DBVal entry;
401  if (!LookupOne(*m_db, block_index, entry)) {
402  return false;
403  }
404 
405  if (is_checkpoint &&
406  m_headers_cache.size() < CF_HEADERS_CACHE_MAX_SZ) {
407  // Add to the headers cache if this is a checkpoint height.
408  m_headers_cache.emplace(block_index->GetBlockHash(), entry.header);
409  }
410 
411  header_out = entry.header;
412  return true;
413 }
414 
415 bool BlockFilterIndex::LookupFilterRange(int start_height, const CBlockIndex* stop_index,
416  std::vector<BlockFilter>& filters_out) const
417 {
418  std::vector<DBVal> entries;
419  if (!LookupRange(*m_db, m_name, start_height, stop_index, entries)) {
420  return false;
421  }
422 
423  filters_out.resize(entries.size());
424  auto filter_pos_it = filters_out.begin();
425  for (const auto& entry : entries) {
426  if (!ReadFilterFromDisk(entry.pos, *filter_pos_it)) {
427  return false;
428  }
429  ++filter_pos_it;
430  }
431 
432  return true;
433 }
434 
435 bool BlockFilterIndex::LookupFilterHashRange(int start_height, const CBlockIndex* stop_index,
436  std::vector<uint256>& hashes_out) const
437 
438 {
439  std::vector<DBVal> entries;
440  if (!LookupRange(*m_db, m_name, start_height, stop_index, entries)) {
441  return false;
442  }
443 
444  hashes_out.clear();
445  hashes_out.reserve(entries.size());
446  for (const auto& entry : entries) {
447  hashes_out.push_back(entry.hash);
448  }
449  return true;
450 }
451 
453 {
454  auto it = g_filter_indexes.find(filter_type);
455  return it != g_filter_indexes.end() ? &it->second : nullptr;
456 }
457 
458 void ForEachBlockFilterIndex(std::function<void (BlockFilterIndex&)> fn)
459 {
460  for (auto& entry : g_filter_indexes) fn(entry.second);
461 }
462 
464  size_t n_cache_size, bool f_memory, bool f_wipe)
465 {
466  auto result = g_filter_indexes.emplace(std::piecewise_construct,
467  std::forward_as_tuple(filter_type),
468  std::forward_as_tuple(filter_type,
469  n_cache_size, f_memory, f_wipe));
470  return result.second;
471 }
472 
474 {
475  return g_filter_indexes.erase(filter_type);
476 }
477 
479 {
480  g_filter_indexes.clear();
481 }
BlockFilterIndex::m_name
std::string m_name
Definition: blockfilterindex.h:28
FLTR_FILE_CHUNK_SIZE
constexpr unsigned int FLTR_FILE_CHUNK_SIZE
The pre-allocation chunk size for fltr?????.dat files.
Definition: blockfilterindex.cpp:33
GetSerializeSize
size_t GetSerializeSize(const T &t, int nVersion=0)
Definition: serialize.h:1080
FlatFilePos::nFile
int nFile
Definition: flatfile.h:16
BlockFilterTypeName
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
Definition: blockfilter.cpp:178
dbwrapper.h
SERIALIZE_METHODS
#define SERIALIZE_METHODS(cls, obj)
Implement the Serialize and Unserialize methods by delegating to a single templated static method tha...
Definition: serialize.h:183
CBlockIndex::GetAncestor
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: chain.cpp:111
assert
assert(!tx.IsCoinBase())
BlockFilter::GetFilterType
BlockFilterType GetFilterType() const
Definition: blockfilter.h:130
SER_DISK
@ SER_DISK
Definition: serialize.h:139
BlockFilter::GetBlockHash
const uint256 & GetBlockHash() const
Definition: blockfilter.h:131
CDBBatch
Batch of changes queued to be written to a CDBWrapper.
Definition: dbwrapper.h:47
ArgsManager::GetDataDirNet
const fs::path & GetDataDirNet() const
Get data directory path with appended network identifier.
Definition: system.h:282
BlockFilterIndex::m_db
std::unique_ptr< BaseIndex::DB > m_db
Definition: blockfilterindex.h:29
BlockFilterIndex::WriteFilterToDisk
size_t WriteFilterToDisk(FlatFilePos &pos, const BlockFilter &filter)
Definition: blockfilterindex.cpp:164
BaseIndex::Init
virtual bool Init()
Initialize internal state from the database and block index.
Definition: base.cpp:55
blockfilterindex.h
BlockFilter::GetEncodedFilter
const std::vector< unsigned char > & GetEncodedFilter() const
Definition: blockfilter.h:134
CAutoFile::Get
FILE * Get() const
Get wrapped FILE* without transfer of ownership.
Definition: streams.h:605
CBlockIndex::pprev
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:144
FileCommit
bool FileCommit(FILE *file)
Ensure file contents are fully committed to disk, using a platform-specific feature analogous to fsyn...
Definition: system.cpp:1094
CBlockIndex::nHeight
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:150
BlockFilterIndex
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
Definition: blockfilterindex.h:24
BlockFilter::ComputeHeader
uint256 ComputeHeader(const uint256 &prev_header) const
Compute the filter header given the previous one.
Definition: blockfilter.cpp:298
g_filter_indexes
static std::map< BlockFilterType, BlockFilterIndex > g_filter_indexes
Definition: blockfilterindex.cpp:90
BlockFilterIndex::CommitInternal
bool CommitInternal(CDBBatch &batch) override
Virtual method called internally by Commit that can be overridden to atomically commit more index sta...
Definition: blockfilterindex.cpp:127
CDBWrapper::Read
bool Read(const K &key, V &value) const
Definition: dbwrapper.h:231
DestroyBlockFilterIndex
bool DestroyBlockFilterIndex(BlockFilterType filter_type)
Destroy the block filter index with the given type.
Definition: blockfilterindex.cpp:473
DB_BLOCK_HASH
constexpr uint8_t DB_BLOCK_HASH
Definition: blockfilterindex.cpp:27
CDBIterator::Next
void Next()
Definition: dbwrapper.cpp:238
prefix
const char * prefix
Definition: rest.cpp:712
CDBBatch::Write
void Write(const K &key, const V &value)
Definition: dbwrapper.h:73
CAutoFile
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:564
ser_readdata32be
uint32_t ser_readdata32be(Stream &s)
Definition: serialize.h:113
BlockFilterIndex::Init
bool Init() override
Initialize internal state from the database and block index.
Definition: blockfilterindex.cpp:109
CDBWrapper::NewIterator
CDBIterator * NewIterator()
Definition: dbwrapper.h:296
CDBIterator::GetValue
bool GetValue(V &value)
Definition: dbwrapper.h:158
BlockFilterIndex::m_filter_type
BlockFilterType m_filter_type
Definition: blockfilterindex.h:27
Unserialize
void Unserialize(Stream &s, char &a)
Definition: serialize.h:215
values
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
Definition: scriptnum_tests.cpp:17
BaseIndex::Rewind
virtual bool Rewind(const CBlockIndex *current_tip, const CBlockIndex *new_tip)
Rewind index to an earlier chain tip during a chain reorg.
Definition: base.cpp:211
FlatFilePos
Definition: flatfile.h:14
BlockFilterIndex::LookupFilterRange
bool LookupFilterRange(int start_height, const CBlockIndex *stop_index, std::vector< BlockFilter > &filters_out) const
Get a range of filters between two heights on a chain.
Definition: blockfilterindex.cpp:415
LookupOne
static bool LookupOne(const CDBWrapper &db, const CBlockIndex *block_index, DBVal &result)
Definition: blockfilterindex.cpp:302
LogPrintf
#define LogPrintf(...)
Definition: logging.h:185
ser_readdata8
uint8_t ser_readdata8(Stream &s)
Definition: serialize.h:89
BlockFilterIndex::Rewind
bool Rewind(const CBlockIndex *current_tip, const CBlockIndex *new_tip) override
Rewind index to an earlier chain tip during a chain reorg.
Definition: blockfilterindex.cpp:279
CAutoFile::IsNull
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
Definition: streams.h:609
base_blob::ToString
std::string ToString() const
Definition: uint256.cpp:64
uint256
256-bit opaque blob.
Definition: uint256.h:124
READWRITE
#define READWRITE(...)
Definition: serialize.h:147
ser_writedata8
void ser_writedata8(Stream &s, uint8_t obj)
Definition: serialize.h:60
UndoReadFromDisk
bool UndoReadFromDisk(CBlockUndo &blockundo, const CBlockIndex *pindex)
Definition: blockstorage.cpp:137
LookupRange
static bool LookupRange(CDBWrapper &db, const std::string &index_name, int start_height, const CBlockIndex *stop_index, std::vector< DBVal > &results)
Definition: blockfilterindex.cpp:320
CBlockIndex::GetBlockHash
uint256 GetBlockHash() const
Definition: chain.h:246
gArgs
ArgsManager gArgs
Definition: system.cpp:84
CDBIterator::Seek
void Seek(const K &key)
Definition: dbwrapper.h:137
BlockFilter::GetHash
uint256 GetHash() const
Compute the filter hash.
Definition: blockfilter.cpp:289
DB_BLOCK_HEIGHT
constexpr uint8_t DB_BLOCK_HEIGHT
Definition: blockfilterindex.cpp:28
CDBWrapper
Definition: dbwrapper.h:176
system.h
CBlock
Definition: block.h:62
BlockFilterIndex::ReadFilterFromDisk
bool ReadFilterFromDisk(const FlatFilePos &pos, BlockFilter &filter) const
Definition: blockfilterindex.cpp:144
BlockFilterIndex::m_next_filter_pos
FlatFilePos m_next_filter_pos
Definition: blockfilterindex.h:31
BlockFilterIndex::LookupFilterHashRange
bool LookupFilterHashRange(int start_height, const CBlockIndex *stop_index, std::vector< uint256 > &hashes_out) const
Get a range of filter hashes between two heights on a chain.
Definition: blockfilterindex.cpp:435
BaseIndex::CommitInternal
virtual bool CommitInternal(CDBBatch &batch)
Virtual method called internally by Commit that can be overridden to atomically commit more index sta...
Definition: base.cpp:204
GetBlockFilterIndex
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
Definition: blockfilterindex.cpp:452
ForEachBlockFilterIndex
void ForEachBlockFilterIndex(std::function< void(BlockFilterIndex &)> fn)
Iterate over all running block filter indexes, invoking fn on each.
Definition: blockfilterindex.cpp:458
LOCK
#define LOCK(cs)
Definition: sync.h:226
blockstorage.h
ser_writedata32be
void ser_writedata32be(Stream &s, uint32_t obj)
Definition: serialize.h:79
CDBIterator::GetKey
bool GetKey(K &key)
Definition: dbwrapper.h:147
BlockFilterIndex::WriteBlock
bool WriteBlock(const CBlock &block, const CBlockIndex *pindex) override
Write update index entries for a newly connected block.
Definition: blockfilterindex.cpp:210
CF_HEADERS_CACHE_MAX_SZ
constexpr size_t CF_HEADERS_CACHE_MAX_SZ
Maximum size of the cfheaders cache We have a limit to prevent a bug in filling this cache potentiall...
Definition: blockfilterindex.cpp:39
MAX_FLTR_FILE_SIZE
constexpr unsigned int MAX_FLTR_FILE_SIZE
Definition: blockfilterindex.cpp:31
CLIENT_VERSION
static const int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:33
CFCHECKPT_INTERVAL
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
Definition: blockfilterindex.h:15
BlockFilterIndex::LookupFilter
bool LookupFilter(const CBlockIndex *block_index, BlockFilter &filter_out) const
Get a single filter by block.
Definition: blockfilterindex.cpp:375
InitBlockFilterIndex
bool InitBlockFilterIndex(BlockFilterType filter_type, size_t n_cache_size, bool f_memory, bool f_wipe)
Initialize a block filter index for the given type if one does not already exist.
Definition: blockfilterindex.cpp:463
BlockFilterType
BlockFilterType
Definition: blockfilter.h:88
FlatFilePos::nPos
unsigned int nPos
Definition: flatfile.h:17
BlockFilterIndex::GetFilterType
BlockFilterType GetFilterType() const
Definition: blockfilterindex.h:59
BlockFilterIndex::m_cs_headers_cache
Mutex m_cs_headers_cache
Definition: blockfilterindex.h:37
CopyHeightIndexToHashIndex
static bool CopyHeightIndexToHashIndex(CDBIterator &db_it, CDBBatch &batch, const std::string &index_name, int start_height, int stop_height)
Definition: blockfilterindex.cpp:253
error
bool error(const char *fmt, const Args &... args)
Definition: system.h:49
BlockFilterIndex::BlockFilterIndex
BlockFilterIndex(BlockFilterType filter_type, size_t n_cache_size, bool f_memory=false, bool f_wipe=false)
Constructs the index, which becomes available to be queried.
Definition: blockfilterindex.cpp:94
DB_FILTER_POS
constexpr uint8_t DB_FILTER_POS
Definition: blockfilterindex.cpp:29
CBlockIndex
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:137
Serialize
void Serialize(Stream &s, char a)
Definition: serialize.h:199
TruncateFile
bool TruncateFile(FILE *file, unsigned int length)
Definition: system.cpp:1136
BlockFilterIndex::LookupFilterHeader
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out)
Get a single filter header by block.
Definition: blockfilterindex.cpp:385
DestroyAllBlockFilterIndexes
void DestroyAllBlockFilterIndexes()
Destroy all open block filter indexes.
Definition: blockfilterindex.cpp:478
CBlockUndo
Undo information for a CBlock.
Definition: undo.h:63
BlockFilterIndex::m_filter_fileseq
std::unique_ptr< FlatFileSeq > m_filter_fileseq
Definition: blockfilterindex.h:32
CDBIterator
Definition: dbwrapper.h:117
BlockFilterIndex::GetName
const char * GetName() const override
Get the name of the index for display in logs.
Definition: blockfilterindex.h:52
BlockFilter
Complete block filter struct as defined in BIP 157.
Definition: blockfilter.h:110