Skip to content

Commit b0a53d5

Browse files
pstratemkcalvinalvin
authored andcommitted
Make sanity check in GCSFilter constructor optional
BlockFilterIndex will perform the cheaper check of verifying the filter hash when reading the filter from disk.
1 parent 2b5a741 commit b0a53d5

File tree

4 files changed

+18
-11
lines changed

4 files changed

+18
-11
lines changed

src/blockfilter.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ GCSFilter::GCSFilter(const Params& params)
4747
: m_params(params), m_N(0), m_F(0), m_encoded{0}
4848
{}
4949

50-
GCSFilter::GCSFilter(const Params& params, std::vector<unsigned char> encoded_filter)
50+
GCSFilter::GCSFilter(const Params& params, std::vector<unsigned char> encoded_filter, bool skip_decode_check)
5151
: m_params(params), m_encoded(std::move(encoded_filter))
5252
{
5353
SpanReader stream{GCS_SER_TYPE, GCS_SER_VERSION, m_encoded};
@@ -59,6 +59,8 @@ GCSFilter::GCSFilter(const Params& params, std::vector<unsigned char> encoded_fi
5959
}
6060
m_F = static_cast<uint64_t>(m_N) * static_cast<uint64_t>(m_params.m_M);
6161

62+
if (skip_decode_check) return;
63+
6264
// Verify that the encoded filter contains exactly N elements. If it has too much or too little
6365
// data, a std::ios_base::failure exception will be raised.
6466
BitStreamReader<SpanReader> bitreader{stream};
@@ -219,14 +221,14 @@ static GCSFilter::ElementSet BasicFilterElements(const CBlock& block,
219221
}
220222

221223
BlockFilter::BlockFilter(BlockFilterType filter_type, const uint256& block_hash,
222-
std::vector<unsigned char> filter)
224+
std::vector<unsigned char> filter, bool skip_decode_check)
223225
: m_filter_type(filter_type), m_block_hash(block_hash)
224226
{
225227
GCSFilter::Params params;
226228
if (!BuildParams(params)) {
227229
throw std::invalid_argument("unknown filter_type");
228230
}
229-
m_filter = GCSFilter(params, std::move(filter));
231+
m_filter = GCSFilter(params, std::move(filter), skip_decode_check);
230232
}
231233

232234
BlockFilter::BlockFilter(BlockFilterType filter_type, const CBlock& block, const CBlockUndo& block_undo)

src/blockfilter.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class GCSFilter
5959
explicit GCSFilter(const Params& params = Params());
6060

6161
/** Reconstructs an already-created filter from an encoding. */
62-
GCSFilter(const Params& params, std::vector<unsigned char> encoded_filter);
62+
GCSFilter(const Params& params, std::vector<unsigned char> encoded_filter, bool skip_decode_check);
6363

6464
/** Builds a new filter from the params and set of elements. */
6565
GCSFilter(const Params& params, const ElementSet& elements);
@@ -122,7 +122,7 @@ class BlockFilter
122122

123123
//! Reconstruct a BlockFilter from parts.
124124
BlockFilter(BlockFilterType filter_type, const uint256& block_hash,
125-
std::vector<unsigned char> filter);
125+
std::vector<unsigned char> filter, bool skip_decode_check);
126126

127127
//! Construct a new BlockFilter of the specified type from a block.
128128
BlockFilter(BlockFilterType filter_type, const CBlock& block, const CBlockUndo& block_undo);
@@ -164,7 +164,7 @@ class BlockFilter
164164
if (!BuildParams(params)) {
165165
throw std::ios_base::failure("unknown filter_type");
166166
}
167-
m_filter = GCSFilter(params, std::move(encoded_filter));
167+
m_filter = GCSFilter(params, std::move(encoded_filter), /*skip_decode_check=*/false);
168168
}
169169
};
170170

src/index/blockfilterindex.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <map>
66

77
#include <dbwrapper.h>
8+
#include <hash.h>
89
#include <index/blockfilterindex.h>
910
#include <node/blockstorage.h>
1011
#include <util/system.h>
@@ -143,18 +144,22 @@ bool BlockFilterIndex::CommitInternal(CDBBatch& batch)
143144
return BaseIndex::CommitInternal(batch);
144145
}
145146

146-
bool BlockFilterIndex::ReadFilterFromDisk(const FlatFilePos& pos, BlockFilter& filter) const
147+
bool BlockFilterIndex::ReadFilterFromDisk(const FlatFilePos& pos, const uint256& hash, BlockFilter& filter) const
147148
{
148149
CAutoFile filein(m_filter_fileseq->Open(pos, true), SER_DISK, CLIENT_VERSION);
149150
if (filein.IsNull()) {
150151
return false;
151152
}
152153

154+
// Check that the hash of the encoded_filter matches the one stored in the db.
153155
uint256 block_hash;
154156
std::vector<uint8_t> encoded_filter;
155157
try {
156158
filein >> block_hash >> encoded_filter;
157-
filter = BlockFilter(GetFilterType(), block_hash, std::move(encoded_filter));
159+
uint256 result;
160+
CHash256().Write(encoded_filter).Finalize(result);
161+
if (result != hash) return error("Checksum mismatch in filter decode.");
162+
filter = BlockFilter(GetFilterType(), block_hash, std::move(encoded_filter), /*skip_decode_check=*/true);
158163
}
159164
catch (const std::exception& e) {
160165
return error("%s: Failed to deserialize block filter from disk: %s", __func__, e.what());
@@ -381,7 +386,7 @@ bool BlockFilterIndex::LookupFilter(const CBlockIndex* block_index, BlockFilter&
381386
return false;
382387
}
383388

384-
return ReadFilterFromDisk(entry.pos, filter_out);
389+
return ReadFilterFromDisk(entry.pos, entry.hash, filter_out);
385390
}
386391

387392
bool BlockFilterIndex::LookupFilterHeader(const CBlockIndex* block_index, uint256& header_out)
@@ -425,7 +430,7 @@ bool BlockFilterIndex::LookupFilterRange(int start_height, const CBlockIndex* st
425430
filters_out.resize(entries.size());
426431
auto filter_pos_it = filters_out.begin();
427432
for (const auto& entry : entries) {
428-
if (!ReadFilterFromDisk(entry.pos, *filter_pos_it)) {
433+
if (!ReadFilterFromDisk(entry.pos, entry.hash, *filter_pos_it)) {
429434
return false;
430435
}
431436
++filter_pos_it;

src/index/blockfilterindex.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class BlockFilterIndex final : public BaseIndex
3131
FlatFilePos m_next_filter_pos;
3232
std::unique_ptr<FlatFileSeq> m_filter_fileseq;
3333

34-
bool ReadFilterFromDisk(const FlatFilePos& pos, BlockFilter& filter) const;
34+
bool ReadFilterFromDisk(const FlatFilePos& pos, const uint256& hash, BlockFilter& filter) const;
3535
size_t WriteFilterToDisk(FlatFilePos& pos, const BlockFilter& filter);
3636

3737
Mutex m_cs_headers_cache;

0 commit comments

Comments
 (0)