View in context in the libbitcoin Slack #general mirror.
BOOST_AUTO_TEST_CASE(chaser_validate__process_batch__late_invalid_batched_link__does_not_become_valid)
{
configuration config{ chain::selection::mainnet };
config.database.path = TEST_DIRECTORY;
config.node.batch_signatures = 1;
const auto events = [](auto, auto) NOEXCEPT {};
store store_{ config.database };
query query_{ store_ };
BOOST_REQUIRE(test::clear(TEST_DIRECTORY));
BOOST_REQUIRE_EQUAL(store_.create(events), database::error::success);
BOOST_REQUIRE(query_.initialize(config.bitcoin.genesis_block));
const chain::block invalid_block{ block1_data, true };
const chain::block trigger_block{ block2_data, true };
const chain::block valid_block{ block3_data, true };
BOOST_REQUIRE(query_.set(invalid_block, database::context{ 0, 1, 0 }, false, false));
BOOST_REQUIRE(query_.set(trigger_block, database::context{ 0, 2, 0 }, false, false));
BOOST_REQUIRE(query_.set(valid_block, database::context{ 0, 3, 0 }, false, false));
const auto invalid_link = query_.to_header(invalid_block.hash());
const auto trigger_link = query_.to_header(trigger_block.hash());
const auto valid_link = query_.to_header(valid_block.hash());
BOOST_REQUIRE(query_.push_candidate(invalid_link));
BOOST_REQUIRE(query_.push_candidate(trigger_link));
BOOST_REQUIRE(query_.push_candidate(valid_link));
// invalid_link has a bad sig row, trigger_link has a good sig row.
BOOST_REQUIRE(query_.set_signature(sighash_bad, ecdsa_compressed,
ecdsa_signature, 0, invalid_link));
BOOST_REQUIRE(query_.set_signature(ecdsa_sighash, ecdsa_compressed,
ecdsa_signature, 0, trigger_link));
BOOST_REQUIRE_EQUAL(query_.ecdsa_records(), 2u);
code invalid_state{};
code trigger_state{};
code valid_state{};
{
const network::logger log{};
full_node node{ query_, config, log };
batch_test_chaser chaser{ node };
// trigger_link push_batch() processes both table rows before
// invalid_link delayed push_batch() has appended invalid_link to batched_
chaser.complete_batched(trigger_link, 2u);
chaser.drain();
BOOST_REQUIRE_EQUAL(query_.ecdsa_records(), 0u);
BOOST_REQUIRE_EQUAL(query_.get_block_state(invalid_link),
database::error::block_unconfirmable);
BOOST_REQUIRE_EQUAL(query_.get_block_state(trigger_link),
database::error::block_valid);
// invalid_link arrives late into batched_ after its bad row was purged
chaser.complete_batched(invalid_link, 1u);
chaser.drain();
// later good batch causes process_valids() to iterate the stale
// invalid_link and call set_block_valid() on it.
BOOST_REQUIRE(query_.set_signature(ecdsa_sighash, ecdsa_compressed,
ecdsa_signature, 0, valid_link));
chaser.complete_batched(valid_link, 3u);
chaser.drain();
invalid_state = query_.get_block_state(invalid_link);
trigger_state = query_.get_block_state(trigger_link);
valid_state = query_.get_block_state(valid_link);
}
BOOST_REQUIRE(!store_.close(events));
// this fails on upstream: invalid_state becomes block_valid.
BOOST_CHECK_EQUAL(invalid_state, database::error::block_unconfirmable);
BOOST_CHECK_EQUAL(trigger_state, database::error::block_valid);
BOOST_CHECK_EQUAL(valid_state, database::error::block_valid);
} (edited)