Line data Source code
1 : // Copyright (c) 2018-2019 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 : #ifndef BITCOIN_BLOCKFILTER_H 6 : #define BITCOIN_BLOCKFILTER_H 7 : 8 : #include <stdint.h> 9 : #include <string> 10 : #include <set> 11 : #include <unordered_set> 12 : #include <vector> 13 : 14 : #include <attributes.h> 15 : #include <primitives/block.h> 16 : #include <serialize.h> 17 : #include <uint256.h> 18 : #include <undo.h> 19 : #include <util/bytevectorhash.h> 20 : 21 : /** 22 : * This implements a Golomb-coded set as defined in BIP 158. It is a 23 : * compact, probabilistic data structure for testing set membership. 24 : */ 25 : class GCSFilter 26 : { 27 : public: 28 : typedef std::vector<unsigned char> Element; 29 : typedef std::unordered_set<Element, ByteVectorHash> ElementSet; 30 : 31 : struct Params 32 : { 33 : uint64_t m_siphash_k0; 34 : uint64_t m_siphash_k1; 35 : uint8_t m_P; //!< Golomb-Rice coding parameter 36 : uint32_t m_M; //!< Inverse false positive rate 37 : 38 594160 : Params(uint64_t siphash_k0 = 0, uint64_t siphash_k1 = 0, uint8_t P = 0, uint32_t M = 1) 39 297080 : : m_siphash_k0(siphash_k0), m_siphash_k1(siphash_k1), m_P(P), m_M(M) 40 594160 : {} 41 : }; 42 : 43 : private: 44 : Params m_params; 45 : uint32_t m_N; //!< Number of elements in the filter 46 : uint64_t m_F; //!< Range of element hashes, F = N * M 47 : std::vector<unsigned char> m_encoded; 48 : 49 : /** Hash a data element to an integer in the range [0, N * M). */ 50 : uint64_t HashToRange(const Element& element) const; 51 : 52 : std::vector<uint64_t> BuildHashedSet(const ElementSet& elements) const; 53 : 54 : /** Helper method used to implement Match and MatchAny */ 55 : bool MatchInternal(const uint64_t* sorted_element_hashes, size_t size) const; 56 : 57 : public: 58 : 59 : /** Constructs an empty filter. */ 60 : explicit GCSFilter(const Params& params = Params()); 61 : 62 : /** Reconstructs an already-created filter from an encoding. */ 63 : GCSFilter(const Params& params, std::vector<unsigned char> encoded_filter, bool skip_decode_check); 64 : 65 : /** Builds a new filter from the params and set of elements. */ 66 : GCSFilter(const Params& params, const ElementSet& elements); 67 : 68 1 : uint32_t GetN() const { return m_N; } 69 1 : const Params& GetParams() const LIFETIMEBOUND { return m_params; } 70 586880 : const std::vector<unsigned char>& GetEncoded() const LIFETIMEBOUND { return m_encoded; } 71 : 72 : /** 73 : * Checks if the element may be in the set. False positives are possible 74 : * with probability 1/M. 75 : */ 76 : bool Match(const Element& element) const; 77 : 78 : /** 79 : * Checks if any of the given elements may be in the set. False positives 80 : * are possible with probability 1/M per element checked. This is more 81 : * efficient that checking Match on multiple elements separately. 82 : */ 83 : bool MatchAny(const ElementSet& elements) const; 84 : }; 85 : 86 : constexpr uint8_t BASIC_FILTER_P = 19; 87 : constexpr uint32_t BASIC_FILTER_M = 784931; 88 : 89 : enum class BlockFilterType : uint8_t 90 : { 91 : BASIC_FILTER = 0, 92 : INVALID = 255, 93 : }; 94 : 95 : /** Get the human-readable name for a filter type. Returns empty string for unknown types. */ 96 : const std::string& BlockFilterTypeName(BlockFilterType filter_type); 97 : 98 : /** Find a filter type by its human-readable name. */ 99 : bool BlockFilterTypeByName(const std::string& name, BlockFilterType& filter_type); 100 : 101 : /** Get a list of known filter types. */ 102 : const std::set<BlockFilterType>& AllBlockFilterTypes(); 103 : 104 : /** Get a comma-separated list of known filter type names. */ 105 : const std::string& ListBlockFilterTypes(); 106 : 107 : /** 108 : * Complete block filter struct as defined in BIP 157. Serialization matches 109 : * payload of "cfilter" messages. 110 : */ 111 : class BlockFilter 112 : { 113 : private: 114 1335 : BlockFilterType m_filter_type = BlockFilterType::INVALID; 115 : uint256 m_block_hash; 116 : GCSFilter m_filter; 117 : 118 : bool BuildParams(GCSFilter::Params& params) const; 119 : 120 : public: 121 : 122 4005 : BlockFilter() = default; 123 : 124 : //! Reconstruct a BlockFilter from parts. 125 : BlockFilter(BlockFilterType filter_type, const uint256& block_hash, 126 : std::vector<unsigned char> filter, bool skip_decode_check); 127 : 128 : //! Construct a new BlockFilter of the specified type from a block. 129 : BlockFilter(BlockFilterType filter_type, const CBlock& block, const CBlockUndo& block_undo); 130 : 131 146534 : BlockFilterType GetFilterType() const { return m_filter_type; } 132 293064 : const uint256& GetBlockHash() const LIFETIMEBOUND { return m_block_hash; } 133 838 : const GCSFilter& GetFilter() const LIFETIMEBOUND { return m_filter; } 134 : 135 586849 : const std::vector<unsigned char>& GetEncodedFilter() const LIFETIMEBOUND 136 : { 137 586849 : return m_filter.GetEncoded(); 138 : } 139 : 140 : //! Compute the filter hash. 141 : uint256 GetHash() const; 142 : 143 : //! Compute the filter header given the previous one. 144 : uint256 ComputeHeader(const uint256& prev_header) const; 145 : 146 : template <typename Stream> 147 23 : void Serialize(Stream& s) const { 148 23 : s << static_cast<uint8_t>(m_filter_type) 149 23 : << m_block_hash 150 23 : << m_filter.GetEncoded(); 151 23 : } 152 : 153 : template <typename Stream> 154 1 : void Unserialize(Stream& s) { 155 1 : std::vector<unsigned char> encoded_filter; 156 : uint8_t filter_type; 157 : 158 1 : s >> filter_type 159 1 : >> m_block_hash 160 1 : >> encoded_filter; 161 : 162 1 : m_filter_type = static_cast<BlockFilterType>(filter_type); 163 : 164 1 : GCSFilter::Params params; 165 1 : if (!BuildParams(params)) { 166 0 : throw std::ios_base::failure("unknown filter_type"); 167 : } 168 1 : m_filter = GCSFilter(params, std::move(encoded_filter), /*skip_decode_check=*/false); 169 1 : } 170 : }; 171 : 172 : #endif // BITCOIN_BLOCKFILTER_H