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
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,41 @@ bool CLASS::populate_with_metadata(const input& input,
// Node only (cheap so always include).
input.metadata.parent_tx = tx;

// TODO: Chain only metadata (expensive).
// This is used by node for unconfirmed tx validation.
// This is used by node for unconfirmed tx validation (expensive).
// There are three consensus-relevant heights. These are the height of the
// presumed next block (pool), the height of the block containing previous
// output's transaction, and the height of a block containing a previous
// spender of the previous output. median-time-past is of the prevout.
if (chain)
{
input.metadata.spender_height = max_uint32;
input.metadata.prevout_height = max_uint32;
input.metadata.median_time_past = max_uint32;
auto& metadata = input.metadata;

context ctx{};
if (get_context(ctx, find_strong(metadata.parent_tx)))
{
// Confirmed previous output found at height (and with mtp).
metadata.prevout_height = ctx.height;
metadata.median_time_past = ctx.mtp;
}
else
{
// Confirmed previous output not found.
metadata.prevout_height = max_uint32;
metadata.median_time_past = max_uint32;
}

if (const auto height = find_strong_spender_height(input.point());
!height.is_terminal())
{
// Confirmed spender found at height.
metadata.spender_height = system::possible_narrow_cast<uint32_t>(
height.value);
}
else
{
// Confirmed spender not found.
metadata.spender_height = max_uint32;
}
}

// If read via the store for store confirmation, then...
Expand Down
29 changes: 15 additions & 14 deletions include/bitcoin/database/impl/query/consensus/consensus_strong.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -54,23 +54,29 @@ tx_link CLASS::find_strong_tx(const tx_link& link) const NOEXCEPT

return find_strong_tx(get_tx_key(link));
}

TEMPLATE
tx_link CLASS::find_strong_tx(const hash_digest& tx_hash) const NOEXCEPT
{
// Get all tx links for tx_hash.
tx_links txs{};
for (auto it = store_.tx.it(tx_hash); it; ++it)
txs.push_back(*it);

// Find the first strong tx of the set and return its link.
for (const auto& tx: txs)
// Find the first strong tx of all duplicates and return its link.
for (const auto& tx: to_duplicates(tx_hash))
if (!to_block(tx).is_terminal())
return tx;

return {};
}

TEMPLATE
height_link CLASS::find_strong_spender_height(
const point& point) const NOEXCEPT
{
size_t out{};
for (const auto& sp: to_spenders(point))
if (const auto tx = to_spending_tx(sp); get_tx_height(out, tx))
break;

return { system::possible_narrow_cast<uint32_t>(out) };
}

// find_strong (block)
// ----------------------------------------------------------------------------

Expand All @@ -87,13 +93,8 @@ header_link CLASS::find_strong(const tx_link& link) const NOEXCEPT
TEMPLATE
header_link CLASS::find_strong(const hash_digest& tx_hash) const NOEXCEPT
{
// Get all tx links for tx_hash.
tx_links txs{};
for (auto it = store_.tx.it(tx_hash); it; ++it)
txs.push_back(*it);

// Find the first strong tx of the set and return its block.
for (const auto& tx: txs)
for (const auto& tx: to_duplicates(tx_hash))
if (const auto block = to_block(tx); !block.is_terminal())
return block;

Expand Down
13 changes: 13 additions & 0 deletions include/bitcoin/database/impl/query/navigate/navigate_reverse.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,19 @@ uint32_t CLASS::to_output_index(const tx_link& parent_fk,
return point::null_index;
}

// tx.hash->txs (all instances of same tx by hash)
// ----------------------------------------------------------------------------

TEMPLATE
tx_links CLASS::to_duplicates(const hash_digest& tx_hash) const NOEXCEPT
{
tx_links out{};
for (auto it = store_.tx.it(tx_hash); it; ++it)
out.push_back(*it);

return out;
}

// tx->block[strong]
// ----------------------------------------------------------------------------
// protected (logically hazardous)
Expand Down
3 changes: 3 additions & 0 deletions include/bitcoin/database/impl/query/properties_block.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ bool CLASS::get_bits(uint32_t& bits, const header_link& link) const NOEXCEPT
return true;
}

// context
// ----------------------------------------------------------------------------

