| 865 | } |
| 866 | |
| 867 | void chainman_mainnet_validation_test(TestDirectory& test_directory) |
| 868 | { |
| 869 | auto notifications{std::make_shared<TestKernelNotifications>()}; |
| 870 | auto validation_interface{std::make_shared<TestValidationInterface>()}; |
| 871 | auto context{create_context(notifications, ChainType::MAINNET, validation_interface)}; |
| 872 | auto chainman{create_chainman( |
| 873 | test_directory, /*reindex=*/false, /*wipe_chainstate=*/false, |
| 874 | /*block_tree_db_in_memory=*/false, /*chainstate_db_in_memory=*/false, context)}; |
| 875 | |
| 876 | // mainnet block 1 |
| 877 | auto raw_block = hex_string_to_byte_vec("010000006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e61bc6649ffff001d01e362990101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000"); |
| 878 | Block block{raw_block}; |
| 879 | BlockHeader header{block.GetHeader()}; |
| 880 | TransactionView tx{block.GetTransaction(block.CountTransactions() - 1)}; |
| 881 | BOOST_CHECK_EQUAL(byte_span_to_hex_string_reversed(tx.Txid().ToBytes()), "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098"); |
| 882 | BOOST_CHECK_EQUAL(header.Version(), 1); |
| 883 | BOOST_CHECK_EQUAL(header.Timestamp(), 1231469665); |
| 884 | BOOST_CHECK_EQUAL(header.Bits(), 0x1d00ffff); |
| 885 | BOOST_CHECK_EQUAL(header.Nonce(), 2573394689); |
| 886 | BOOST_CHECK_EQUAL(tx.CountInputs(), 1); |
| 887 | Transaction tx2 = tx; |
| 888 | BOOST_CHECK_EQUAL(tx2.CountInputs(), 1); |
| 889 | for (auto transaction : block.Transactions()) { |
| 890 | BOOST_CHECK_EQUAL(transaction.CountInputs(), 1); |
| 891 | } |
| 892 | auto output_counts = *(block.Transactions() | std::views::transform([](const auto& tx) { |
| 893 | return tx.CountOutputs(); |
| 894 | })).begin(); |
| 895 | BOOST_CHECK_EQUAL(output_counts, 1); |
| 896 | |
| 897 | validation_interface->m_expected_valid_block.emplace(raw_block); |
| 898 | auto ser_block{block.ToBytes()}; |
| 899 | check_equal(ser_block, raw_block); |
| 900 | bool new_block = false; |
| 901 | BOOST_CHECK(chainman->ProcessBlock(block, &new_block)); |
| 902 | BOOST_CHECK(new_block); |
| 903 | |
| 904 | validation_interface->m_expected_valid_block = std::nullopt; |
| 905 | new_block = false; |
| 906 | Block invalid_block{hex_string_to_byte_vec(REGTEST_BLOCK_DATA[REGTEST_BLOCK_DATA.size() - 1])}; |
| 907 | BOOST_CHECK(!chainman->ProcessBlock(invalid_block, &new_block)); |
| 908 | BOOST_CHECK(!new_block); |
| 909 | |
| 910 | auto chain{chainman->GetChain()}; |
| 911 | BOOST_CHECK_EQUAL(chain.Height(), 1); |
| 912 | auto tip{chain.Entries().back()}; |
| 913 | auto read_block{chainman->ReadBlock(tip)}; |
| 914 | BOOST_REQUIRE(read_block); |
| 915 | check_equal(read_block.value().ToBytes(), raw_block); |
| 916 | |
| 917 | // Check that we can read the previous block |
| 918 | BlockTreeEntry tip_2{*tip.GetPrevious()}; |
| 919 | Block read_block_2{*chainman->ReadBlock(tip_2)}; |
| 920 | BOOST_CHECK_EQUAL(chainman->ReadBlockSpentOutputs(tip_2).Count(), 0); |
| 921 | BOOST_CHECK_EQUAL(chainman->ReadBlockSpentOutputs(tip).Count(), 0); |
| 922 | |
| 923 | // It should be an error if we go another block back, since the genesis has no ancestor |
| 924 | BOOST_CHECK(!tip_2.GetPrevious()); |
no test coverage detected