kernel: Expose CheckTransaction consensus validation function #33796

pull w0xlt wants to merge 1 commits into bitcoin:master from w0xlt:kernel_checktransaction changing 4 files +257 −0
  1. w0xlt commented at 11:59 pm on November 5, 2025: contributor

    This PR exposes the consensus-level CheckTransaction function through the libbitcoinkernel C API and adds a corresponding C++ wrapper.

    Currently, libkernel only provided script-level validation via btck_script_pubkey_verify and ScriptPubkeyApi<>::Verify.

    AFAIK there was no way to perform context-free consensus checks on a transaction’s structure (e.g., coinbase rules, money-range, duplicate inputs).

    This change introduces a new API:

    0int btck_check_transaction(const btck_Transaction* tx, btck_TxValidationState** out_state);
    

    and a C++ convenience wrapper:

    0std::pair<bool, TxValidationState> btck::CheckTransaction(const Transaction& tx);
    

    Both follow the ownership and error-handling conventions established in bitcoinkernel.h.

    The test suite is extended with cases covering:

    • coinbase scriptSig length bounds
    • empty vin / vout detection
    • negative or out-of-range output values
    • duplicate inputs
    • null prevouts in non-coinbase transactions
  2. DrahtBot commented at 11:59 pm on November 5, 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/33796.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK sedited, janb84
    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:

    • #33908 (kernel: add context‑free block validation API (btck_check_block_context_free) with POW/Merkle flags 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.

  3. in src/kernel/bitcoinkernel.h:367 in a262282abe outdated
    362+#define btck_TxValidationResult_WITNESS_STRIPPED    ((btck_TxValidationResult)(7))
    363+#define btck_TxValidationResult_CONFLICT            ((btck_TxValidationResult)(8))
    364+#define btck_TxValidationResult_MEMPOOL_POLICY      ((btck_TxValidationResult)(9))
    365+#define btck_TxValidationResult_NO_MEMPOOL          ((btck_TxValidationResult)(10))
    366+#define btck_TxValidationResult_RECONSIDERABLE      ((btck_TxValidationResult)(11))
    367+#define btck_TxValidationResult_UNKNOWN             ((btck_TxValidationResult)(12))
    


    l0rinc commented at 9:04 am on November 6, 2025:
    shouldn’t this be bigger than 12 (or could maybe be 0) so that new values can be added in the future?

    w0xlt commented at 1:42 am on February 10, 2026:
    Done. Thanks.
  4. sedited commented at 11:01 am on November 6, 2025: contributor

    Concept ACK on adding more checks. I am not sure how useful this check by itself is though, since it lacks finality, inputs, sigops, amount + fee, and script checks. Are you planning on adding these too and if not, what is the purpose served from surfacing the context-free checks, but not the others?

    I think the unit tests are going a bit too far. We don’t have to verify again that our validation logic works internally and should instead just verify that the function’s contract is correct. If you want to check that the mapping for each of the result enums is correct maybe pass in a few hard-coded transactions instead? We do the same in our unit tests too so maybe just reuse a few of the vectors from test/data/tx_invalid.json?

  5. w0xlt commented at 6:44 pm on November 6, 2025: contributor

    I am not sure how useful this check by itself is … what is the purpose served from surfacing the context‑free checks, but not the others?

    The new API intentionally exposes only the context‑free consensus predicate (consensus/tx_check::CheckTransaction) so callers can fail fast on malformed transactions without needing a kernel context, UTXO set, or policy knobs.

    This gives library users (indexers, gateways, alternative mempool layers, etc.) a cheap pre‑filter to catch structural rule violations like empty vin/vout, out‑of‑range amounts, coinbase scriptSig length bounds, duplicate inputs, or null prevouts in non‑coinbase txs—before doing any stateful or expensive work.

    Script checks are already available via btck_script_pubkey_verify in this API; inputs/fees/sigops/finality all need UTXO and/or chain context and are out of scope for a context‑free entry point.

    think the unit tests are going a bit too far … instead just verify that the function’s contract is correct.

    Agreed. This can be simplified.

  6. ?
    project_v2_item_status_changed sedited
  7. ?
    added_to_project_v2 sedited
  8. fanquake renamed this:
    [kernel] Expose `CheckTransaction` consensus validation function
    kernel: Expose `CheckTransaction` consensus validation function
    on Nov 7, 2025
  9. DrahtBot added the label Validation on Nov 7, 2025
  10. in src/kernel/bitcoinkernel.h:603 in a262282abe
    598+ */
    599+///@{
    600+/**
    601+ * @brief Run consensus/tx_check::CheckTransaction on a tx and return the filled state.
    602+ * @return 1 if valid, 0 if invalid.
    603+ */
    


    yuvicc commented at 6:27 am on November 8, 2025:
     0/**
     1   * [@brief](/bitcoin-bitcoin/contributor/brief/) Run consensus/tx_check::CheckTransaction on a transaction.
     2   * 
     3   * Performs context-free consensus validation on a transaction without
     4   * requiring blockchain state.
     5   * 
     6   * [@param](/bitcoin-bitcoin/contributor/param/)[in] tx The transaction to validate
     7   * [@param](/bitcoin-bitcoin/contributor/param/)[out] out_state Pointer to receive the validation state (always set,
     8   *                       caller must destroy with btck_tx_validation_state_destroy)
     9   * [@return](/bitcoin-bitcoin/contributor/return/) 1 if valid, 0 if invalid
    10   */
    

    w0xlt commented at 1:42 am on February 10, 2026:
    Done. Thanks.
  11. yuvicc commented at 6:31 am on November 8, 2025: contributor

    Approach ACK

    Great addition exposing CheckTransaction to the kernel API. This will be useful to external users needing context-free transaction validation.

  12. in src/test/kernel/test_kernel.cpp:1075 in a262282abe outdated
    1068@@ -973,3 +1069,133 @@ BOOST_AUTO_TEST_CASE(btck_chainman_regtest_tests)
    1069     std::filesystem::remove_all(test_directory.m_directory / "blocks" / "rev00000.dat");
    1070     BOOST_CHECK_THROW(chainman->ReadBlockSpentOutputs(tip), std::runtime_error);
    1071 }
    1072+
    1073+// -----------------------------------------------------------------------------
    1074+// CheckTransaction tests
    1075+// -----------------------------------------------------------------------------
    


    janb84 commented at 10:20 am on November 17, 2025:

    NIT: (non-blocking) maybe add a note why only the 2 (possible) states are tested ? For a non-bitcoin-core dev this is maybe a bit unclear given all the TxValidationResults and the Check_Transaction that these are the 2 outcomes. It’s for me not logical to add this as a comment on the function because it returns a pointer to the results.

    0// -----------------------------------------------------------------------------
    1// Note: CheckTransaction performs only basic consensus checks and returns either:
    2//   - VALID (ValidationMode::VALID, TxValidationResult::UNSET) for valid transactions
    3//   - INVALID (ValidationMode::INVALID, TxValidationResult::CONSENSUS) for violations
    4//
    5// Other TxValidationResult values are set by higher-level validation functions and
    6// not exposed through btck_check_transaction.
    7// -----------------------------------------------------------------------------
    

    w0xlt commented at 1:43 am on February 10, 2026:
    Done. Thanks.
  13. janb84 commented at 10:35 am on November 17, 2025: contributor

    Concept ACK a262282abefc0a16be329ab2179c193b4b32cc5b

    PR extends bitcoin kernel library with the checkTransaction consensus validation function.

    Added a suggestion NIT (non-blocking) and I agree with the NIT from yuvicc

    Steps taken:

  14. DrahtBot added the label Needs rebase on Dec 27, 2025
  15. w0xlt force-pushed on Feb 10, 2026
  16. w0xlt commented at 1:44 am on February 10, 2026: contributor
    @sedited tests simplified. Vectors from test/data/tx_invalid.json are now being reused.
  17. DrahtBot removed the label Needs rebase on Feb 10, 2026
  18. sedited requested review from yuvicc on Mar 5, 2026
  19. sedited requested review from janb84 on Mar 5, 2026
  20. in src/kernel/bitcoinkernel.cpp:12 in 83b211dc84 outdated
     8@@ -9,6 +9,7 @@
     9 #include <chain.h>
    10 #include <coins.h>
    11 #include <consensus/validation.h>
    12+#include <consensus/tx_check.h>
    


    sedited commented at 9:03 pm on March 5, 2026:
    Nit (ordering): This should be one line higher.

    w0xlt commented at 11:04 pm on March 5, 2026:
    Done. Thanks.
  21. in src/kernel/bitcoinkernel.cpp:1403 in 83b211dc84
    1395@@ -1394,3 +1396,46 @@ void btck_block_header_destroy(btck_BlockHeader* header)
    1396 {
    1397     delete header;
    1398 }
    1399+
    1400+btck_ValidationMode btck_tx_validation_state_get_validation_mode(const btck_TxValidationState* state_)
    1401+{
    1402+    const auto& state = btck_TxValidationState::get(state_);
    1403+    if (state.IsValid())   return btck_ValidationMode_VALID;
    


    sedited commented at 9:04 pm on March 5, 2026:
    Nit (formatting): Aligning this with the line below looks a bit weird to me. I’d just apply a single space.

    w0xlt commented at 11:04 pm on March 5, 2026:
    Done. Thanks.
  22. in src/kernel/bitcoinkernel.h:526 in 83b211dc84 outdated
    521+        const btck_TxValidationState* state) BITCOINKERNEL_ARG_NONNULL(1);
    522+
    523+BITCOINKERNEL_API btck_TxValidationResult btck_tx_validation_state_get_tx_validation_result(
    524+    const btck_TxValidationState* state) BITCOINKERNEL_ARG_NONNULL(1);
    525+
    526+BITCOINKERNEL_API void btck_tx_validation_state_destroy(btck_TxValidationState* state);
    


    sedited commented at 9:08 pm on March 5, 2026:
    I think these should get doc strings.

    w0xlt commented at 11:04 pm on March 5, 2026:
    Done. Thanks.
  23. w0xlt force-pushed on Mar 5, 2026
  24. w0xlt force-pushed on Mar 6, 2026
  25. kernel: Expose CheckTransaction consensus function
    Add btck_check_transaction() to the libbitcoinkernel C API, exposing
    context-free transaction consensus validation (consensus/tx_check.h).
    
    Introduces btck_TxValidationState with introspection and lifecycle
    functions, and btck_TxValidationResult for granular failure reasons.
    
    Includes C++ wrapper and test coverage for all CheckTransaction
    failure paths using test vectors from tx_valid.json / tx_invalid.json.
    3e10c18cee
  26. w0xlt force-pushed on Mar 6, 2026
  27. DrahtBot added the label CI failed on Mar 6, 2026
  28. DrahtBot removed the label CI failed on Mar 6, 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-11 06:13 UTC

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