Skip to content

Commit

Permalink
Merge pull request #529 from evoskuil/master
Browse files Browse the repository at this point in the history
Populate 'inside' metadata, update tests, fix metadata side effects.
  • Loading branch information
evoskuil authored Jan 5, 2025
2 parents ab4072d + 2bd5c7d commit 62067a4
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 35 deletions.
1 change: 1 addition & 0 deletions include/bitcoin/database/impl/query/archive.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ bool CLASS::populate(const input& input) const NOEXCEPT
const auto tx = to_tx(input.point().hash());
input.prevout = get_output(tx, input.point().index());
input.metadata.coinbase = is_coinbase(tx);
input.metadata.inside = false;
input.metadata.parent = tx;

// input.metadata is not populated.
Expand Down
108 changes: 73 additions & 35 deletions test/query/archive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,24 @@ BOOST_AUTO_TEST_CASE(query_archive__set_block_txs__get_block__expected)
BOOST_REQUIRE_EQUAL(hashes, test::genesis.transaction_hashes(false));
}

// populate
// ----------------------------------------------------------------------------

// METADATA IS SETTABLE ON CONST TEST OBJECTS.
// COPY CONSTRUCTION CREATES SAHRED POINTER REFERENCES.
// SO POPULATE ON CONST OBJECTS HAS SIDE EFFECTS IF THE OBJECTS SPAN TESTS.
const auto& clean_(const auto& block_or_tx) NOEXCEPT
{
const auto inputs = block_or_tx.inputs_ptr();
for (const auto& input: *inputs)
{
input->prevout.reset();
input->metadata = system::chain::prevout{};
}

return block_or_tx;
}

// First four blocks have only coinbase txs.
BOOST_AUTO_TEST_CASE(query_archive__populate__null_prevouts__true)
{
Expand All @@ -772,10 +790,10 @@ BOOST_AUTO_TEST_CASE(query_archive__populate__null_prevouts__true)
BOOST_REQUIRE(query.set(test::block2, test::context, false, false));
BOOST_REQUIRE(query.set(test::block3, test::context, false, false));

system::chain::block copy{ test::genesis };
system::chain::block copy1{ test::block1 };
system::chain::block copy2{ test::block2 };
system::chain::block copy3{ test::block3 };
const auto& copy = clean_(test::genesis);
const auto& copy1 = clean_(test::block1);
const auto& copy2 = clean_(test::block2);
const auto& copy3 = clean_(test::block3);

BOOST_REQUIRE(query.populate(copy));
BOOST_REQUIRE(query.populate(copy1));
Expand All @@ -795,26 +813,26 @@ BOOST_AUTO_TEST_CASE(query_archive__populate__partial_prevouts__false)
BOOST_REQUIRE(query.set(test::block2a, test::context, false, false));
BOOST_REQUIRE(query.set(test::tx4));

system::chain::block copy1{ test::block1a };
const auto& block1a = clean_(test::block1a);

// Block populate treates first tx as null point.
BOOST_REQUIRE( query.populate(copy1));
BOOST_REQUIRE(!query.populate(*copy1.transactions_ptr()->at(0)));
BOOST_REQUIRE(!query.populate(*copy1.inputs_ptr()->at(0)));
BOOST_REQUIRE(!query.populate(*copy1.inputs_ptr()->at(2)));
BOOST_REQUIRE( query.populate(block1a));
BOOST_REQUIRE(!query.populate(*block1a.transactions_ptr()->at(0)));
BOOST_REQUIRE(!query.populate(*block1a.inputs_ptr()->at(0)));
BOOST_REQUIRE(!query.populate(*block1a.inputs_ptr()->at(2)));

// Block populate treates first tx as null point and other has missing prevouts.
system::chain::block copy2{ test::block2a };
BOOST_REQUIRE(!query.populate(copy2));
BOOST_REQUIRE( query.populate(*copy2.transactions_ptr()->at(0)));
BOOST_REQUIRE(!query.populate(*copy2.transactions_ptr()->at(1)));
BOOST_REQUIRE( query.populate(*copy2.inputs_ptr()->at(0)));
BOOST_REQUIRE(!query.populate(*copy2.inputs_ptr()->at(3)));

system::chain::transaction copy4{ test::tx4 };
BOOST_REQUIRE(query.populate(copy4));
BOOST_REQUIRE(query.populate(*copy4.inputs_ptr()->at(0)));
BOOST_REQUIRE(query.populate(*copy4.inputs_ptr()->at(1)));
const auto& block2a = clean_(test::block2a);
BOOST_REQUIRE(!query.populate(block2a));
BOOST_REQUIRE( query.populate(*block2a.transactions_ptr()->at(0)));
BOOST_REQUIRE(!query.populate(*block2a.transactions_ptr()->at(1)));
BOOST_REQUIRE( query.populate(*block2a.inputs_ptr()->at(0)));
BOOST_REQUIRE(!query.populate(*block2a.inputs_ptr()->at(3)));

const auto& tx4 = clean_(test::tx4);
BOOST_REQUIRE(query.populate(tx4));
BOOST_REQUIRE(query.populate(*tx4.inputs_ptr()->at(0)));
BOOST_REQUIRE(query.populate(*tx4.inputs_ptr()->at(1)));
}

