kernel: add context‑free block validation API (btck_check_block_context_free) with POW/Merkle flags #33908

pull w0xlt wants to merge 2 commits into bitcoin:master from w0xlt:kerne_checkblock changing 4 files +120 −2
  1. w0xlt commented at 11:37 pm on November 18, 2025: contributor

    This PR exposes Bitcoin Core’s context‑free block checks to library users via a new C API entry point, btck_check_block_context_free.

    Callers can validate a block’s structure (size/weight, coinbase rules, per‑tx context‑free checks) and optionally re‑run Proof‑of‑Work and Merkle‑root verification without touching chainstate, the block index, or the UTXO set.

    Rationale Clients embedding the kernel need a pure block sanity check without requiring node state or disk writes (candidate block validation, for example). This API offers that surface in a single call, with optional PoW/Merkle toggles to avoid redundant work when the header has already been validated or when Merkle verification is deferred.

  2. DrahtBot added the label Validation on Nov 18, 2025
  3. DrahtBot commented at 11:37 pm on November 18, 2025: contributor

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

    Code Coverage & Benchmarks

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

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK sedited
    Approach ACK yuvicc

    If your review is incorrectly listed, please copy-paste <!–meta-tag:bot-skip–> into the comment that the bot should ignore.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #33796 (kernel: Expose CheckTransaction consensus validation function by w0xlt)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    LLM Linter (✨ experimental)

    Possible places where comparison-specific test macros should replace generic comparisons:

    • src/test/kernel/test_kernel.cpp: + BOOST_CHECK_THROW(Block{broken_block_data}, std::runtime_error); -> Use BOOST_CHECK_EXCEPTION to assert the exception type and verify the failure reason/message, e.g. BOOST_CHECK_EXCEPTION(Block{broken_block_data}, std::runtime_error, HasReason(“the exact failure message”))

    2026-02-18 18:56:02

  4. w0xlt force-pushed on Nov 18, 2025
  5. DrahtBot added the label CI failed on Nov 18, 2025
  6. DrahtBot removed the label CI failed on Nov 19, 2025
  7. yuvicc commented at 10:22 am on November 19, 2025: contributor

    Concept ACK, Approach NACK from my side.

    Currently, btck_check_block_context_free requires a full btck_Context*, but it only usescontext->m_chainparams->GetConsensus(). Library user will need to maintain a full context object just to perform context-free block validation checks which I think is not a good idea. Also, the function doesn’t clearly communicate that only consensus params are needed and not full context. I think a better approach could be to expose opaque struct for consensus params (btck_ConsensusParams). This makes the API lighter-weight and more clearly expresses the actual behaviour. I’ve been working on a similar implementation to expose context free checkblock and made a patch. The wrapper and test_kernel also needs to be updated.

    The use of bitflags for extensibility look good imo.

  8. purpleKarrot commented at 11:10 am on November 19, 2025: contributor
    Both @w0xlt and @yuvicc, please don’t introduce more boolean traps.
  9. w0xlt force-pushed on Nov 20, 2025
  10. w0xlt force-pushed on Nov 20, 2025
  11. DrahtBot added the label CI failed on Nov 20, 2025
  12. DrahtBot commented at 0:18 am on November 20, 2025: contributor

    🚧 At least one of the CI tasks failed. Task ASan + LSan + UBSan + integer: https://github.com/bitcoin/bitcoin/actions/runs/19520546781/job/55882840198 LLM reason (✨ experimental): C++ compile error: overridden BlockChecked signature mismatches base (hides virtual with BlockValidationState vs BlockValidationStateView).

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

  13. w0xlt commented at 0:23 am on November 20, 2025: contributor

    Thanks for the review @yuvicc and @purpleKarrot .

    Great idea exposing the chain parameter class. I’ve updated the PR to follow this approach and split it into three commits for better readability and easier reviewing (and added @yuvicc as co-author). I also had to update BlockValidationState so the reference parameter works correctly. I kept btck_BlockCheckFlags to avoid unclear boolean parameters.

  14. DrahtBot removed the label CI failed on Nov 20, 2025
  15. in src/kernel/bitcoinkernel.h:1200 in c5071d173d outdated
    1191@@ -1192,6 +1192,17 @@ BITCOINKERNEL_API int btck_block_to_bytes(
    1192  */
    1193 BITCOINKERNEL_API void btck_block_destroy(btck_Block* block);
    1194 
    1195+/**
    1196+ * @brief Create a new block validation state.
    1197+ * @return The block validation state, or null on error.
    1198+ */
    1199+BITCOINKERNEL_API btck_BlockValidationState* BITCOINKERNEL_WARN_UNUSED_RESULT btck_block_validation_state_create();
    1200+
    


    yuvicc commented at 9:24 am on November 20, 2025:

    I think we also expose _copy API here:

    0
    1/**
    2 * [@brief](/bitcoin-bitcoin/contributor/brief/) Copies the block validation state.
    3 *
    4 * [@param](/bitcoin-bitcoin/contributor/param/)[in] block_validation_state Non-null.
    5 * [@return](/bitcoin-bitcoin/contributor/return/)                           The copied block validation state.
    6 */
    7BITCOINKERNEL_API btck_BlockValidationState* BITCOINKERNEL_WARN_UNUSED_RESULT btck_block_validation_state_copy(
    8    const btck_BlockValidationState* block_validation_state) BITCOINKERNEL_ARG_NONNULL(1);
    
  16. in src/kernel/bitcoinkernel_wrapper.h:732 in c5071d173d outdated
    727+{
    728+public:
    729+    explicit BlockValidationStateView(const btck_BlockValidationState* ptr) : View{ptr} {}
    730+};
    731+
    732+class BlockValidationState : public UniqueHandle<btck_BlockValidationState, btck_block_validation_state_destroy>, public BlockValidationStateApi<BlockValidationState>
    


    yuvicc commented at 9:26 am on November 20, 2025:

    And then use Handle instead of UniqueHandle here:

    0class BlockValidationState : public Handle<btck_BlockValidationState, btck_block_validation_state_copy, btck_block_validation_state_destroy>, public BlockValidationStateApi<BlockValidationState>
    

    w0xlt commented at 1:42 am on February 10, 2026:
    Done. Thanks.
  17. in src/kernel/bitcoinkernel_wrapper.h:735 in c5071d173d outdated
    730+};
    731+
    732+class BlockValidationState : public UniqueHandle<btck_BlockValidationState, btck_block_validation_state_destroy>, public BlockValidationStateApi<BlockValidationState>
    733+{
    734+public:
    735+    BlockValidationState() : UniqueHandle{btck_block_validation_state_create()} {}
    


    yuvicc commented at 9:27 am on November 20, 2025:

    Also here:

    0explicit BlockValidationState() : Handle{btck_block_validation_state_create()} {}
    

    w0xlt commented at 1:42 am on February 10, 2026:
    Done. Thanks.
  18. yuvicc commented at 9:29 am on November 20, 2025: contributor

    Approach ACK

    Thanks for taking my suggestion.

  19. ?
    project_v2_item_status_changed sedited
  20. ?
    added_to_project_v2 sedited
  21. DrahtBot added the label Needs rebase on Dec 27, 2025
  22. purpleKarrot commented at 9:28 pm on December 29, 2025: contributor
    I think the most important question is this: Is there a valid use case for an invalid block? Could “valid” be an invariant of block, so that a block is guaranteed to be valid by construction?
  23. in src/kernel/bitcoinkernel.cpp:1084 in 824b5c4756
    1076@@ -1077,6 +1077,18 @@ btck_Block* btck_block_copy(const btck_Block* block)
    1077     return btck_Block::copy(block);
    1078 }
    1079 
    1080+int btck_block_check(const btck_Block* block, const btck_ConsensusParams* consensus_params, btck_BlockCheckFlags flags, btck_BlockValidationState* validation_state)
    1081+{
    1082+    auto& state = btck_BlockValidationState::get(validation_state);
    1083+
    1084+    const bool check_pow_again = (flags & btck_BlockCheckFlags_POW) != 0;
    


    sedited commented at 1:11 pm on January 22, 2026:
    Nit: Why call this _again?

    w0xlt commented at 1:42 am on February 10, 2026:
    Done. Thanks.
  24. in src/kernel/bitcoinkernel.h:1148 in 824b5c4756
    1142@@ -1143,6 +1143,33 @@ BITCOINKERNEL_API btck_Block* BITCOINKERNEL_WARN_UNUSED_RESULT btck_block_create
    1143 BITCOINKERNEL_API btck_Block* BITCOINKERNEL_WARN_UNUSED_RESULT btck_block_copy(
    1144     const btck_Block* block) BITCOINKERNEL_ARG_NONNULL(1);
    1145 
    1146+/** Bitflags to control context-free block checks (optional). */
    1147+typedef uint32_t btck_BlockCheckFlags;
    1148+#define btck_BlockCheckFlags_NONE   ((btck_BlockCheckFlags)0)
    


    sedited commented at 1:11 pm on January 22, 2026:
    The NONE name is misleading here, since we do still validate stuff even if it is not defined. Maybe call it BASE?

    w0xlt commented at 1:42 am on February 10, 2026:
    Done. Thanks.
  25. in src/kernel/bitcoinkernel_wrapper.h:714 in c5071d173d outdated
    709+    auto impl() const
    710+    {
    711+        return static_cast<const Derived*>(this)->get();
    712+    }
    713+    friend Derived;
    714+public:
    


    sedited commented at 1:14 pm on January 22, 2026:
    Nit (clang-format): Add an empty line before public:.

    w0xlt commented at 1:42 am on February 10, 2026:
    Done. Thanks.
  26. in src/kernel/bitcoinkernel.h:1158 in 824b5c4756
    1153+/**
    1154+ * @brief Perform context-free validation checks on a block.
    1155+ *
    1156+ * Runs full context-free block checks (header + body) using the supplied
    1157+ * consensus parameters. The proof-of-work and merkle-root checks can be
    1158+ * toggled via @p flags.
    


    sedited commented at 1:28 pm on January 22, 2026:
    Can you add Note that this does not include any transaction script, timestamps, order, or other checks that may require more context.?

    w0xlt commented at 1:42 am on February 10, 2026:
    Done. Thanks.
  27. sedited commented at 1:35 pm on January 22, 2026: contributor
    Concept ACK
  28. sedited commented at 1:40 pm on January 22, 2026: contributor

    Could “valid” be an invariant of block, so that a block is guaranteed to be valid by construction?

    That would be my preferred approach too, but I think that will be a much more ambitious undertaking. I wonder though if there is a good reason against just immediately running these checks on deserializing a raw block.

  29. yuvicc commented at 1:06 pm on February 9, 2026: contributor

    I wonder though if there is a good reason against just immediately running these checks on deserializing a raw block.

    Adding checks during deserialization would add unnecessary overhead. Also, block validation requires ConsensusParams, so we’d need to pass them into the API just to deserialize. Not sure if we want to go that way.

  30. yuvicc commented at 1:10 pm on February 9, 2026: contributor
    friendly ping @w0xlt If you don’t have the time to carry the patch happy to take this over, just let me know.
  31. w0xlt force-pushed on Feb 9, 2026
  32. w0xlt force-pushed on Feb 9, 2026
  33. DrahtBot added the label CI failed on Feb 9, 2026
  34. DrahtBot commented at 11:01 pm on February 9, 2026: contributor

    🚧 At least one of the CI tasks failed. Task iwyu: https://github.com/bitcoin/bitcoin/actions/runs/21844026286/job/63035482221 LLM reason (✨ experimental): CI failure caused by IWYU (include-what-you-use) detecting issues in bitcoinkernel.cpp and returning non-zero exit status.

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

  35. DrahtBot removed the label Needs rebase on Feb 10, 2026
  36. DrahtBot removed the label CI failed on Feb 10, 2026
  37. w0xlt commented at 1:41 am on February 10, 2026: contributor
    Thanks for the ping @yuvicc I rebased and addressed all the comments here and in #33796 as well.
  38. in src/kernel/bitcoinkernel.h:870 in d739bb5ae6 outdated
    865+ * @param[in] chain_parameters  Non-null.
    866+ * @return                      The consensus parameters.
    867+ */
    868+BITCOINKERNEL_API const btck_ConsensusParams* BITCOINKERNEL_WARN_UNUSED_RESULT btck_chain_parameters_get_consensus_params(
    869+    const btck_ChainParameters* chain_parameters) BITCOINKERNEL_ARG_NONNULL(1);
    870+
    


    yuvicc commented at 6:33 am on February 16, 2026:

    doc naming convention: always use struct names instead of natural names.

     0diff --git a/src/kernel/bitcoinkernel.h b/src/kernel/bitcoinkernel.h
     1index 9bd698fc54..7912e38ef0 100644
     2--- a/src/kernel/bitcoinkernel.h
     3+++ b/src/kernel/bitcoinkernel.h
     4@@ -859,11 +859,11 @@ BITCOINKERNEL_API btck_ChainParameters* BITCOINKERNEL_WARN_UNUSED_RESULT btck_ch
     5     const btck_ChainParameters* chain_parameters) BITCOINKERNEL_ARG_NONNULL(1);
     6
     7 /**
     8- * [@brief](/bitcoin-bitcoin/contributor/brief/) Get consensus params from chain parameters. The returned consensus params
     9+ * [@brief](/bitcoin-bitcoin/contributor/brief/) Get btck_ConsensusParams from chain parameters. The returned consensus params
    10  * are not owned and depend on the lifetime of the chain parameters.
    11  *
    12  * [@param](/bitcoin-bitcoin/contributor/param/)[in] chain_parameters  Non-null.
    13- * [@return](/bitcoin-bitcoin/contributor/return/)                      The consensus parameters.
    14+ * [@return](/bitcoin-bitcoin/contributor/return/)                      The btck_ConsensensusParams.
    15  */
    16 BITCOINKERNEL_API const btck_ConsensusParams* BITCOINKERNEL_WARN_UNUSED_RESULT btck_chain_parameters_get_consensus_params(
    17     const btck_ChainParameters* chain_parameters) BITCOINKERNEL_ARG_NONNULL(1);
    

    w0xlt commented at 6:56 pm on February 18, 2026:
    Done. Thanks.
  39. in src/kernel/bitcoinkernel.h:1262 in 9ffc39cf39
    1257+#define btck_BlockCheckFlags_POW    ((btck_BlockCheckFlags)(1U << 0))  /* run CheckProofOfWork via CheckBlockHeader */
    1258+#define btck_BlockCheckFlags_MERKLE ((btck_BlockCheckFlags)(1U << 1))  /* verify merkle root (and mutation detection) */
    1259+#define btck_BlockCheckFlags_ALL    ((btck_BlockCheckFlags)(btck_BlockCheckFlags_POW | btck_BlockCheckFlags_MERKLE))
    1260+
    1261+/**
    1262+ * @brief Perform context-free validation checks on a block.
    


    yuvicc commented at 6:38 am on February 16, 2026:
    Here as well. See comment.

    w0xlt commented at 6:56 pm on February 18, 2026:
    Done. Thanks.
  40. yuvicc commented at 6:54 am on February 16, 2026: contributor
    Left some nits.
  41. kernel: Expose consensus parameters (`btck_ConsensusParams`)
    Library users currently need to maintain a full context object to perform
    context-free block validation. Exposing an opaque `btck_ConsensusParams`
    struct allows callers to supply only the required consensus parameters,
    resulting in a lighter-weight API and a clearer expression of the actual
    validation behavior.
    
    Co-authored-by: yuvicc <yuvichh01@gmail.com>
    261d80b2d5
  42. kernel: Expose context-free block validation
    This introduces a context-free validation entry point for full blocks in
    the kernel C and C++ APIs.
    
    * Add `btck_block_check`, a C function that wraps `CheckBlock` and runs
    header and body checks for a `btck_Block` using `btck_ConsensusParams`.
    Callers provide a `btck_BlockValidationState` to receive the result
    and supply a `btck_BlockCheckFlags` bitmask to control POW and
    merkle-root verification.
    
    * Add `btck_BlockCheckFlags` in the C API, plus the corresponding
    `BlockCheckFlags` scoped enum in the C++ wrapper, including a
    `*_ALL` convenience value.
    
    * Add `Block::Check()` to the C++ wrapper to mirror the new C function
    and return a bool while filling a `BlockValidationState`.
    
    * Add a test `(btck_check_block_context_free)` that verifies a known
    valid mainnet block passes with `BlockCheckFlags::ALL` and that
    truncated block data fails deserialization.
    
    Co-authored-by: yuvicc <yuvichh01@gmail.com>
    c582d2e811
  43. w0xlt force-pushed on Feb 18, 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-03-03 03:13 UTC

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