From 5494f48380c4217df97eb94139fe48bfe8dd3569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C5=91rinc?= Date: Sat, 17 Jan 2026 23:55:18 +0100 Subject: [PATCH 1/7] test: lock in mainnet genesis `scriptSig` bytes This hard codes the expected coinbase `scriptSig` hex. This protects consensus-critical genesis construction against refactors. --- src/test/pow_tests.cpp | 9 +++++++++ src/test/util_tests.cpp | 45 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 8de76ff21f9d..253b7009518a 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -198,6 +199,14 @@ BOOST_AUTO_TEST_CASE(ChainParams_TESTNET_sanity) sanity_check_chainparams(*m_node.args, ChainType::TESTNET); } +BOOST_AUTO_TEST_CASE(ChainParams_MAIN_genesis_scriptsig) +{ + const auto chainParams = CreateChainParams(*m_node.args, ChainType::MAIN); + const auto& genesis = chainParams->GenesisBlock(); + const auto& script_sig = genesis.vtx[0]->vin[0].scriptSig; + BOOST_CHECK_EQUAL(HexStr(script_sig), "04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73"); +} + BOOST_AUTO_TEST_CASE(ChainParams_TESTNET4_sanity) { sanity_check_chainparams(*m_node.args, ChainType::TESTNET4); diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 13821db4b95b..0a8b065cd2fc 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -278,6 +278,51 @@ BOOST_AUTO_TEST_CASE(span_write_bytes) BOOST_CHECK_EQUAL(mut_arr.at(1), 0x11); } +BOOST_AUTO_TEST_CASE(span_make_byte_span) +{ + constexpr std::array input{0x01, 0x02, 0x03}; + const auto expected = std::as_bytes(std::span{input}); + const auto actual = MakeByteSpan(input); + BOOST_CHECK_EQUAL_COLLECTIONS(actual.begin(), actual.end(), expected.begin(), expected.end()); +} + +BOOST_AUTO_TEST_CASE(span_make_writable_byte_span) +{ + std::array input{0x0a, 0x0b}; + const auto expected = std::as_writable_bytes(std::span{input}); + const auto actual = MakeWritableByteSpan(input); + BOOST_CHECK_EQUAL(actual.data(), expected.data()); + BOOST_CHECK_EQUAL(actual.size(), expected.size()); +} + +BOOST_AUTO_TEST_CASE(span_make_uchar_span) +{ + std::array bytes{std::byte{0x12}, std::byte{0x34}}; + const auto span = MakeUCharSpan(bytes); + BOOST_CHECK_EQUAL(span.size(), bytes.size()); + BOOST_CHECK_EQUAL(span[0], 0x12); + BOOST_CHECK_EQUAL(span[1], 0x34); +} + +BOOST_AUTO_TEST_CASE(span_uchar_cast) +{ + std::array bytes{std::byte{0xab}, std::byte{0xcd}}; + const auto ptr = UCharCast(bytes.data()); + BOOST_CHECK_EQUAL(ptr[0], 0xab); + BOOST_CHECK_EQUAL(ptr[1], 0xcd); +} + +BOOST_AUTO_TEST_CASE(span_pop_back) +{ + std::array values{1, 2, 3}; + std::span span{values}; + const int last = SpanPopBack(span); + BOOST_CHECK_EQUAL(last, 3); + BOOST_CHECK_EQUAL(span.size(), 2); + BOOST_CHECK_EQUAL(span[0], 1); + BOOST_CHECK_EQUAL(span[1], 2); +} + BOOST_AUTO_TEST_CASE(util_Join) { // Normal version From 68c202e29b01f46247bd814b114d44755a2b4756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C5=91rinc?= Date: Sun, 18 Jan 2026 00:03:34 +0100 Subject: [PATCH 2/7] kernel: use `MakeUCharSpan` for genesis timestamp bytes This is equivalent to the prior `std::vector` built from `pszTimestamp` and `strlen`. It preserves the exact byte sequence while avoiding raw pointer casts. --- src/kernel/chainparams.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp index 300df95fb8ed..dc74c53a0947 100644 --- a/src/kernel/chainparams.cpp +++ b/src/kernel/chainparams.cpp @@ -16,6 +16,7 @@ #include #include