BOOST_AUTO_TEST_CASE(query_archive__populate__metadata__expected)
Expand All @@ -831,28 +849,48 @@ BOOST_AUTO_TEST_CASE(query_archive__populate__metadata__expected)
BOOST_REQUIRE(!query.is_coinbase(1));

// Genesis only has coinbase, which does not spend.
system::chain::block copy{ test::genesis };
BOOST_REQUIRE(query.populate(copy));
BOOST_REQUIRE(!copy.inputs_ptr()->at(0)->prevout);
const auto& genesis = clean_(test::genesis);

BOOST_REQUIRE(!genesis.inputs_ptr()->at(0)->prevout);
BOOST_REQUIRE( genesis.inputs_ptr()->at(0)->metadata.inside);
BOOST_REQUIRE( genesis.inputs_ptr()->at(0)->metadata.coinbase);
BOOST_REQUIRE_EQUAL(genesis.inputs_ptr()->at(0)->metadata.parent, 0u);

BOOST_REQUIRE(query.populate(genesis));

BOOST_REQUIRE(!genesis.inputs_ptr()->at(0)->prevout);
BOOST_REQUIRE( genesis.inputs_ptr()->at(0)->metadata.inside);
BOOST_REQUIRE( genesis.inputs_ptr()->at(0)->metadata.coinbase);
BOOST_REQUIRE_EQUAL(genesis.inputs_ptr()->at(0)->metadata.parent, 0u);

// Transaction population.
system::chain::transaction copy4{ test::tx4 };
BOOST_REQUIRE(query.populate(copy4));
const auto& tx4 = clean_(test::tx4);

BOOST_REQUIRE(!tx4.inputs_ptr()->at(0)->prevout);
BOOST_REQUIRE( tx4.inputs_ptr()->at(0)->metadata.inside);
BOOST_REQUIRE( tx4.inputs_ptr()->at(0)->metadata.coinbase);
BOOST_REQUIRE_EQUAL(tx4.inputs_ptr()->at(0)->metadata.parent, 0u);
BOOST_REQUIRE(!tx4.inputs_ptr()->at(1)->prevout);
BOOST_REQUIRE( tx4.inputs_ptr()->at(1)->metadata.inside);
BOOST_REQUIRE( tx4.inputs_ptr()->at(1)->metadata.coinbase);
BOOST_REQUIRE_EQUAL(tx4.inputs_ptr()->at(1)->metadata.parent, 0u);

BOOST_REQUIRE(query.populate(tx4));

// TODO: test non-coinbase and other parent.
// spent/mtp are defaults, coinbase/parent are set (to non-default values).
BOOST_REQUIRE( copy4.inputs_ptr()->at(0)->prevout);
BOOST_REQUIRE( copy4.inputs_ptr()->at(0)->metadata.spent);
BOOST_REQUIRE(!copy4.inputs_ptr()->at(0)->metadata.coinbase);
BOOST_REQUIRE_EQUAL(copy4.inputs_ptr()->at(0)->metadata.parent, 1u);
BOOST_REQUIRE_EQUAL(copy4.inputs_ptr()->at(0)->metadata.median_time_past, max_uint32);
BOOST_REQUIRE( copy4.inputs_ptr()->at(1)->prevout);
BOOST_REQUIRE( copy4.inputs_ptr()->at(1)->metadata.spent);
BOOST_REQUIRE(!copy4.inputs_ptr()->at(1)->metadata.coinbase);
BOOST_REQUIRE_EQUAL(copy4.inputs_ptr()->at(1)->metadata.parent, 1u);
BOOST_REQUIRE_EQUAL(copy4.inputs_ptr()->at(1)->metadata.median_time_past, max_uint32);
BOOST_REQUIRE( tx4.inputs_ptr()->at(0)->prevout);
BOOST_REQUIRE(!tx4.inputs_ptr()->at(0)->metadata.inside);
BOOST_REQUIRE(!tx4.inputs_ptr()->at(0)->metadata.coinbase);
BOOST_REQUIRE_EQUAL(tx4.inputs_ptr()->at(0)->metadata.parent, 1u);
BOOST_REQUIRE( tx4.inputs_ptr()->at(1)->prevout);
BOOST_REQUIRE(!tx4.inputs_ptr()->at(1)->metadata.inside);
BOOST_REQUIRE(!tx4.inputs_ptr()->at(1)->metadata.coinbase);
BOOST_REQUIRE_EQUAL(tx4.inputs_ptr()->at(1)->metadata.parent, 1u);
}

// ----------------------------------------------------------------------------

// archive (foreign-keyed)

BOOST_AUTO_TEST_CASE(query_archive__is_coinbase__coinbase__true)
Expand Down

0 comments on commit 62067a4

Please sign in to comment.