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
8 changes: 8 additions & 0 deletions include/bitcoin/database/impl/query/confirmed.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ bool CLASS::is_candidate_header(const header_link& link) const NOEXCEPT
return store_.candidate.at(height) == link;
}

// An unassociated candidate extending the confirmed top.
TEMPLATE
bool CLASS::is_candidate_extension(const header_link& link) const NOEXCEPT
{
return !is_associated(link) && is_candidate_header(link) &&
(to_confirmed(get_top_confirmed()) == to_parent(link));
}

TEMPLATE
bool CLASS::is_confirmed_block(const header_link& link) const NOEXCEPT
{
Expand Down
23 changes: 23 additions & 0 deletions include/bitcoin/database/impl/query/properties_block.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,29 @@ hashes CLASS::get_wtxids(const header_link& link) const NOEXCEPT
return hashes;
}

// The coinbase commits to the witness root, otherwise the block is
// unsegregated and its witness root is the header merkle root.
TEMPLATE
bool CLASS::is_witness_committed(const hash_digest& witness_root,
const header_link& link) const NOEXCEPT
{
using namespace system;
const auto coinbase = get_transaction(to_coinbase(link), true);
if (!coinbase)
return false;

hash_cref commitment{ null_hash };
hash_cref reservation{ null_hash };
if (!coinbase->get_witness_commitment(commitment))
{
const auto header = get_header(link);
return header && (header->merkle_root() == witness_root);
}

return coinbase->get_witness_reservation(reservation) &&
(bitcoin_hash(witness_root, reservation) == commitment.get());
}

// The pool id columns hold the witness hash of a pooled tx, otherwise (such as
// for any coinbase) the witness hash is computed from the stored tx.
TEMPLATE
Expand Down
3 changes: 3 additions & 0 deletions include/bitcoin/database/query.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,8 @@ class query
hash_digest get_top_candidate_hash() const NOEXCEPT;
hashes get_tx_keys(const header_link& link) const NOEXCEPT;
hashes get_wtxids(const header_link& link) const NOEXCEPT;
bool is_witness_committed(const hash_digest& witness_root,
const header_link& link) const NOEXCEPT;
size_t get_tx_count(const header_link& link) const NOEXCEPT;
size_t get_branch_tx_count(const header_link& link) const NOEXCEPT;
inline hash_digest get_header_key(const header_link& link) const NOEXCEPT;
Expand Down Expand Up @@ -711,6 +713,7 @@ class query

/// These compare strong with height index.
bool is_candidate_header(const header_link& link) const NOEXCEPT;
bool is_candidate_extension(const header_link& link) const NOEXCEPT;
bool is_confirmed_block(const header_link& link) const NOEXCEPT;
bool is_confirmed_tx(const tx_link& link) const NOEXCEPT;
bool is_confirmed_input(const ins_link& link) const NOEXCEPT;
Expand Down
22 changes: 22 additions & 0 deletions test/query/confirmed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,28 @@ BOOST_AUTO_TEST_CASE(query_confirmed__is_candidate_block__push_pop_candidate__ex
BOOST_REQUIRE(!query.is_candidate_header(database::header_link::terminal));
}

BOOST_AUTO_TEST_CASE(query_confirmed__is_candidate_extension__candidates__expected)
{
settings settings{};
settings.path = TEST_DIRECTORY;
test::chunk_store store{ settings };
test::query_accessor query{ store };
BOOST_REQUIRE(!store.create(test::events_handler));
BOOST_REQUIRE(query.initialize(test::genesis));
BOOST_REQUIRE(query.set(test::block1.header(), context{ 0, 1, 0 }, {}, false));
BOOST_REQUIRE(query.set(test::block2.header(), context{ 0, 2, 0 }, {}, false));
BOOST_REQUIRE(!query.is_candidate_extension(0));
BOOST_REQUIRE(!query.is_candidate_extension(1));

BOOST_REQUIRE(query.push_candidate(1));
BOOST_REQUIRE(query.push_candidate(2));
BOOST_REQUIRE(query.is_candidate_extension(1));
BOOST_REQUIRE(!query.is_candidate_extension(2));

BOOST_REQUIRE(query.set(test::block1, context{ 0, 1, 0 }, {}, false, false));
BOOST_REQUIRE(!query.is_candidate_extension(1));
}

BOOST_AUTO_TEST_CASE(query_confirmed__get_confirmed_height__push_pop_confirmed__expected)
{
settings settings{};
Expand Down
37 changes: 37 additions & 0 deletions test/query/properties_block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,4 +255,41 @@ BOOST_AUTO_TEST_CASE(query_properties_block__get_block_state__unconfirmable__blo
BOOST_REQUIRE_EQUAL(query.get_block_state(1), error::block_unconfirmable);
}

BOOST_AUTO_TEST_CASE(query_properties_block__is_witness_committed__genesis__header_merkle_root)
{
settings settings{};
settings.path = TEST_DIRECTORY;
test::chunk_store store{ settings };
test::query_accessor query{ store };
BOOST_REQUIRE(!store.create(test::events_handler));
BOOST_REQUIRE(query.initialize(test::genesis));

BOOST_REQUIRE(query.is_witness_committed(test::genesis.header().merkle_root(), 0));
BOOST_REQUIRE(!query.is_witness_committed(one_hash, 0));
}

BOOST_AUTO_TEST_CASE(query_properties_block__is_witness_committed__committed__expected)
{
using namespace system::chain;
settings settings{};
settings.path = TEST_DIRECTORY;
test::chunk_store store{ settings };
test::query_accessor query{ store };
BOOST_REQUIRE(!store.create(test::events_handler));
BOOST_REQUIRE(query.initialize(test::genesis));

const hash_digest reserved_hash{ 0x02 };
const auto commitment = bitcoin_hash(one_hash, reserved_hash);
const script commitment_script(splice(base16_chunk("6a24aa21a9ed"), commitment), false);
const witness reserved{ chunk_cptrs{ to_shared(to_chunk(reserved_hash)) } };
const inputs ins{ input{ point{}, script{ operations{ operation{ data_chunk{ 0x01, 0x02 }, false } } }, reserved, 0xffffffff } };
const transaction coinbase{ 1, ins, outputs{ output{ 0, commitment_script } }, 0 };
const block block1{ header{ 1, test::genesis.hash(), null_hash, 0, 0, 0 }, transactions{ coinbase } };
BOOST_REQUIRE(query.set(block1, context{}, {}, false, false));

const auto link = query.to_header(block1.hash());
BOOST_REQUIRE(query.is_witness_committed(one_hash, link));
BOOST_REQUIRE(!query.is_witness_committed(reserved_hash, link));
}

BOOST_AUTO_TEST_SUITE_END()
Loading