Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions include/bitcoin/network/messages/peer/detail/get_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ namespace peer {
struct BCT_API get_data
{
typedef std::shared_ptr<const get_data> cptr;
typedef inventory_item::selector selector;
typedef inventory_item::type_id type_id;
typedef inventory_item item;

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

// inventory implements the same methods.
auto view(type_id type) const NOEXCEPT;
inline auto view(type_id type) const NOEXCEPT;
inventory_items select(selector types) const NOEXCEPT;
inventory_items filter(type_id type) const NOEXCEPT;
system::hashes to_hashes(type_id type) const NOEXCEPT;
size_t count(selector type) const NOEXCEPT;
size_t count(type_id type) const NOEXCEPT;
bool any(type_id type) const NOEXCEPT;
bool any_transaction() const NOEXCEPT;
Expand All @@ -68,9 +72,9 @@ struct BCT_API get_data

inline auto get_data::view(type_id type) const NOEXCEPT
{
const auto is_type = [type](const auto& item) NOEXCEPT
const auto is_type = [type](const inventory_item& item) NOEXCEPT
{
return item.type == type;
return item.is_type(type);
};

return std::ranges::filter_view(items, is_type);
Expand Down
10 changes: 7 additions & 3 deletions include/bitcoin/network/messages/peer/detail/inventory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ namespace peer {
struct BCT_API inventory
{
typedef std::shared_ptr<const inventory> cptr;
typedef inventory_item::selector selector;
typedef inventory_item::type_id type_id;
typedef inventory_item item;

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

// get_data implements the same methods.
auto view(type_id type) const NOEXCEPT;
inline auto view(type_id type) const NOEXCEPT;
inventory_items select(selector types) const NOEXCEPT;
inventory_items filter(type_id type) const NOEXCEPT;
system::hashes to_hashes(type_id type) const NOEXCEPT;
size_t count(selector type) const NOEXCEPT;
size_t count(type_id type) const NOEXCEPT;
bool any(type_id type) const NOEXCEPT;
bool any_transaction() const NOEXCEPT;
Expand All @@ -74,9 +78,9 @@ struct BCT_API inventory

inline auto inventory::view(type_id type) const NOEXCEPT
{
const auto is_type = [type](const auto& item) NOEXCEPT
const auto is_type = [type](const inventory_item& item) NOEXCEPT
{
return item.type == type;
return item.is_type(type);
};

return std::ranges::filter_view(items, is_type);
Expand Down
35 changes: 27 additions & 8 deletions include/bitcoin/network/messages/peer/detail/inventory_item.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,27 @@ struct BCT_API inventory_item
{
typedef std::shared_ptr<const inventory_item> cptr;

/// Logical type selection.
enum class selector
{
txids,
wtxids,
blocks,
filters
};

/// Serializeable type id.
enum class type_id : uint32_t
{
// It's so dumb that these are not flags (so use class enum).
error = 0,
transaction = 1,
block = 2,
filtered = 3,
compact = 4,
wtxid = 5,
// It's so dumb that these are not flags.
error = 0,
transaction = 1,
block = 2,
filtered = 3,
compact = 4,
wtxid = 5,

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

/// These indicate relevance to a specific object identifier.
bool is_txid() const NOEXCEPT;
bool is_wtxid() const NOEXCEPT;
bool is_block() const NOEXCEPT;
bool is_filter() const NOEXCEPT;
bool is_selected(selector types) const NOEXCEPT;

/// These indicate context, not object identifier.
bool is_block_type() const NOEXCEPT;
bool is_transaction_type() const NOEXCEPT;
bool is_witness_type() const NOEXCEPT;
bool is_type(type_id id) const NOEXCEPT;

type_id type;
system::hash_digest hash;
Expand Down
54 changes: 39 additions & 15 deletions src/messages/peer/detail/get_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <bitcoin/network/messages/peer/detail/get_data.hpp>

#include <algorithm>
#include <ranges>
#include <bitcoin/network/messages/peer/enums/identifier.hpp>
#include <bitcoin/network/messages/peer/enums/level.hpp>
#include <bitcoin/network/messages/peer/enums/magic_numbers.hpp>
Expand Down Expand Up @@ -55,11 +56,11 @@ get_data get_data::deserialize(uint32_t version, reader& source) NOEXCEPT
source.invalidate();

const auto size = source.read_size(max_inventory);
get_data get;
get_data get{};
get.items.reserve(size);

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

return get;
}
Expand All @@ -76,9 +77,9 @@ bool get_data::serialize(uint32_t version,
void get_data::serialize(uint32_t version, writer& sink) const NOEXCEPT
{
BC_DEBUG_ONLY(const auto bytes = size(version);)
BC_DEBUG_ONLY(const auto start = sink.get_write_position();)
BC_DEBUG_ONLY(const auto start = sink.get_write_position();)

sink.write_variable(items.size());
sink.write_variable(items.size());

for (const auto& item: items)
item.serialize(version, sink);
Expand All @@ -89,12 +90,25 @@ void get_data::serialize(uint32_t version, writer& sink) const NOEXCEPT
size_t get_data::size(uint32_t version) const NOEXCEPT
{
return variable_size(items.size()) +
(items.size() * inventory_item::size(version));
(items.size() * item::size(version));
}

// Populated in reverse order for efficient removals.
inventory_items get_data::select(selector types) const NOEXCEPT
{
inventory_items out{};
out.reserve(count(types));

for (const auto& item: std::views::reverse(items))
if (item.is_selected(types))
out.push_back(item);

return out;
}

inventory_items get_data::filter(type_id type) const NOEXCEPT
{
inventory_items out;
inventory_items out{};
out.reserve(count(type));

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

hashes get_data::to_hashes(type_id type) const NOEXCEPT
{
hashes out;
hashes out{};
out.reserve(count(type));

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

size_t get_data::count(selector type) const NOEXCEPT
{
const auto is_selected = [type](const item& item)
{
return item.is_selected(type);
};

return std::count_if(items.begin(), items.end(), is_selected);
}

size_t get_data::count(type_id type) const NOEXCEPT
{
const auto is_type = [type](const inventory_item& item)
const auto is_type = [type](const item& item)
{
return item.type == type;
return item.is_type(type);
};

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

bool get_data::any(type_id type) const NOEXCEPT
{
const auto is_type = [type](const inventory_item& item)
const auto is_type = [type](const item& item)
{
return item.type == type;
return item.is_type(type);
};

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

bool get_data::any_transaction() const NOEXCEPT
{
const auto is_transaction = [](const inventory_item& item)
const auto is_transaction = [](const item& item)
{
return item.is_transaction_type();
};
Expand All @@ -148,7 +172,7 @@ bool get_data::any_transaction() const NOEXCEPT

bool get_data::any_block() const NOEXCEPT
{
const auto is_block = [](const inventory_item& item)
const auto is_block = [](const item& item)
{
return item.is_block_type();
};
Expand All @@ -158,7 +182,7 @@ bool get_data::any_block() const NOEXCEPT

bool get_data::any_witness() const NOEXCEPT
{
const auto is_witness = [](const inventory_item& item)
const auto is_witness = [](const item& item)
{
return item.is_witness_type();
};
Expand Down
52 changes: 38 additions & 14 deletions src/messages/peer/detail/inventory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <bitcoin/network/messages/peer/detail/inventory.hpp>

#include <algorithm>
#include <ranges>
#include <utility>
#include <bitcoin/network/messages/peer/enums/identifier.hpp>
#include <bitcoin/network/messages/peer/enums/level.hpp>
Expand Down Expand Up @@ -48,7 +49,7 @@ inventory inventory::factory(hashes&& hashes, type_id type) NOEXCEPT
std::transform(hashes.begin(), hashes.end(), items.begin(),
[=](hash_digest& hash) NOEXCEPT
{
return inventory_item{ type, std::move(hash) };
return item{ type, std::move(hash) };
});

return { items };
Expand All @@ -62,7 +63,7 @@ inventory inventory::factory(const hashes& hashes, type_id type) NOEXCEPT
std::transform(hashes.begin(), hashes.end(), items.begin(),
[=](const hash_digest& hash) NOEXCEPT
{
return inventory_item{ type, hash };
return item{ type, hash };
});

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

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

return { items };
}
Expand Down Expand Up @@ -119,12 +120,25 @@ void inventory::serialize(uint32_t version, writer& sink) const NOEXCEPT
size_t inventory::size(uint32_t version) const NOEXCEPT
{
return variable_size(items.size()) +
(items.size() * inventory_item::size(version));
(items.size() * item::size(version));
}

// Populated in reverse order for efficient removals.
inventory_items inventory::select(selector types) const NOEXCEPT
{
inventory_items out{};
out.reserve(count(types));

for (const auto& item: std::views::reverse(items))
if (item.is_selected(types))
out.push_back(item);

return out;
}

inventory_items inventory::filter(type_id type) const NOEXCEPT
{
inventory_items out;
inventory_items out{};
out.reserve(count(type));

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

hashes inventory::to_hashes(type_id type) const NOEXCEPT
{
hashes out;
hashes out{};
out.reserve(count(type));

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

size_t inventory::count(selector type) const NOEXCEPT
{
const auto is_selected = [type](const inventory_item& item)
{
return item.is_selected(type);
};

return std::count_if(items.begin(), items.end(), is_selected);
}

size_t inventory::count(type_id type) const NOEXCEPT
{
const auto is_type = [type](const inventory_item& item)
const auto is_type = [type](const item& item)
{
return item.type == type;
return item.is_type(type);
};

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

bool inventory::any(type_id type) const NOEXCEPT
{
const auto is_type = [type](const inventory_item& item)
const auto is_type = [type](const item& item)
{
return item.type == type;
return item.is_type(type);
};

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

bool inventory::any_transaction() const NOEXCEPT
{
const auto is_transaction = [](const inventory_item& item)
const auto is_transaction = [](const item& item)
{
return item.is_transaction_type();
};
Expand All @@ -178,7 +202,7 @@ bool inventory::any_transaction() const NOEXCEPT

bool inventory::any_block() const NOEXCEPT
{
const auto is_block = [](const inventory_item& item)
const auto is_block = [](const item& item)
{
return item.is_block_type();
};
Expand All @@ -188,7 +212,7 @@ bool inventory::any_block() const NOEXCEPT

bool inventory::any_witness() const NOEXCEPT
{
const auto is_witness = [](const inventory_item& item)
const auto is_witness = [](const item& item)
{
return item.is_witness_type();
};
Expand Down
Loading