Skip to content

Commit 7a9af53

Browse files
authored
Merge pull request #752 from evoskuil/master
Expand and test inventory/get_data filtering/selection.
2 parents 59baf2f + 23cdb14 commit 7a9af53

File tree

8 files changed

+520
-61
lines changed

8 files changed

+520
-61
lines changed

include/bitcoin/network/messages/peer/detail/get_data.hpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ namespace peer {
3434
struct BCT_API get_data
3535
{
3636
typedef std::shared_ptr<const get_data> cptr;
37+
typedef inventory_item::selector selector;
3738
typedef inventory_item::type_id type_id;
39+
typedef inventory_item item;
3840

3941
static const identifier id;
4042
static const std::string command;
@@ -54,9 +56,11 @@ struct BCT_API get_data
5456
size_t size(uint32_t version) const NOEXCEPT;
5557

5658
// inventory implements the same methods.
57-
auto view(type_id type) const NOEXCEPT;
59+
inline auto view(type_id type) const NOEXCEPT;
60+
inventory_items select(selector types) const NOEXCEPT;
5861
inventory_items filter(type_id type) const NOEXCEPT;
5962
system::hashes to_hashes(type_id type) const NOEXCEPT;
63+
size_t count(selector type) const NOEXCEPT;
6064
size_t count(type_id type) const NOEXCEPT;
6165
bool any(type_id type) const NOEXCEPT;
6266
bool any_transaction() const NOEXCEPT;
@@ -68,9 +72,9 @@ struct BCT_API get_data
6872

6973
inline auto get_data::view(type_id type) const NOEXCEPT
7074
{
71-
const auto is_type = [type](const auto& item) NOEXCEPT
75+
const auto is_type = [type](const inventory_item& item) NOEXCEPT
7276
{
73-
return item.type == type;
77+
return item.is_type(type);
7478
};
7579

7680
return std::ranges::filter_view(items, is_type);

include/bitcoin/network/messages/peer/detail/inventory.hpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ namespace peer {
3434
struct BCT_API inventory
3535
{
3636
typedef std::shared_ptr<const inventory> cptr;
37+
typedef inventory_item::selector selector;
3738
typedef inventory_item::type_id type_id;
39+
typedef inventory_item item;
3840

3941
static const identifier id;
4042
static const std::string command;
@@ -60,9 +62,11 @@ struct BCT_API inventory
6062
size_t size(uint32_t version) const NOEXCEPT;
6163

6264
// get_data implements the same methods.
63-
auto view(type_id type) const NOEXCEPT;
65+
inline auto view(type_id type) const NOEXCEPT;
66+
inventory_items select(selector types) const NOEXCEPT;
6467
inventory_items filter(type_id type) const NOEXCEPT;
6568
system::hashes to_hashes(type_id type) const NOEXCEPT;
69+
size_t count(selector type) const NOEXCEPT;
6670
size_t count(type_id type) const NOEXCEPT;
6771
bool any(type_id type) const NOEXCEPT;
6872
bool any_transaction() const NOEXCEPT;
@@ -74,9 +78,9 @@ struct BCT_API inventory
7478

7579
inline auto inventory::view(type_id type) const NOEXCEPT
7680
{
77-
const auto is_type = [type](const auto& item) NOEXCEPT
81+
const auto is_type = [type](const inventory_item& item) NOEXCEPT
7882
{
79-
return item.type == type;
83+
return item.is_type(type);
8084
};
8185

8286
return std::ranges::filter_view(items, is_type);

include/bitcoin/network/messages/peer/detail/inventory_item.hpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,27 @@ struct BCT_API inventory_item
3232
{
3333
typedef std::shared_ptr<const inventory_item> cptr;
3434

35+
/// Logical type selection.
36+
enum class selector
37+
{
38+
txids,
39+
wtxids,
40+
blocks,
41+
filters
42+
};
43+
44+
/// Serializeable type id.
3545
enum class type_id : uint32_t
3646
{
37-
// It's so dumb that these are not flags (so use class enum).
38-
error = 0,
39-
transaction = 1,
40-
block = 2,
41-
filtered = 3,
42-
compact = 4,
43-
wtxid = 5,
47+
// It's so dumb that these are not flags.
48+
error = 0,
49+
transaction = 1,
50+
block = 2,
51+
filtered = 3,
52+
compact = 4,
53+
wtxid = 5,
4454

45-
// And yet this is a flag, but excludes wtxid.
55+
// But witness is a flag.
4656
witness = system::bit_right<uint32_t>(30),
4757
witness_tx = witness | transaction,
4858
witness_block = witness | block,
@@ -59,9 +69,18 @@ struct BCT_API inventory_item
5969
system::reader& source) NOEXCEPT;
6070
void serialize(uint32_t version, system::writer& sink) const NOEXCEPT;
6171

72+
/// These indicate relevance to a specific object identifier.
73+
bool is_txid() const NOEXCEPT;
74+
bool is_wtxid() const NOEXCEPT;
75+
bool is_block() const NOEXCEPT;
76+
bool is_filter() const NOEXCEPT;
77+
bool is_selected(selector types) const NOEXCEPT;
78+
79+
/// These indicate context, not object identifier.
6280
bool is_block_type() const NOEXCEPT;
6381
bool is_transaction_type() const NOEXCEPT;
6482
bool is_witness_type() const NOEXCEPT;
83+
bool is_type(type_id id) const NOEXCEPT;
6584

6685
type_id type;
6786
system::hash_digest hash;

src/messages/peer/detail/get_data.cpp

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <bitcoin/network/messages/peer/detail/get_data.hpp>
2020

2121
#include <algorithm>
22+
#include <ranges>
2223
#include <bitcoin/network/messages/peer/enums/identifier.hpp>
2324
#include <bitcoin/network/messages/peer/enums/level.hpp>
2425
#include <bitcoin/network/messages/peer/enums/magic_numbers.hpp>
@@ -55,11 +56,11 @@ get_data get_data::deserialize(uint32_t version, reader& source) NOEXCEPT
5556
source.invalidate();
5657

5758
const auto size = source.read_size(max_inventory);
58-
get_data get;
59+
get_data get{};
5960
get.items.reserve(size);
6061

61-
for (size_t item = 0; item < size; ++item)
62-
get.items.push_back(inventory_item::deserialize(version, source));
62+
for (size_t item{}; item < size; ++item)
63+
get.items.push_back(item::deserialize(version, source));
6364

6465
return get;
6566
}
@@ -76,9 +77,9 @@ bool get_data::serialize(uint32_t version,
7677
void get_data::serialize(uint32_t version, writer& sink) const NOEXCEPT
7778
{
7879
BC_DEBUG_ONLY(const auto bytes = size(version);)
79-
BC_DEBUG_ONLY(const auto start = sink.get_write_position();)
80+
BC_DEBUG_ONLY(const auto start = sink.get_write_position();)
8081

81-
sink.write_variable(items.size());
82+
sink.write_variable(items.size());
8283

8384
for (const auto& item: items)
8485
item.serialize(version, sink);
@@ -89,12 +90,25 @@ void get_data::serialize(uint32_t version, writer& sink) const NOEXCEPT
8990
size_t get_data::size(uint32_t version) const NOEXCEPT
9091
{
9192
return variable_size(items.size()) +
92-
(items.size() * inventory_item::size(version));
93+
(items.size() * item::size(version));
94+
}
95+
96+
// Populated in reverse order for efficient removals.
97+
inventory_items get_data::select(selector types) const NOEXCEPT
98+
{
99+
inventory_items out{};
100+
out.reserve(count(types));
101+
102+
for (const auto& item: std::views::reverse(items))
103+
if (item.is_selected(types))
104+
out.push_back(item);
105+
106+
return out;
93107
}
94108

95109
inventory_items get_data::filter(type_id type) const NOEXCEPT
96110
{
97-
inventory_items out;
111+
inventory_items out{};
98112
out.reserve(count(type));
99113

100114
for (const auto& item: items)
@@ -106,7 +120,7 @@ inventory_items get_data::filter(type_id type) const NOEXCEPT
106120

107121
hashes get_data::to_hashes(type_id type) const NOEXCEPT
108122
{
109-
hashes out;
123+
hashes out{};
110124
out.reserve(count(type));
111125

112126
for (const auto& item: items)
@@ -116,29 +130,39 @@ hashes get_data::to_hashes(type_id type) const NOEXCEPT
116130
return out;
117131
}
118132

133+
size_t get_data::count(selector type) const NOEXCEPT
134+
{
135+
const auto is_selected = [type](const item& item)
136+
{
137+
return item.is_selected(type);
138+
};
139+
140+
return std::count_if(items.begin(), items.end(), is_selected);
141+
}
142+
119143
size_t get_data::count(type_id type) const NOEXCEPT
120144
{
121-
const auto is_type = [type](const inventory_item& item)
145+
const auto is_type = [type](const item& item)
122146
{
123-
return item.type == type;
147+
return item.is_type(type);
124148
};
125149

126150
return std::count_if(items.begin(), items.end(), is_type);
127151
}
128152

129153
bool get_data::any(type_id type) const NOEXCEPT
130154
{
131-
const auto is_type = [type](const inventory_item& item)
155+
const auto is_type = [type](const item& item)
132156
{
133-
return item.type == type;
157+
return item.is_type(type);
134158
};
135159

136160
return std::any_of(items.begin(), items.end(), is_type);
137161
}
138162

139163
bool get_data::any_transaction() const NOEXCEPT
140164
{
141-
const auto is_transaction = [](const inventory_item& item)
165+
const auto is_transaction = [](const item& item)
142166
{
143167
return item.is_transaction_type();
144168
};
@@ -148,7 +172,7 @@ bool get_data::any_transaction() const NOEXCEPT
148172

149173
bool get_data::any_block() const NOEXCEPT
150174
{
151-
const auto is_block = [](const inventory_item& item)
175+
const auto is_block = [](const item& item)
152176
{
153177
return item.is_block_type();
154178
};
@@ -158,7 +182,7 @@ bool get_data::any_block() const NOEXCEPT
158182

159183
bool get_data::any_witness() const NOEXCEPT
160184
{
161-
const auto is_witness = [](const inventory_item& item)
185+
const auto is_witness = [](const item& item)
162186
{
163187
return item.is_witness_type();
164188
};

src/messages/peer/detail/inventory.cpp

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <bitcoin/network/messages/peer/detail/inventory.hpp>
2020

2121
#include <algorithm>
22+
#include <ranges>
2223
#include <utility>
2324
#include <bitcoin/network/messages/peer/enums/identifier.hpp>
2425
#include <bitcoin/network/messages/peer/enums/level.hpp>
@@ -48,7 +49,7 @@ inventory inventory::factory(hashes&& hashes, type_id type) NOEXCEPT
4849
std::transform(hashes.begin(), hashes.end(), items.begin(),
4950
[=](hash_digest& hash) NOEXCEPT
5051
{
51-
return inventory_item{ type, std::move(hash) };
52+
return item{ type, std::move(hash) };
5253
});
5354

5455
return { items };
@@ -62,7 +63,7 @@ inventory inventory::factory(const hashes& hashes, type_id type) NOEXCEPT
6263
std::transform(hashes.begin(), hashes.end(), items.begin(),
6364
[=](const hash_digest& hash) NOEXCEPT
6465
{
65-
return inventory_item{ type, hash };
66+
return item{ type, hash };
6667
});
6768

6869
return { items };
@@ -88,8 +89,8 @@ inventory inventory::deserialize(uint32_t version, reader& source) NOEXCEPT
8889
inventory_items items;
8990
items.reserve(size);
9091

91-
for (size_t item = 0; item < size; ++item)
92-
items.push_back(inventory_item::deserialize(version, source));
92+
for (size_t item{}; item < size; ++item)
93+
items.push_back(item::deserialize(version, source));
9394

9495
return { items };
9596
}
@@ -119,12 +120,25 @@ void inventory::serialize(uint32_t version, writer& sink) const NOEXCEPT
119120
size_t inventory::size(uint32_t version) const NOEXCEPT
120121
{
121122
return variable_size(items.size()) +
122-
(items.size() * inventory_item::size(version));
123+
(items.size() * item::size(version));
124+
}
125+
126+
// Populated in reverse order for efficient removals.
127+
inventory_items inventory::select(selector types) const NOEXCEPT
128+
{
129+
inventory_items out{};
130+
out.reserve(count(types));
131+
132+
for (const auto& item: std::views::reverse(items))
133+
if (item.is_selected(types))
134+
out.push_back(item);
135+
136+
return out;
123137
}
124138

125139
inventory_items inventory::filter(type_id type) const NOEXCEPT
126140
{
127-
inventory_items out;
141+
inventory_items out{};
128142
out.reserve(count(type));
129143

130144
for (const auto& item: items)
@@ -136,7 +150,7 @@ inventory_items inventory::filter(type_id type) const NOEXCEPT
136150

137151
hashes inventory::to_hashes(type_id type) const NOEXCEPT
138152
{
139-
hashes out;
153+
hashes out{};
140154
out.reserve(count(type));
141155

142156
for (const auto& item: items)
@@ -146,29 +160,39 @@ hashes inventory::to_hashes(type_id type) const NOEXCEPT
146160
return out;
147161
}
148162

163+
size_t inventory::count(selector type) const NOEXCEPT
164+
{
165+
const auto is_selected = [type](const inventory_item& item)
166+
{
167+
return item.is_selected(type);
168+
};
169+
170+
return std::count_if(items.begin(), items.end(), is_selected);
171+
}
172+
149173
size_t inventory::count(type_id type) const NOEXCEPT
150174
{
151-
const auto is_type = [type](const inventory_item& item)
175+
const auto is_type = [type](const item& item)
152176
{
153-
return item.type == type;
177+
return item.is_type(type);
154178
};
155179

156180
return std::count_if(items.begin(), items.end(), is_type);
157181
}
158182

159183
bool inventory::any(type_id type) const NOEXCEPT
160184
{
161-
const auto is_type = [type](const inventory_item& item)
185+
const auto is_type = [type](const item& item)
162186
{
163-
return item.type == type;
187+
return item.is_type(type);
164188
};
165189

166190
return std::any_of(items.begin(), items.end(), is_type);
167191
}
168192

169193
bool inventory::any_transaction() const NOEXCEPT
170194
{
171-
const auto is_transaction = [](const inventory_item& item)
195+
const auto is_transaction = [](const item& item)
172196
{
173197
return item.is_transaction_type();
174198
};
@@ -178,7 +202,7 @@ bool inventory::any_transaction() const NOEXCEPT
178202

179203
bool inventory::any_block() const NOEXCEPT
180204
{
181-
const auto is_block = [](const inventory_item& item)
205+
const auto is_block = [](const item& item)
182206
{
183207
return item.is_block_type();
184208
};
@@ -188,7 +212,7 @@ bool inventory::any_block() const NOEXCEPT
188212

189213
bool inventory::any_witness() const NOEXCEPT
190214
{
191-
const auto is_witness = [](const inventory_item& item)
215+
const auto is_witness = [](const item& item)
192216
{
193217
return item.is_witness_type();
194218
};

0 commit comments

Comments
 (0)