Skip to content

Commit 98112c4

Browse files
committed
add: serialization method for block header in the kernel api. Also, fix CheckHandle to compare the byte content instead of sizes.
1 parent 5b8c204 commit 98112c4

File tree

4 files changed

+37
-2
lines changed

4 files changed

+37
-2
lines changed

src/kernel/bitcoinkernel.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5+
#include "bitcoinkernel.h"
56
#define BITCOINKERNEL_BUILD
67

78
#include <kernel/bitcoinkernel.h>
@@ -1389,6 +1390,13 @@ uint32_t btck_block_header_get_nonce(const btck_BlockHeader* header)
13891390
return btck_BlockHeader::get(header).nNonce;
13901391
}
13911392

1393+
void btck_block_header_to_bytes(const btck_BlockHeader* header, unsigned char output[80])
1394+
{
1395+
DataStream stream{};
1396+
stream << btck_BlockHeader::get(header);
1397+
std::memcpy(output, stream.data(), 80);
1398+
}
1399+
13921400
void btck_block_header_destroy(btck_BlockHeader* header)
13931401
{
13941402
delete header;

src/kernel/bitcoinkernel.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,6 +1768,16 @@ BITCOINKERNEL_API int32_t BITCOINKERNEL_WARN_UNUSED_RESULT btck_block_header_get
17681768
BITCOINKERNEL_API uint32_t BITCOINKERNEL_WARN_UNUSED_RESULT btck_block_header_get_nonce(
17691769
const btck_BlockHeader* header) BITCOINKERNEL_ARG_NONNULL(1);
17701770

1771+
/**
1772+
* @brief Serializes the btck_BlockHeader through the passed in callback to bytes.
1773+
* This is consensus serialization that is also used for the P2P network.
1774+
*
1775+
* @param[in] header Non-null.
1776+
* @param[out] output The serialized block header (80 bytes).
1777+
*/
1778+
BITCOINKERNEL_API void btck_block_header_to_bytes(
1779+
const btck_BlockHeader* header, unsigned char output[80]) BITCOINKERNEL_ARG_NONNULL(1, 2);
1780+
17711781
/**
17721782
* Destroy the btck_BlockHeader.
17731783
*/

src/kernel/bitcoinkernel_wrapper.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#ifndef BITCOIN_KERNEL_BITCOINKERNEL_WRAPPER_H
66
#define BITCOIN_KERNEL_BITCOINKERNEL_WRAPPER_H
77

8+
#include "bitcoinkernel.h"
89
#include <kernel/bitcoinkernel.h>
910

1011
#include <array>
@@ -746,6 +747,13 @@ class BlockHeaderApi
746747
{
747748
return btck_block_header_get_nonce(impl());
748749
}
750+
751+
std::array<std::byte, 80> ToBytes() const
752+
{
753+
std::array<std::byte, 80> header;
754+
btck_block_header_to_bytes(impl(), reinterpret_cast<unsigned char*>(header.data()));
755+
return header;
756+
}
749757
};
750758

751759
class BlockHeaderView : public View<btck_BlockHeader>, public BlockHeaderApi<BlockHeaderView>

src/test/kernel/test_kernel.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ void run_verify_test(
266266

267267
template <typename T>
268268
concept HasToBytes = requires(T t) {
269-
{ t.ToBytes() } -> std::convertible_to<std::vector<std::byte>>;
269+
{ t.ToBytes() } -> std::convertible_to<std::span<const std::byte>>;
270270
};
271271

272272
template <typename T>
@@ -277,7 +277,7 @@ void CheckHandle(T object, T distinct_object)
277277
BOOST_CHECK(object.get() != distinct_object.get());
278278

279279
if constexpr (HasToBytes<T>) {
280-
BOOST_CHECK_NE(object.ToBytes().size(), distinct_object.ToBytes().size());
280+
BOOST_CHECK(object.ToBytes() != distinct_object.ToBytes());
281281
}
282282

283283
// Copy constructor
@@ -682,6 +682,10 @@ BOOST_AUTO_TEST_CASE(btck_block_header_tests)
682682
auto prev_hash = header.PrevHash();
683683
BOOST_CHECK_EQUAL(byte_span_to_hex_string_reversed(prev_hash.ToBytes()), "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
684684

685+
// Test round-trip serialization of block header
686+
auto header_roundtrip{BlockHeader{header.ToBytes()}};
687+
check_equal(header_roundtrip.ToBytes(), mainnet_block_1_header);
688+
685689
auto raw_block = hex_string_to_byte_vec("010000006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e61bc6649ffff001d01e362990101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000");
686690
Block block{raw_block};
687691
BlockHeader block_header{block.GetHeader()};
@@ -690,6 +694,11 @@ BOOST_AUTO_TEST_CASE(btck_block_header_tests)
690694
BOOST_CHECK_EQUAL(block_header.Bits(), 0x1d00ffff);
691695
BOOST_CHECK_EQUAL(block_header.Nonce(), 2573394689);
692696
BOOST_CHECK_EQUAL(byte_span_to_hex_string_reversed(block_header.Hash().ToBytes()), "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048");
697+
698+
// Verify header from block serializes to first 80 bytes of raw block
699+
auto block_header_bytes = block_header.ToBytes();
700+
BOOST_CHECK_EQUAL(block_header_bytes.size(), 80);
701+
check_equal(block_header_bytes, std::span<const std::byte>(raw_block.data(), 80));
693702
}
694703

695704
BOOST_AUTO_TEST_CASE(btck_block)

0 commit comments

Comments
 (0)