Skip to content

Conversation

@w0xlt
Copy link
Contributor

@w0xlt w0xlt commented Nov 18, 2025

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.

@DrahtBot
Copy link
Contributor

DrahtBot commented Nov 18, 2025

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
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:

  • #33891 (kernel: Expose reusable PrecomputedTransactionData in script validation by joshdoman)
  • #33856 (kernel, validation: Refactor ProcessNewBlockHeaders to return BlockValidationState by yuvicc)
  • #33822 (kernel: Add block header support and validation by yuvicc)
  • #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 typos and grammar issues:

  • "The returned consensus params is not owned and depends on the lifetime of the chain parameters." -> "The returned consensus params are not owned and depend on the lifetime of the chain parameters." [subject "consensus params" is plural so verbs must be plural]

drahtbot_id_5_m

@yuvicc
Copy link
Contributor

yuvicc commented Nov 19, 2025

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.

@purpleKarrot
Copy link
Contributor

Both @w0xlt and @yuvicc, please don't introduce more boolean traps.

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 <[email protected]>
w0xlt and others added 2 commits November 19, 2025 16:17
This change exposes create and destroy functions for
`btck_BlockValidationState` in the C API and splits the C++ wrapper
into an owning `BlockValidationState` (which allocates memory) and a
non-owning `BlockValidationStateView`.

Co-authored-by: yuvicc <[email protected]>
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 <[email protected]>
@DrahtBot
Copy link
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).

Hints

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.

@w0xlt
Copy link
Contributor Author

w0xlt commented Nov 20, 2025

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.

Copy link
Contributor

@yuvicc yuvicc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approach ACK

Thanks for taking my suggestion.

* @return The block validation state, or null on error.
*/
BITCOINKERNEL_API btck_BlockValidationState* BITCOINKERNEL_WARN_UNUSED_RESULT btck_block_validation_state_create();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we also expose _copy API here:

Suggested change
/**
* @brief Copies the block validation state.
*
* @param[in] block_validation_state Non-null.
* @return The copied block validation state.
*/
BITCOINKERNEL_API btck_BlockValidationState* BITCOINKERNEL_WARN_UNUSED_RESULT btck_block_validation_state_copy(
const btck_BlockValidationState* block_validation_state) BITCOINKERNEL_ARG_NONNULL(1);

explicit BlockValidationStateView(const btck_BlockValidationState* ptr) : View{ptr} {}
};

class BlockValidationState : public UniqueHandle<btck_BlockValidationState, btck_block_validation_state_destroy>, public BlockValidationStateApi<BlockValidationState>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And then use Handle instead of UniqueHandle here:

Suggested change
class BlockValidationState : public UniqueHandle<btck_BlockValidationState, btck_block_validation_state_destroy>, public BlockValidationStateApi<BlockValidationState>
class BlockValidationState : public Handle<btck_BlockValidationState, btck_block_validation_state_copy, btck_block_validation_state_destroy>, public BlockValidationStateApi<BlockValidationState>

class BlockValidationState : public UniqueHandle<btck_BlockValidationState, btck_block_validation_state_destroy>, public BlockValidationStateApi<BlockValidationState>
{
public:
BlockValidationState() : UniqueHandle{btck_block_validation_state_create()} {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also here:

Suggested change
BlockValidationState() : UniqueHandle{btck_block_validation_state_create()} {}
explicit BlockValidationState() : Handle{btck_block_validation_state_create()} {}

@DrahtBot
Copy link
Contributor

🐙 This pull request conflicts with the target branch and needs rebase.

@purpleKarrot
Copy link
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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: API Development

Development

Successfully merging this pull request may close these issues.

4 participants