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
2 changes: 2 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ test_libbitcoin_database_test_SOURCES = \
test/query/network.cpp \
test/query/objects.cpp \
test/query/optional.cpp \
test/query/services.cpp \
test/query/translate.cpp \
test/query/validate.cpp \
test/tables/archives/header.cpp \
Expand Down Expand Up @@ -187,6 +188,7 @@ include_bitcoin_database_impl_query_HEADERS = \
include/bitcoin/database/impl/query/objects.ipp \
include/bitcoin/database/impl/query/optional.ipp \
include/bitcoin/database/impl/query/query.ipp \
include/bitcoin/database/impl/query/services.ipp \
include/bitcoin/database/impl/query/translate.ipp \
include/bitcoin/database/impl/query/validate.ipp

Expand Down
1 change: 1 addition & 0 deletions builds/cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ if (with-tests)
"../../test/query/network.cpp"
"../../test/query/objects.cpp"
"../../test/query/optional.cpp"
"../../test/query/services.cpp"
"../../test/query/translate.cpp"
"../../test/query/validate.cpp"
"../../test/tables/archives/header.cpp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@
<ClCompile Include="..\..\..\..\test\query\network.cpp" />
<ClCompile Include="..\..\..\..\test\query\objects.cpp" />
<ClCompile Include="..\..\..\..\test\query\optional.cpp" />
<ClCompile Include="..\..\..\..\test\query\services.cpp" />
<ClCompile Include="..\..\..\..\test\query\translate.cpp" />
<ClCompile Include="..\..\..\..\test\query\validate.cpp" />
<ClCompile Include="..\..\..\..\test\settings.cpp" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@
<ClCompile Include="..\..\..\..\test\query\optional.cpp">
<Filter>src\query</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\test\query\services.cpp">
<Filter>src\query</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\test\query\translate.cpp">
<Filter>src\query</Filter>
</ClCompile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@
<None Include="..\..\..\..\include\bitcoin\database\impl\query\objects.ipp" />
<None Include="..\..\..\..\include\bitcoin\database\impl\query\optional.ipp" />
<None Include="..\..\..\..\include\bitcoin\database\impl\query\query.ipp" />
<None Include="..\..\..\..\include\bitcoin\database\impl\query\services.ipp" />
<None Include="..\..\..\..\include\bitcoin\database\impl\query\translate.ipp" />
<None Include="..\..\..\..\include\bitcoin\database\impl\query\validate.ipp" />
<None Include="..\..\..\..\include\bitcoin\database\impl\store.ipp" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,9 @@
<None Include="..\..\..\..\include\bitcoin\database\impl\query\query.ipp">
<Filter>include\bitcoin\database\impl\query</Filter>
</None>
<None Include="..\..\..\..\include\bitcoin\database\impl\query\services.ipp">
<Filter>include\bitcoin\database\impl\query</Filter>
</None>
<None Include="..\..\..\..\include\bitcoin\database\impl\query\translate.ipp">
<Filter>include\bitcoin\database\impl\query</Filter>
</None>
Expand Down
6 changes: 5 additions & 1 deletion include/bitcoin/database/impl/query/archive_write.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,9 @@ code CLASS::set_code(const block& block, const header_link& key,
const auto size = block.serialized_size(true);
const auto wire = possible_narrow_cast<bytes>(size);

// Depth is only used for genesis (is_zero(tx_fks[0])).
const auto depth = store_.interval_depth();

// ========================================================================
const auto scope = store_.get_transactor();
constexpr auto positive = true;
Expand All @@ -414,7 +417,8 @@ code CLASS::set_code(const block& block, const header_link& key,
wire,
count,
tx_fks,
std::move(interval)
std::move(interval),
depth
}) ? error::success : error::txs_txs_put;
// ========================================================================
}
Expand Down
147 changes: 1 addition & 146 deletions include/bitcoin/database/impl/query/optional.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#include <bitcoin/system.hpp>
#include <bitcoin/database/define.hpp>

// TODO: address table could use point keys to compress the multimap.
// TODO: address table could use point keys to compress the multimap.

