Under Active Development

Bitcoin Kernel API

A stable C API for Bitcoin Core's consensus validation engine. Build block explorers, alternative node implementations, research tools, and more — in any language.

6
Official Bindings
C
Core ABI
MIT
License

What Can You Do

The Bitcoinkernel library exposes Bitcoin Core's validation logic through a stable C API. It is a stateful and capable of full block validation, UTXO management, and chain state operations.

⛓️

Block Validation

Validate blocks using the exact same consensus rules as Bitcoin Core. Process blocks against the current chain state with full contextual checks.

📜

Script Verification

Verify transaction scripts including P2SH, SegWit, and Taproot spend paths. For now, the script verification requires no context.

🗄️

Block and Header Data Access

Read block data, undo data, and iterate over the UTXO set. Retrieve block indices by height or hash for chain traversal. Create and validate block header of a block.

🔗

Chain Management

Initialize and manage chain state from a data directory. Supports mainnet, testnet, signet, and regtest chains.

📡

Validation Callbacks

Receive asynchronous notifications about validation events — block connected, block disconnected, error conditions, and progress updates.

🧩

FFI Bindings

The C ABI makes it straightforward to create bindings for any language with C interop. Official bindings exist for C++, Rust, JDK, Python, Go and dotnet.

Architecture Overview

The library follows an opaque-pointer pattern. All kernel objects are created through factory functions and destroyed with corresponding destroy functions. Objects are represented as opaque btck_* pointers — you never access internal fields directly.

The lifecycle for most operations follows this pattern: create a Context (with optional configuration), create a ChainstateManager for chain state operations, then use the manager to validate blocks or read data. When finished, destroy objects in reverse order.

lifecycle.c
// 1. Create context with options
btck_ContextOptions* opts = btck_context_options_create();
btck_context_options_set_chainparams(opts, btck_chain_parameters_create(btck_CHAIN_MAINNET));
btck_Context* ctx = btck_context_create(opts);

// 2. Create chainstate manager
btck_ChainstateManagerOptions* cm_opts = btck_chainstate_manager_options_create(
    ctx, data_dir, data_dir_len, blocks_dir, blocks_dir_len);
btck_ChainstateManager* chainman = btck_chainstate_manager_create(ctx, cm_opts);

// 3. Use the manager — validate blocks, read data, etc.
btck_chainstate_manager_process_block(ctx, chainman, block, &accepted);

// 4. Tear down in reverse order
btck_chainstate_manager_destroy(chainman, ctx);
btck_chainstate_manager_options_destroy(cm_opts);
btck_context_destroy(ctx);
btck_context_options_destroy(opts);
ℹ️
Objects must be destroyed in reverse creation order. The Context must outlive all objects that were created with it.
C

Core C API

The foundational API defined in bitcoinkernel.h. All language bindings ultimately call through this C interface. See the full C API reference for complete documentation.

Context & Configuration

btck_context_createCreate
Create a new kernel context. If options are NULL, defaults are used.
btck_Context* btck_context_create(const btck_ContextOptions* options);
btck_context_options_set_chainparamsConfig
Attach chain parameters (mainnet, testnet, signet, regtest) to the context options.
void btck_context_options_set_chainparams(btck_ContextOptions* opts, btck_ChainParameters* params);
btck_context_destroyDestroy
Destroy the context and free all resources. Call after all dependent objects are destroyed.
void btck_context_destroy(btck_Context* context);

ChainstateManager

btck_chainstate_manager_createCreate
Create a chain state manager bound to a data directory. Loads or initializes the block index and UTXO set.
btck_ChainstateManager* btck_chainstate_manager_create(const btck_Context* ctx, const btck_ChainstateManagerOptions* opts);
btck_chainstate_manager_process_blockValidate
Submit a block for full validation. If accepted, it is connected to the chain.
bool btck_chainstate_manager_process_block(const btck_Context* ctx, btck_ChainstateManager* cm, const btck_Block* block, bool* accepted);

Script Verification

script_verify.c
btck_ScriptPubkey* spk = btck_script_pubkey_create(script_bytes, script_len);
btck_Transaction*  tx  = btck_transaction_create(raw_tx, raw_tx_len);
btck_ScriptVerifyStatus status;

int ok = btck_script_pubkey_verify(
    spk, amount, tx, spent_outputs, n_outputs, input_idx,
    btck_SCRIPT_FLAGS_VERIFY_ALL, &status);

btck_transaction_destroy(tx);
btck_script_pubkey_destroy(spk);

Validation Callbacks

callbacks.c
void on_block_tip(void* user_data, btck_SynchronizationState state,
                   const btck_BlockIndex* index) {
    printf("New tip at height: %d\n", btck_block_index_get_height(index));
}

btck_ValidationInterfaceCallbacks cbs = {
    .block_tip  = on_block_tip,
    .user_data  = my_app_state,
};
btck_context_options_set_validation_interface(opts, cbs);

Language Bindings

Current language bindings documented here in this site.

C++ — RAII wrapper
#include <bitcoinkernel_wrapper.hpp>

btck::ContextOptions opts{};
opts.SetNotifications(std::make_shared<MyNotifications>());

btck::Context   ctx{opts};
btck::ChainMan cm{ctx, {ctx, data_dir, blocks_dir}};
cm.ImportBlocks({});

for (auto entry : cm.GetChain().Entries())
    std::cout << entry.GetHeight() << "\n";
JDK — bitcoinkernel-jdk
try (BitcoinKernel kernel = new BitcoinKernel(
        ChainType.MAINNET,
        Path.of(home, ".bitcoin"),
        Path.of(home, ".bitcoin", "blocks"),
        System.out::println)) {

    ChainstateManager csm = kernel.getChainstateManager();
    csm.ImportBlocks(new String[]{});

    for (BlockTreeEntry e : csm.getChain())
        System.out.println("Height: " + e.getHeight());
}

Error Handling

The C API returns NULL or false on failure. For script verification, a btck_ScriptVerifyStatus output parameter provides detailed error info. Always register a fatal_error callback — if it fires, halt immediately.

Memory Management

Every btck_*_create has a matching btck_*_destroy. Destroy in reverse creation order. Language bindings handle this automatically — Rust uses Drop, JDK uses AutoCloseable, C++ uses RAII handles.

ℹ️
The ChainstateManager requires exclusive access to the data directory. Do not share with a running Bitcoin Core process.