Changeset View
Changeset View
Standalone View
Standalone View
src/blockfilter.cpp
// Copyright (c) 2018 The Bitcoin Core developers | // Copyright (c) 2018 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <blockfilter.h> | #include <blockfilter.h> | ||||
#include <crypto/siphash.h> | #include <crypto/siphash.h> | ||||
#include <hash.h> | |||||
#include <primitives/transaction.h> | |||||
#include <script/script.h> | |||||
#include <streams.h> | #include <streams.h> | ||||
/// SerType used to serialize parameters in GCS filter encoding. | /// SerType used to serialize parameters in GCS filter encoding. | ||||
static constexpr int GCS_SER_TYPE = SER_NETWORK; | static constexpr int GCS_SER_TYPE = SER_NETWORK; | ||||
/// Protocol version used to serialize parameters in GCS filter encoding. | /// Protocol version used to serialize parameters in GCS filter encoding. | ||||
static constexpr int GCS_SER_VERSION = 0; | static constexpr int GCS_SER_VERSION = 0; | ||||
▲ Show 20 Lines • Show All 176 Lines • ▼ Show 20 Lines | bool GCSFilter::Match(const Element &element) const { | ||||
uint64_t query = HashToRange(element); | uint64_t query = HashToRange(element); | ||||
return MatchInternal(&query, 1); | return MatchInternal(&query, 1); | ||||
} | } | ||||
bool GCSFilter::MatchAny(const ElementSet &elements) const { | bool GCSFilter::MatchAny(const ElementSet &elements) const { | ||||
const std::vector<uint64_t> queries = BuildHashedSet(elements); | const std::vector<uint64_t> queries = BuildHashedSet(elements); | ||||
return MatchInternal(queries.data(), queries.size()); | return MatchInternal(queries.data(), queries.size()); | ||||
} | } | ||||
static GCSFilter::ElementSet BasicFilterElements(const CBlock &block, | |||||
const CBlockUndo &block_undo) { | |||||
GCSFilter::ElementSet elements; | |||||
for (const CTransactionRef &tx : block.vtx) { | |||||
for (const CTxOut &txout : tx->vout) { | |||||
const CScript &script = txout.scriptPubKey; | |||||
if (script.empty() || script[0] == OP_RETURN) { | |||||
continue; | |||||
} | |||||
elements.emplace(script.begin(), script.end()); | |||||
} | |||||
} | |||||
for (const CTxUndo &tx_undo : block_undo.vtxundo) { | |||||
for (const Coin &prevout : tx_undo.vprevout) { | |||||
const CScript &script = prevout.GetTxOut().scriptPubKey; | |||||
if (script.empty()) { | |||||
continue; | |||||
} | |||||
elements.emplace(script.begin(), script.end()); | |||||
} | |||||
} | |||||
return elements; | |||||
} | |||||
BlockFilter::BlockFilter(BlockFilterType filter_type, const CBlock &block, | |||||
const CBlockUndo &block_undo) | |||||
: m_filter_type(filter_type), m_block_hash(block.GetHash()) { | |||||
switch (m_filter_type) { | |||||
case BlockFilterType::BASIC: | |||||
m_filter = | |||||
GCSFilter(m_block_hash.GetUint64(0), m_block_hash.GetUint64(1), | |||||
BASIC_FILTER_P, BASIC_FILTER_M, | |||||
BasicFilterElements(block, block_undo)); | |||||
break; | |||||
default: | |||||
throw std::invalid_argument("unknown filter_type"); | |||||
} | |||||
} | |||||
uint256 BlockFilter::GetHash() const { | |||||
const std::vector<uint8_t> &data = GetEncodedFilter(); | |||||
uint256 result; | |||||
CHash256().Write(data.data(), data.size()).Finalize(result.begin()); | |||||
return result; | |||||
} | |||||
uint256 BlockFilter::ComputeHeader(const uint256 &prev_header) const { | |||||
const uint256 &filter_hash = GetHash(); | |||||
uint256 result; | |||||
CHash256() | |||||
.Write(filter_hash.begin(), filter_hash.size()) | |||||
.Write(prev_header.begin(), prev_header.size()) | |||||
.Finalize(result.begin()); | |||||
return result; | |||||
} |