namespace libbitcoin {
namespace database {
Expand Down Expand Up @@ -259,151 +259,6 @@ code CLASS::get_confirmed_balance(std::atomic_bool& cancel, uint64_t& balance,
return error::success;
}

// merkle
// ----------------------------------------------------------------------------

// protected
TEMPLATE
size_t CLASS::interval_span() const NOEXCEPT
{
// span of zero (overflow) is disallowed (division by zero).
// span of one (2^0) caches every block (no optimization, wasted storage).
// span greater than top height eliminates caching (no optimization).
const auto span = system::power2(store_.interval_depth());
return is_zero(span) ? max_size_t : span;
}

// protected
TEMPLATE
CLASS::hash_option CLASS::create_interval(header_link link,
size_t height) const NOEXCEPT
{
// Interval ends at nth block where n is a multiple of span.
// One is a functional but undesirable case (no optimization).
const auto span = interval_span();
BC_ASSERT(!is_zero(span));

// If valid link is provided then empty return implies non-interval height.
if (link.is_terminal() || !system::is_multiple(add1(height), span))
return {};

// Generate the leaf nodes for the span.
hashes leaves(span);
for (auto& leaf: std::views::reverse(leaves))
{
leaf = get_header_key(link);
link = to_parent(link);
}

// Generate the merkle root of the interval ending on link header.
return system::merkle_root(std::move(leaves));
}

// protected
TEMPLATE
CLASS::hash_option CLASS::get_confirmed_interval(size_t height) const NOEXCEPT
{
const auto span = interval_span();
BC_ASSERT(!is_zero(span));

if (!system::is_multiple(add1(height), span))
return {};

table::txs::get_interval txs{};
if (!store_.txs.at(to_confirmed(height), txs))
return {};

return txs.interval;
}

// static/protected
TEMPLATE
void CLASS::merge_merkle(hashes& to, hashes&& from, size_t first) NOEXCEPT
{
using namespace system;
for (const auto& row: block::merkle_branch(first, from.size()))
{
BC_ASSERT(row.sibling * add1(row.width) <= from.size());
const auto it = std::next(from.begin(), row.sibling * row.width);
const auto mover = std::make_move_iterator(it);
to.push_back(merkle_root({ mover, std::next(mover, row.width) }));
}
}

// protected
TEMPLATE
code CLASS::get_merkle_proof(hashes& proof, hashes roots, size_t target,
size_t waypoint) const NOEXCEPT
{
const auto span = interval_span();
BC_ASSERT(!is_zero(span));

const auto first = (target / span) * span;
const auto last = std::min(sub1(first + span), waypoint);
auto other = get_confirmed_hashes(first, add1(last - first));
if (other.empty())
return error::merkle_proof;

using namespace system;
proof.reserve(ceilinged_log2(other.size()) + ceilinged_log2(roots.size()));
merge_merkle(proof, std::move(other), target % span);
merge_merkle(proof, std::move(roots), target / span);
return error::success;
}

// protected
TEMPLATE
code CLASS::get_merkle_tree(hashes& tree, size_t waypoint) const NOEXCEPT
{
const auto span = interval_span();
BC_ASSERT(!is_zero(span));

const auto range = add1(waypoint);
tree.reserve(system::ceilinged_divide(range, span));
for (size_t first{}; first < range; first += span)
{
const auto last = std::min(sub1(first + span), waypoint);
const auto size = add1(last - first);

if (size == span)
{
auto interval = get_confirmed_interval(last);
if (!interval.has_value()) return error::merkle_interval;
tree.push_back(std::move(interval.value()));
}
else
{
auto confirmed = get_confirmed_hashes(first, size);
if (confirmed.empty()) return error::merkle_hashes;
tree.push_back(system::merkle_root(std::move(confirmed)));
}
}

return error::success;
}

TEMPLATE
code CLASS::get_merkle_root_and_proof(hash_digest& root, hashes& proof,
size_t target, size_t waypoint) const NOEXCEPT
{
if (target > waypoint)
return error::merkle_arguments;

if (waypoint > get_top_confirmed())
return error::merkle_not_found;

hashes tree{};
if (const auto ec = get_merkle_tree(tree, waypoint))
return ec;

proof.clear();
if (const auto ec = get_merkle_proof(proof, tree, target, waypoint))
return ec;

root = system::merkle_root(std::move(tree));
return {};
}

////TEMPLATE
////bool CLASS::set_address_output(const output& output,
//// const output_link& link) NOEXCEPT
Expand Down
31 changes: 31 additions & 0 deletions include/bitcoin/database/impl/query/query.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,37 @@ CLASS::query(Store& store) NOEXCEPT
{
}

TEMPLATE
size_t CLASS::interval_span() const NOEXCEPT
{
if (const auto span = span_.load(std::memory_order_relaxed);
is_nonzero(span))
return span;

// initialize_span() never returns zero.
span_.store(initialize_span(), std::memory_order_relaxed);
return span_;
}

// protected
TEMPLATE
size_t CLASS::interval_depth() const NOEXCEPT
{
table::txs::get_genesis_depth txs{};
return store_.txs.at(to_txs(0), txs) ? txs.depth : store_.interval_depth();
}

// protected
TEMPLATE
size_t CLASS::initialize_span() const NOEXCEPT
{
// span of zero (overflow) is disallowed (division by zero).
// span of one (2^0) caches every block (no optimization, wasted storage).
// span greater than top height eliminates caching (no optimization).
const auto span = system::power2(interval_depth());
return is_zero(span) ? max_size_t : span;
}

TEMPLATE
code CLASS::get_code() const NOEXCEPT
{
Expand Down
Loading
Loading