kernel: expose block header Merkle root #36194

pull lucasdbr05 wants to merge 1 commits into bitcoin:master from lucasdbr05:kernel/header-merkle-root-utils changing 4 files +25 −0
  1. lucasdbr05 commented at 4:42 PM on September 8, 2026: contributor

    After participating in a deep-dive on libbitcoinkernel, I noticed that the BlockHeader API did not provide a simple way to access the Merkle root.

    This PR adds a method to the BlockHeader API that retrieves the Merkle root from a block header into a 32-byte output buffer.

  2. DrahtBot added the label Validation on Sep 8, 2026
  3. DrahtBot commented at 4:42 PM on September 8, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/36194.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process.

    Type Reviewers
    ACK stickies-v, sedited, nervana21
    Concept ACK jjamming

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  4. sedited commented at 6:04 PM on September 8, 2026: contributor

    Concept ACK

  5. DrahtBot added the label CI failed on Sep 8, 2026
  6. stickies-v commented at 7:17 PM on September 8, 2026: contributor

    Concept ACK.

    I think this should be a block_header instead of a block attribute, though. I'm also not sure we need a separate btck_BlockMerkleRoot type for this? Would a simple void btck_block_header_get_merkle_root(const btck_BlockHeader* header, unsigned char output[32]) not suffice?

  7. sedited commented at 7:41 PM on September 8, 2026: contributor

    Would a simple void btck_block_header_get_merkle_root(const btck_BlockHeader* header, unsigned char output[32]) not suffice?

    I think I'd prefer that too.

  8. jjamming commented at 3:23 AM on September 9, 2026: none

    Concept ACK

  9. alexanderwiederin commented at 10:19 AM on September 9, 2026: contributor

    Not opposed. Worth flagging generally that we shouldn't grow the API surface without a clear use, though here it's arguably completing an existing set of header accessors.

    Agree with @stickies-v on approach.

  10. nervana21 commented at 8:15 PM on September 10, 2026: contributor

    Concept ACK

  11. in src/kernel/bitcoinkernel.cpp:1321 in 42a6ab2d74
    1316 | +
    1317 | +void btck_block_merkle_root_to_bytes(const btck_BlockMerkleRoot* merkle_root, unsigned char output[32])
    1318 | +{
    1319 | +    std::memcpy(output, btck_BlockMerkleRoot::get(merkle_root).begin(), 32);
    1320 | +}
    1321 | +
    


    nervana21 commented at 5:48 PM on September 11, 2026:

    42a6ab2d74267c1aa57c7d2d14bb9b85a6592966: kernel: Expose block header Merkle root

    void btck_block_merkle_root_to_bytes(const btck_BlockMerkleRoot* merkle_root, unsigned char output[32])
    {
        std::memcpy(output, btck_BlockMerkleRoot::get(merkle_root).begin(), 32);
    }
    
    int btck_block_merkle_root_equals(const btck_BlockMerkleRoot* merkle_root1, const btck_BlockMerkleRoot* merkle_root2)
    {
        return btck_BlockMerkleRoot::get(merkle_root1) == btck_BlockMerkleRoot::get(merkle_root2);
    }
    

    nit: Consider mirroring the order of the above btck_block_hash_ which flips these and instead reads _copy, _to_bytes, _equals, _destroy. The same in bitcoinkernel.h

  12. kernel: expose block header Merkle root
    Add an accessor that writes the block header's Merkle root to a 32-byte output buffer, and expose it through the wrapper as a fixed-size byte array
    16278c2816
  13. in src/test/kernel/test_kernel.cpp:733 in 42a6ab2d74


    nervana21 commented at 5:52 PM on September 11, 2026:

    42a6ab2d74267c1aa57c7d2d14bb9b85a6592966: kernel: Expose block header Merkle root

        // merkle_root sits at offset 36: version(4) + prev_hash(32)
        check_equal(std::span{mainnet_block_1_header}.subspan(36, 32), merkle_root.ToBytes());
    
  14. lucasdbr05 force-pushed on Sep 15, 2026
  15. lucasdbr05 commented at 4:07 AM on September 15, 2026: contributor

    Thanks @stickies-v for the feedback, and @nervana21 for the feedback and code review.

    In the current implementation, I followed the approach suggested by @stickies-v and I removed btck_BlockMerkleRoot and simplified the API so that only btck_block_header_get_merkle_root is needed to access the Merkle root.

    After removing the dedicated btck_BlockMerkleRoot type and the BlockMerkleRoot class, I needed to change the return type of the MerkleRoot() method. The best approach I found was to use std::array<std::byte, 32>.

    IMHO, although the current implementation is simpler, I would prefer MerkleRoot() to return a dedicated Merkle root type rather than directly std::array<std::byte, 32>.

  16. stickies-v approved
  17. stickies-v commented at 11:12 AM on September 15, 2026: contributor

    ACK 16278c28166b0ddff1a96fdb6545850d7c921ea6

    The PR description needs to be updated to reflect the current state before merging.

    I would prefer MerkleRoot() to return a dedicated Merkle root type rather than directly std::array<std::byte, 32>.

    Can you elaborate on why you'd prefer that? I personally can't see any meaningful benefits, only costs.

  18. DrahtBot requested review from nervana21 on Sep 15, 2026
  19. DrahtBot requested review from sedited on Sep 15, 2026
  20. sedited approved
  21. sedited commented at 11:57 AM on September 15, 2026: contributor

    ACK 16278c28166b0ddff1a96fdb6545850d7c921ea6

    Would also prefer this directly going to bytes as done currently. Can you correct the description? I think the last sentence can just be dropped.

  22. DrahtBot removed the label CI failed on Sep 15, 2026
  23. lucasdbr05 commented at 4:56 PM on September 15, 2026: contributor

    Can you elaborate on why you'd prefer that? I personally can't see any meaningful benefits, only costs.

    I agree that introducing it would add some extra cost. My preference was based mainly on consistency with the coding style I observed in the API. That said, I agree with keeping std::array<std::byte, 32> as the direct return type.

  24. nervana21 commented at 9:11 PM on September 15, 2026: contributor

    tACK 16278c28166b0ddff1a96fdb6545850d7c921ea6

  25. sedited merged this on Sep 16, 2026
  26. sedited closed this on Sep 16, 2026


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-09-17 21:51 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me