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
40 changes: 21 additions & 19 deletions include/bitcoin/database/impl/query/consensus/consensus_compact.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,21 @@ namespace database {

TEMPLATE
code CLASS::get_compact_links(tx_links& out,
const std::vector<uint64_t>& short_ids,
const std::vector<short_id>& short_ids,
const system::siphash_key& key) const NOEXCEPT
{
using namespace system;
constexpr auto mask = unmask_right<uint64_t>(48);
out.assign(short_ids.size(), tx_link::terminal);
if (short_ids.empty() || !store_.pool.enabled())
return error::success;

// A short id duplicated within the block is ambiguous.
std::vector<bool> ambiguous(short_ids.size());
std::unordered_map<uint64_t, size_t> positions{};
std::unordered_map<short_id, size_t> positions{};
positions.reserve(short_ids.size());
for (size_t index{}; index < short_ids.size(); ++index)
{
const auto id = bit_and(short_ids.at(index), mask);
const auto id = bit_and(short_ids.at(index), chain::short_id::mask);
if (const auto [it, added] = positions.emplace(id, index); !added)
ambiguous.at(index) = ambiguous.at(it->second) = true;
}
Expand Down Expand Up @@ -78,12 +77,15 @@ code CLASS::get_compact_links(tx_links& out,
// The columns are little-endian words, hashed in place across vector lanes.
TEMPLATE
bool CLASS::get_compact_matches(compact_matches& out,
const std::unordered_map<uint64_t, size_t>& positions,
const std::unordered_map<short_id, size_t>& positions,
const system::siphash_key& key) const NOEXCEPT
{
using namespace system;
constexpr auto mask = unmask_right<uint64_t>(48);
constexpr size_t chunk_rows = 16384;
using lane_t = schema::pool::witness_lane;
using link_t = table::pool::link::integer;
static_assert(is_same_type<siphash_columns::value_type,
std::span<const lane_t>>);
constexpr auto chunk_rows = short_id_chunk_rows;
const auto ptr0 = store_.pool.id0.get_memory();
const auto ptr1 = store_.pool.id1.get_memory();
const auto ptr2 = store_.pool.id2.get_memory();
Expand All @@ -94,7 +96,7 @@ bool CLASS::get_compact_matches(compact_matches& out,
const auto rows = possible_narrow_cast<size_t>(store_.pool.count().value);
if constexpr (is_little_endian)
{
const auto bytes = rows * sizeof(uint64_t);
const auto bytes = rows * sizeof(lane_t);
if (is_lesser(ptr0.size(), bytes) || is_lesser(ptr1.size(), bytes) ||
is_lesser(ptr2.size(), bytes) || is_lesser(ptr3.size(), bytes))
return false;
Expand All @@ -110,16 +112,16 @@ bool CLASS::get_compact_matches(compact_matches& out,
[&](size_t chunk) NOEXCEPT
{
const auto first = chunk * chunk_rows;
std::vector<uint64_t> ids(std::min(chunk_rows, rows - first));
std::vector<short_id> ids(std::min(chunk_rows, rows - first));

if constexpr (is_little_endian)
{
const auto column = [&](const memory& ptr) NOEXCEPT
{
return std::span<const uint64_t>
const auto data = pointer_cast<const lane_t>(ptr.data());
return std::span<const lane_t>
{
std::next(pointer_cast<const uint64_t>(ptr.data()),
first), ids.size()
std::next(data, first), ids.size()
};
};

Expand All @@ -135,8 +137,7 @@ bool CLASS::get_compact_matches(compact_matches& out,
{
const table::pool::link link
{
possible_narrow_cast<table::pool::link::integer>(
first + row)
possible_narrow_cast<link_t>(first + row)
};

if (!store_.pool.id0.get(ptr0, link, id0) ||
Expand All @@ -157,18 +158,19 @@ bool CLASS::get_compact_matches(compact_matches& out,

auto& matches = found.at(chunk);
for (size_t row{}; row < ids.size(); ++row)
if (const auto it = positions.find(bit_and(ids[row], mask));
it != positions.end())
{
const auto id = bit_and(ids[row], chain::short_id::mask);
if (const auto it = positions.find(id); it != positions.end())
matches.emplace_back(it->second,
possible_narrow_cast<table::pool::link::integer>(
first + row));
possible_narrow_cast<link_t>(first + row));
}
});

if (fail.load(std::memory_order_relaxed))
return false;

for (const auto& matches: found)
out.insert(out.end(), matches.begin(), matches.end());
out.insert(out.end(), matches.cbegin(), matches.cend());

return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,9 @@ bool CLASS::set_pooled(const tx_link& link, const transaction& tx,
const auto bip16 = ctx.is_enabled(chain::flags::bip16_rule);
const auto bip141 = ctx.is_enabled(chain::flags::bip141_rule);
const auto sigops = tx.signature_operations(bip16, bip141);
const auto words = from_little_endians(array_cast<uint64_t>(
tx.get_hash(true)));
using lane_t = schema::pool::witness_lane;
const auto hash = tx.get_hash(true);
const auto words = from_little_endians(array_cast<lane_t>(hash));

// ========================================================================
const auto scope = get_transactor();
Expand Down
4 changes: 3 additions & 1 deletion include/bitcoin/database/impl/query/properties_block.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,9 @@ hash_digest CLASS::get_wtxid(const tx_link& link) const NOEXCEPT
!store_.pool.id3.get(row, id3))
return {};

const auto words = to_little_endians(std_array<uint64_t, 4>
using lane_t = schema::pool::witness_lane;
using lanes_t = std_array<lane_t, schema::pool::witness_lanes>;
const auto words = to_little_endians(lanes_t
{
id0.word, id1.word, id2.word, id3.word
});
Expand Down
12 changes: 8 additions & 4 deletions include/bitcoin/database/query.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class query
using chain_state_cptr = system::chain::chain_state::cptr;
using chain_context = system::chain::context;
using prevout_spends = table::prevout::spends;
using short_id = system::chain::short_id::integer;
using ec_compresseds = system::ec_compresseds;
using ec_compressed = system::ec_compressed;
using ec_signatures = system::ec_signatures;
Expand Down Expand Up @@ -626,10 +627,10 @@ class query
code validate_pooled(const header_link& link, const chain_context& ctx,
uint64_t subsidy_interval, uint64_t initial_subsidy) NOEXCEPT;

/// Pooled tx links by compact block short id (low 48 bits of the siphash
/// of wtxid), terminal where not pooled or ambiguous.
/// Pooled tx links by compact block short id (masked siphash of wtxid),
/// terminal where not pooled or ambiguous.
code get_compact_links(tx_links& out,
const std::vector<uint64_t>& short_ids,
const std::vector<short_id>& short_ids,
const system::siphash_key& key) const NOEXCEPT;

/// Header properties.
Expand Down Expand Up @@ -957,7 +958,7 @@ class query
/// Called by get_compact_links.
using compact_matches = std::vector<std::pair<size_t, table::pool::link>>;
bool get_compact_matches(compact_matches& out,
const std::unordered_map<uint64_t, size_t>& positions,
const std::unordered_map<short_id, size_t>& positions,
const system::siphash_key& key) const NOEXCEPT;

/// Support set_strong and set_unstrong writers.
Expand Down Expand Up @@ -1091,6 +1092,9 @@ class query
// This value should never be read, but may be useful in debugging.
static constexpr uint32_t unspecified_timestamp = max_uint32;

// Pool rows hashed by one task of the compact block short id scan.
static constexpr size_t short_id_chunk_rows = system::power2(14u);

// Chain objects.
template <typename Bool>
static bool push_bool(std::vector<Bool>& stack,
Expand Down
10 changes: 6 additions & 4 deletions include/bitcoin/database/tables/caches/pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,32 +37,34 @@ struct pool_context
static constexpr auto suffix = "context"_t;
};

/// One 64 bit word of the short id hash (common to the id columns).
/// One lane of the witness hash (common to the id columns).
struct pool_word
: public schema::pool_id0
{
using lane = schema::pool::witness_lane;

static constexpr link count() NOEXCEPT
{
return 1;
}

inline bool from_data(reader& source) NOEXCEPT
{
word = source.read_little_endian<uint64_t>();
word = source.read_little_endian<lane>();
BC_ASSERT(!source || source.get_read_position() == minrow);
return source;
}

inline bool to_data(flipper& sink) const NOEXCEPT
{
sink.write_little_endian<uint64_t>(word);
sink.write_little_endian<lane>(word);
BC_ASSERT(!sink || sink.get_write_position() == minrow);
return sink;
}

inline bool operator==(const pool_word&) const NOEXCEPT = default;

uint64_t word{};
lane word{};
};

/// Transaction identifier columns (words 0-3 of the short id hash).
Expand Down
13 changes: 8 additions & 5 deletions include/bitcoin/database/tables/schema.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ constexpr size_t prevout_ = 5; // ->prevout slab.
constexpr size_t txs_ = 5; // ->txs slab.
constexpr size_t tx = 4; // ->tx record.
constexpr size_t block = 3; // ->header record.
constexpr size_t pool_ = 4; // ->pool record.
constexpr size_t pool_ = 4; // ->pool record.
constexpr size_t filter_ = 5; // ->filter record.
constexpr size_t doubles_ = 4; // doubles bucket (no actual keys).

Expand Down Expand Up @@ -415,6 +415,8 @@ struct pool
static constexpr size_t pk = schema::pool_;
using link = linkage<pk, to_bits(pk)>;
using key = system::data_array<sk>;
static constexpr size_t witness_lanes = 4;
using witness_lane = unsigned_type<schema::hash / witness_lanes>;
static constexpr size_t minsize =
schema::flags + // context.flags
schema::height_ + // context.height
Expand All @@ -430,14 +432,15 @@ struct pool
static_assert(minrow == 34u);
static_assert(link::size == 4u);
static_assert(cell == 4u);
static_assert(witness_lanes * sizeof(witness_lane) == schema::hash);
bool operator==(const pool&) const NOEXCEPT = default;
};

// pool columns (records aligned with the pool spine).
TABLE_COLUMN(pool_id0, sizeof(uint64_t));
TABLE_COLUMN(pool_id1, sizeof(uint64_t));
TABLE_COLUMN(pool_id2, sizeof(uint64_t));
TABLE_COLUMN(pool_id3, sizeof(uint64_t));
TABLE_COLUMN(pool_id0, sizeof(pool::witness_lane));
TABLE_COLUMN(pool_id1, sizeof(pool::witness_lane));
TABLE_COLUMN(pool_id2, sizeof(pool::witness_lane));
TABLE_COLUMN(pool_id3, sizeof(pool::witness_lane));
static_assert(is_same_type<pool_id0::link, pool::link>);

// record nomap
Expand Down
Loading