mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-11 16:17:54 +02:00
kernel: Add support for block headers
Introduces btck_BlockHeader type with accessor methods and btck_chainstate_manager_process_block_header() for validating headers without full blocks. Also, adds btck_chainstate_manager_get_best_entry() to query the header with most cumulative proof-of-work. Co-authored-by: TheCharlatan <seb.kung@gmail.com>
This commit is contained in:
@@ -659,6 +659,39 @@ BOOST_AUTO_TEST_CASE(btck_context_tests)
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(btck_block_header_tests)
|
||||
{
|
||||
// Block header format: version(4) + prev_hash(32) + merkle_root(32) + timestamp(4) + bits(4) + nonce(4) = 80 bytes
|
||||
BlockHeader header_0{hex_string_to_byte_vec("00e07a26beaaeee2e71d7eb19279545edbaf15de0999983626ec00000000000000000000579cf78b65229bfb93f4a11463af2eaa5ad91780f27f5d147a423bea5f7e4cdf2a47e268b4dd01173a9662ee")};
|
||||
BOOST_CHECK_EQUAL(byte_span_to_hex_string_reversed(header_0.Hash().ToBytes()), "00000000000000000000325c7e14a4ee3b4fcb2343089a839287308a0ddbee4f");
|
||||
BlockHeader header_1{hex_string_to_byte_vec("00c00020e7cb7b4de21d26d55bd384017b8bb9333ac3b2b55bed00000000000000000000d91b4484f801b99f03d36b9d26cfa83420b67f81da12d7e6c1e7f364e743c5ba9946e268b4dd011799c8533d")};
|
||||
CheckHandle(header_0, header_1);
|
||||
|
||||
// Test error handling for invalid data
|
||||
BOOST_CHECK_THROW(BlockHeader{hex_string_to_byte_vec("00")}, std::runtime_error);
|
||||
BOOST_CHECK_THROW(BlockHeader{hex_string_to_byte_vec("")}, std::runtime_error);
|
||||
|
||||
// Test all header field accessors using mainnet block 1
|
||||
auto mainnet_block_1_header = hex_string_to_byte_vec("010000006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e61bc6649ffff001d01e36299");
|
||||
BlockHeader header{mainnet_block_1_header};
|
||||
BOOST_CHECK_EQUAL(header.Version(), 1);
|
||||
BOOST_CHECK_EQUAL(header.Timestamp(), 1231469665);
|
||||
BOOST_CHECK_EQUAL(header.Bits(), 0x1d00ffff);
|
||||
BOOST_CHECK_EQUAL(header.Nonce(), 2573394689);
|
||||
BOOST_CHECK_EQUAL(byte_span_to_hex_string_reversed(header.Hash().ToBytes()), "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048");
|
||||
auto prev_hash = header.PrevHash();
|
||||
BOOST_CHECK_EQUAL(byte_span_to_hex_string_reversed(prev_hash.ToBytes()), "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
|
||||
|
||||
auto raw_block = hex_string_to_byte_vec("010000006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e61bc6649ffff001d01e362990101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000");
|
||||
Block block{raw_block};
|
||||
BlockHeader block_header{block.GetHeader()};
|
||||
BOOST_CHECK_EQUAL(block_header.Version(), 1);
|
||||
BOOST_CHECK_EQUAL(block_header.Timestamp(), 1231469665);
|
||||
BOOST_CHECK_EQUAL(block_header.Bits(), 0x1d00ffff);
|
||||
BOOST_CHECK_EQUAL(block_header.Nonce(), 2573394689);
|
||||
BOOST_CHECK_EQUAL(byte_span_to_hex_string_reversed(block_header.Hash().ToBytes()), "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(btck_block)
|
||||
{
|
||||
Block block{hex_string_to_byte_vec(REGTEST_BLOCK_DATA[0])};
|
||||
@@ -819,8 +852,13 @@ void chainman_mainnet_validation_test(TestDirectory& test_directory)
|
||||
// mainnet block 1
|
||||
auto raw_block = hex_string_to_byte_vec("010000006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e61bc6649ffff001d01e362990101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000");
|
||||
Block block{raw_block};
|
||||
BlockHeader header{block.GetHeader()};
|
||||
TransactionView tx{block.GetTransaction(block.CountTransactions() - 1)};
|
||||
BOOST_CHECK_EQUAL(byte_span_to_hex_string_reversed(tx.Txid().ToBytes()), "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098");
|
||||
BOOST_CHECK_EQUAL(header.Version(), 1);
|
||||
BOOST_CHECK_EQUAL(header.Timestamp(), 1231469665);
|
||||
BOOST_CHECK_EQUAL(header.Bits(), 0x1d00ffff);
|
||||
BOOST_CHECK_EQUAL(header.Nonce(), 2573394689);
|
||||
BOOST_CHECK_EQUAL(tx.CountInputs(), 1);
|
||||
Transaction tx2 = tx;
|
||||
BOOST_CHECK_EQUAL(tx2.CountInputs(), 1);
|
||||
@@ -960,6 +998,23 @@ BOOST_AUTO_TEST_CASE(btck_chainman_regtest_tests)
|
||||
auto notifications{std::make_shared<TestKernelNotifications>()};
|
||||
auto context{create_context(notifications, ChainType::REGTEST)};
|
||||
|
||||
{
|
||||
auto chainman{create_chainman(test_directory, false, false, false, false, context)};
|
||||
for (const auto& data : REGTEST_BLOCK_DATA) {
|
||||
Block block{hex_string_to_byte_vec(data)};
|
||||
BlockHeader header = block.GetHeader();
|
||||
BlockValidationState state{};
|
||||
BOOST_CHECK(state.GetBlockValidationResult() == BlockValidationResult::UNSET);
|
||||
BOOST_CHECK(chainman->ProcessBlockHeader(header, state));
|
||||
BOOST_CHECK(state.GetValidationMode() == ValidationMode::VALID);
|
||||
BlockTreeEntry entry{*chainman->GetBlockTreeEntry(header.Hash())};
|
||||
BOOST_CHECK(!chainman->GetChain().Contains(entry));
|
||||
BlockTreeEntry best_entry{chainman->GetBestEntry()};
|
||||
BlockHash hash{entry.GetHash()};
|
||||
BOOST_CHECK(hash == best_entry.GetHeader().Hash());
|
||||
}
|
||||
}
|
||||
|
||||
// Validate 206 regtest blocks in total.
|
||||
// Stop halfway to check that it is possible to continue validating starting
|
||||
// from prior state.
|
||||
|
||||
Reference in New Issue
Block a user