TEMPLATE
bool CLASS::get_context(context& ctx, const header_link& link) const NOEXCEPT
{
Expand Down
12 changes: 2 additions & 10 deletions include/bitcoin/database/impl/query/properties_tx.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -53,27 +53,19 @@ inline bool CLASS::is_tx_segregated(const tx_link& link) const NOEXCEPT
TEMPLATE
bool CLASS::get_tx_height(size_t& out, const tx_link& link) const NOEXCEPT
{
const auto fk = find_strong(link);
return is_confirmed_block(fk) && get_height(out, fk);
return get_height(out, find_strong(link));
}

TEMPLATE
bool CLASS::get_tx_position(size_t& out, const tx_link& link) const NOEXCEPT
{
// False implies strong block association not found.
const auto block = find_strong(link);
if (!is_confirmed_block(block))
return false;

// False return implies an integrity error (tx should be indexed).
return get_tx_position(out, link, block);
return get_tx_position(out, link, find_strong(link));
}

TEMPLATE
bool CLASS::get_tx_position(size_t& out, const tx_link& link,
const header_link& block) const NOEXCEPT
{
// False return implies an integrity error (tx must be indexed).
table::txs::get_position txs{ {}, link };
if (!store_.txs.at(to_txs(block), txs))
return false;
Expand Down
6 changes: 4 additions & 2 deletions include/bitcoin/database/query.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,10 @@ class query
tx_link find_strong_tx(const hash_digest& tx_hash) const NOEXCEPT;
header_link find_strong(const tx_link& link) const NOEXCEPT;
header_link find_strong(const hash_digest& tx_hash) const NOEXCEPT;
height_link find_strong_spender_height(const point& point) const NOEXCEPT;

header_link to_parent(const header_link& link) const NOEXCEPT;
tx_links to_duplicates(const hash_digest& tx_hash) const NOEXCEPT;

/// find confirmed objects (reverse navigation)
header_link find_confirmed_block(const hash_digest& tx_hash) const NOEXCEPT;
Expand Down Expand Up @@ -523,8 +526,7 @@ class query
code get_tx_state(uint64_t& fee, size_t& sigops, const tx_link& link,
const context& ctx) const NOEXCEPT;

/// Values.
// get_context(chain::context) sets only flags, median_time_past, height.
/// Header properties.
uint32_t get_top_timestamp(bool confirmed) const NOEXCEPT;
bool get_timestamp(uint32_t& timestamp, const header_link& link) const NOEXCEPT;
bool get_version(uint32_t& version, const header_link& link) const NOEXCEPT;
Expand Down
20 changes: 7 additions & 13 deletions test/query/archive_read.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ BOOST_AUTO_TEST_CASE(query_archive_read__get_tx_height__not_strong__false)
BOOST_CHECK(!query.get_tx_height(out, 1));
}

BOOST_AUTO_TEST_CASE(query_archive_read__get_tx_position__confirmed__expected)
BOOST_AUTO_TEST_CASE(query_archive_read__get_tx_position__strong__expected)
{
settings settings{};
settings.path = TEST_DIRECTORY;
Expand All @@ -399,9 +399,6 @@ BOOST_AUTO_TEST_CASE(query_archive_read__get_tx_position__confirmed__expected)
BOOST_CHECK(query.set(test::block1a, context{ 0, 1, 0 }, false, false));
BOOST_CHECK(query.set(test::block2a, context{ 0, 2, 0 }, false, false));
BOOST_CHECK(query.set(test::block3a, context{ 0, 3, 0 }, false, false));
BOOST_CHECK(query.set_strong(1));
BOOST_CHECK(query.set_strong(2));
BOOST_CHECK(query.set_strong(3));

size_t out{};
const auto foo = query.get_tx_position(out, 0);
Expand All @@ -412,9 +409,9 @@ BOOST_AUTO_TEST_CASE(query_archive_read__get_tx_position__confirmed__expected)
BOOST_CHECK(!query.get_tx_position(out, 2));
BOOST_CHECK(!query.get_tx_position(out, 3));
BOOST_CHECK(!query.get_tx_position(out, 4));
BOOST_CHECK(query.push_confirmed(1, false));
BOOST_CHECK(query.push_confirmed(2, false));
BOOST_CHECK(query.push_confirmed(3, false));
BOOST_CHECK(query.set_strong(1));
BOOST_CHECK(query.set_strong(2));
BOOST_CHECK(query.set_strong(3));

BOOST_CHECK_EQUAL(out, 0u);
BOOST_CHECK(query.get_tx_position(out, 0));
Expand Down Expand Up @@ -448,9 +445,6 @@ BOOST_AUTO_TEST_CASE(query_archive_read__get_tx_position__always__expected)
BOOST_CHECK(query.set(test::block2a, context{ 0, 2, 0 }, false, false));
BOOST_CHECK(query.set(test::block3a, context{ 0, 3, 0 }, false, false));
BOOST_CHECK(query.set(test::tx4));
BOOST_CHECK(query.set_strong(1));
BOOST_CHECK(query.set_strong(2));
BOOST_CHECK(query.set_strong(3));

size_t out{};
BOOST_CHECK(query.get_tx_position(out, 0));
Expand All @@ -460,9 +454,9 @@ BOOST_AUTO_TEST_CASE(query_archive_read__get_tx_position__always__expected)
BOOST_CHECK(!query.get_tx_position(out, 2));
BOOST_CHECK(!query.get_tx_position(out, 3));
BOOST_CHECK(!query.get_tx_position(out, 4));
BOOST_CHECK(query.push_confirmed(1, false));
BOOST_CHECK(query.push_confirmed(2, false));
BOOST_CHECK(query.push_confirmed(3, false));
BOOST_CHECK(query.set_strong(1));
BOOST_CHECK(query.set_strong(2));
BOOST_CHECK(query.set_strong(3));

BOOST_CHECK_EQUAL(out, 0u);
BOOST_CHECK(query.get_tx_position(out, 0));
Expand Down
18 changes: 6 additions & 12 deletions test/query/archive_write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1252,9 +1252,6 @@ BOOST_AUTO_TEST_CASE(query_archive_write__get_tx_position__confirmed__expected)
BOOST_CHECK(query.set(test::block1a, context{ 0, 1, 0 }, false, false));
BOOST_CHECK(query.set(test::block2a, context{ 0, 2, 0 }, false, false));
BOOST_CHECK(query.set(test::block3a, context{ 0, 3, 0 }, false, false));
BOOST_CHECK(query.set_strong(1));
BOOST_CHECK(query.set_strong(2));
BOOST_CHECK(query.set_strong(3));

size_t out{};
const auto foo = query.get_tx_position(out, 0);
Expand All @@ -1265,9 +1262,9 @@ BOOST_AUTO_TEST_CASE(query_archive_write__get_tx_position__confirmed__expected)
BOOST_CHECK(!query.get_tx_position(out, 2));
BOOST_CHECK(!query.get_tx_position(out, 3));
BOOST_CHECK(!query.get_tx_position(out, 4));
BOOST_CHECK(query.push_confirmed(1, false));
BOOST_CHECK(query.push_confirmed(2, false));
BOOST_CHECK(query.push_confirmed(3, false));
BOOST_CHECK(query.set_strong(1));
BOOST_CHECK(query.set_strong(2));
BOOST_CHECK(query.set_strong(3));

BOOST_CHECK_EQUAL(out, 0u);
BOOST_CHECK(query.get_tx_position(out, 0));
Expand Down Expand Up @@ -1295,9 +1292,6 @@ BOOST_AUTO_TEST_CASE(query_archive_write__get_tx_position__always__expected)
BOOST_CHECK(query.set(test::block2a, context{ 0, 2, 0 }, false, false));
BOOST_CHECK(query.set(test::block3a, context{ 0, 3, 0 }, false, false));
BOOST_CHECK(query.set(test::tx4));
BOOST_CHECK(query.set_strong(1));
BOOST_CHECK(query.set_strong(2));
BOOST_CHECK(query.set_strong(3));

size_t out{};
BOOST_CHECK(query.get_tx_position(out, 0));
Expand All @@ -1307,9 +1301,9 @@ BOOST_AUTO_TEST_CASE(query_archive_write__get_tx_position__always__expected)
BOOST_CHECK(!query.get_tx_position(out, 2));
BOOST_CHECK(!query.get_tx_position(out, 3));
BOOST_CHECK(!query.get_tx_position(out, 4));
BOOST_CHECK(query.push_confirmed(1, false));
BOOST_CHECK(query.push_confirmed(2, false));
BOOST_CHECK(query.push_confirmed(3, false));
BOOST_CHECK(query.set_strong(1));
BOOST_CHECK(query.set_strong(2));
BOOST_CHECK(query.set_strong(3));

BOOST_CHECK_EQUAL(out, 0u);
BOOST_CHECK(query.get_tx_position(out, 0));
Expand Down