Bitcoin Kernel
C header for interacting with the Bitcoin Kernel library.
Loading...
Searching...
No Matches
Examples

Though these examples are provided, users from other programming languages should use wrappers for their respective languages. These will often provide simplified and more ergonomic interfaces, with less manual memory management.

The kernel library supports three fundamental features:

  1. "Context-free" validation
  2. Full validation
  3. Bitcoin Core data retrieval

Full validation applies the complete validation rules that Bitcoin Core uses to validate transactions and blocks. Currently, this includes block processing. These functions read and write from and to disk.

The library also exposes a bunch of utilities for reading data. This includes iterating over the indexed blocks and reading them from disk.

"Context-free" validation

This describes validation functions for which the user of the library is not required to explicitly instantiate a kernel_Context. These functions can validate data structures only with a subset of the full Bitcoin Core rules. They do not read or write data from or to disk. Currently, this includes script validation.

The user does not need to setup callbacks or other more stateful infrastructure to use these functions.

The following example validates a spend of a taproot output:

#include "bitcoinkernel.h"
#include "stddef.h"
int main() {
// Taproot transaction 33e794d097969002ee05d336686fc03c9e15a597c1b9827669460fac98799036
static const unsigned char tx[] = {
0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xd1, 0xf1, 0xc1, 0xf8, 0xcd, 0xf6, 0x75, 0x91, 0x67,
0xb9, 0x0f, 0x52, 0xc9, 0xad, 0x35, 0x8a, 0x36, 0x9f, 0x95, 0x28, 0x4e, 0x84, 0x1d, 0x7a, 0x25,
0x36, 0xce, 0xf3, 0x1c, 0x05, 0x49, 0x58, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xff, 0xff,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x6a, 0x2f, 0x49, 0x20, 0x6c, 0x69,
0x6b, 0x65, 0x20, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x20, 0x73, 0x69, 0x67, 0x73, 0x20,
0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x65,
0x2e, 0x20, 0x40, 0x62, 0x69, 0x74, 0x62, 0x75, 0x67, 0x34, 0x32, 0x9e, 0x06, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x22, 0x51, 0x20, 0xa3, 0x7c, 0x39, 0x03, 0xc8, 0xd0, 0xdb, 0x65, 0x12, 0xe2,
0xb4, 0x0b, 0x0d, 0xff, 0xa0, 0x5e, 0x5a, 0x3a, 0xb7, 0x36, 0x03, 0xce, 0x8c, 0x9c, 0x4b, 0x77,
0x71, 0xe5, 0x41, 0x23, 0x28, 0xf9, 0x01, 0x40, 0xa6, 0x0c, 0x38, 0x3f, 0x71, 0xba, 0xc0, 0xec,
0x91, 0x9b, 0x1d, 0x7d, 0xbc, 0x3e, 0xb7, 0x2d, 0xd5, 0x6e, 0x7a, 0xa9, 0x95, 0x83, 0x61, 0x55,
0x64, 0xf9, 0xf9, 0x9b, 0x8a, 0xe4, 0xe8, 0x37, 0xb7, 0x58, 0x77, 0x3a, 0x5b, 0x2e, 0x4c, 0x51,
0x34, 0x88, 0x54, 0xc8, 0x38, 0x9f, 0x00, 0x8e, 0x05, 0x02, 0x9d, 0xb7, 0xf4, 0x64, 0xa5, 0xff,
0x2e, 0x01, 0xd5, 0xe6, 0xe6, 0x26, 0x17, 0x4a, 0xff, 0xd3, 0x0a, 0x00
};
// Spends script pubkey 5120339ce7e165e67d93adb3fef88a6d4beed33f01fa876f05a225242b82a631abc0
static const unsigned char script[] = {
0x51, 0x20, 0x33, 0x9c, 0xe7, 0xe1, 0x65, 0xe6, 0x7d, 0x93, 0xad, 0xb3, 0xfe, 0xf8, 0x8a, 0x6d,
0x4b, 0xee, 0xd3, 0x3f, 0x01, 0xfa, 0x87, 0x6f, 0x05, 0xa2, 0x25, 0x24, 0x2b, 0x82, 0xa6, 0x31,
0xab, 0xc0
};
kernel_Transaction* transaction = kernel_transaction_create(tx, sizeof(tx));
if (transaction == NULL) return 1;
kernel_ScriptPubkey* script_pubkey = kernel_script_pubkey_create(script, sizeof(script));
if (script_pubkey == NULL) return 1;
int64_t amount = 88480;
const kernel_TransactionOutput* output_ = output;
bool result = kernel_verify_script(
/*script_pubkey=*/ script_pubkey,
/*amount=*/ amount,
/*tx_to=*/ transaction,
/*spent_outputs=*/ &output_,
/*spent_outputs_len=*/1,
/*input_index=*/ 0,
/*status*/ &status);
return !(result && status == kernel_SCRIPT_VERIFY_OK);
}
void kernel_transaction_output_destroy(kernel_TransactionOutput *transaction_output)
@ kernel_SCRIPT_FLAGS_VERIFY_ALL
Definition bitcoinkernel.h:403
bool kernel_verify_script(const kernel_ScriptPubkey *script_pubkey, int64_t amount, const kernel_Transaction *tx_to, const kernel_TransactionOutput **spent_outputs, size_t spent_outputs_len, unsigned int input_index, unsigned int flags, kernel_ScriptVerifyStatus *status) 3)
Verify if the input at input_index of tx_to spends the script pubkey under the constraints specified ...
void kernel_script_pubkey_destroy(kernel_ScriptPubkey *script_pubkey)
kernel_ScriptPubkey * kernel_script_pubkey_create(const unsigned char *script_pubkey, size_t script_pubkey_len)
Create a script pubkey from serialized data.
kernel_TransactionOutput * kernel_transaction_output_create(const kernel_ScriptPubkey *script_pubkey, int64_t amount)
Create a transaction output from a script pubkey and an amount.
struct kernel_TransactionOutput kernel_TransactionOutput
Definition bitcoinkernel.h:103
struct kernel_Transaction kernel_Transaction
Definition bitcoinkernel.h:93
kernel_Transaction * kernel_transaction_create(const unsigned char *raw_transaction, size_t raw_transaction_len)
Create a new transaction from the serialized data.
struct kernel_ScriptPubkey kernel_ScriptPubkey
Definition bitcoinkernel.h:98
kernel_ScriptVerifyStatus
Definition bitcoinkernel.h:380
@ kernel_SCRIPT_VERIFY_OK
Definition bitcoinkernel.h:381
void kernel_transaction_destroy(kernel_Transaction *transaction)
int main()
Definition context_free_example.c:5

Note that a Null pointer may be passed to spent_outputs if the taproot bit is not set in the flags bitfield and the amount may be zero if the segwit bit is not set.

"Full" validation

Full validation requires the user to instantiate a kernel_Context. It is recommended to create a kernel notification callbacks struct to handle any fatal errors arrising during processing. If a fatal error is encountered it is recommended to halt further processing and tear down.

The below example is a bare-bones setup for processing a single block on regtest. It starts out with creating a context. The context requires a context option, which is setup with callbacks for the notification and validation interface, and targets regtest. Setting the callbacks is optional, but recommended, and done here for demonstration purposes.

Then the context is used to create a chainstate manager together with the required options for the chainstate manager. Note that if the directories the chainstate manager and block manager options are configured with don't exist yet, will be created.

Finally, a block is created from its raw data and then processed by the chainstate manager. The new_block variable is used to denote whether a block has been processed before or not. If it is a duplicate new_block will be set to false.

#include "bitcoinkernel.h"
#include <stdio.h>
#include <stdlib.h>
void handle_error(void* _, const char* msg, size_t msg_size)
{
printf("%s\n", msg);
exit(0);
}
void block_checked(void* _, const kernel_BlockPointer* block, const kernel_BlockValidationState* state)
{
printf("Checked block\n");
}
int main() {
.user_data = NULL,
.block_tip = NULL,
.header_tip = NULL,
.progress = NULL,
.warning_set = NULL,
.warning_unset = NULL,
.flush_error = handle_error,
.fatal_error = handle_error,
};
kernel_context_options_set_notifications(context_options, notifications);
kernel_ValidationInterfaceCallbacks validation_interface = {
.user_data = NULL,
.block_checked = block_checked,
};
kernel_context_options_set_validation_interface(context_options, validation_interface);
kernel_context_options_set_chainparams(context_options, chainparams);
kernel_Context* context = kernel_context_create(context_options);
if (context == NULL) return 1;
const char data_dir[] = ".bitcoin";
kernel_ChainstateManagerOptions* chainman_options = kernel_chainstate_manager_options_create(context, data_dir, sizeof(data_dir) - 1);
if (chainman_options == NULL) return 1;
const char blocks_dir[] = ".bitcoin/blocks";
kernel_BlockManagerOptions* blockman_options = kernel_block_manager_options_create(context, blocks_dir, sizeof(blocks_dir) - 1);
if (blockman_options == NULL) return 1;
kernel_ChainstateManager* chainman = kernel_chainstate_manager_create(context, chainman_options, blockman_options, chainstate_load_options);
if (chainman == NULL) return 1;
kernel_chainstate_load_options_destroy(chainstate_load_options);
static const unsigned char block_data[] = {
0x00, 0x00, 0x00, 0x20, 0x06, 0x22, 0x6e, 0x46, 0x11, 0x1a, 0x0b, 0x59, 0xca, 0xaf, 0x12, 0x60,
0x43, 0xeb, 0x5b, 0xbf, 0x28, 0xc3, 0x4f, 0x3a, 0x5e, 0x33, 0x2a, 0x1f, 0xc7, 0xb2, 0xb7, 0x3c,
0xf1, 0x88, 0x91, 0x0f, 0x29, 0x5b, 0xad, 0xc0, 0xbd, 0xd9, 0xa2, 0xbc, 0x09, 0x55, 0xd1, 0x2f,
0x33, 0x74, 0x91, 0xea, 0xe4, 0xc8, 0x7b, 0xa4, 0x66, 0x00, 0x78, 0xc0, 0x15, 0x63, 0x10, 0x28,
0x4d, 0x47, 0xc6, 0xff, 0x9a, 0x24, 0x2d, 0x66, 0xff, 0xff, 0x7f, 0x20, 0x00, 0x00, 0x00, 0x00,
0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x02, 0x51, 0x00, 0xff,
0xff, 0xff, 0xff, 0x02, 0x00, 0xf2, 0x05, 0x2a, 0x01, 0x00, 0x00, 0x00, 0x16, 0x00, 0x14, 0x14,
0x09, 0x74, 0x54, 0x05, 0xc4, 0xe8, 0x31, 0x0a, 0x87, 0x5b, 0xcd, 0x60, 0x2d, 0xb6, 0xb9, 0xb3,
0xdc, 0x0c, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x6a, 0x24, 0xaa, 0x21,
0xa9, 0xed, 0xe2, 0xf6, 0x1c, 0x3f, 0x71, 0xd1, 0xde, 0xfd, 0x3f, 0xa9, 0x99, 0xdf, 0xa3, 0x69,
0x53, 0x75, 0x5c, 0x69, 0x06, 0x89, 0x79, 0x99, 0x62, 0xb4, 0x8b, 0xeb, 0xd8, 0x36, 0x97, 0x4e,
0x8c, 0xf9, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
kernel_Block* block = kernel_block_create(block_data, sizeof(block_data));
if (block == NULL) return 1;
bool new_block = true;
int res = kernel_chainstate_manager_process_block(context, chainman, block, &new_block);
return !(res && new_block);
}
void kernel_context_options_destroy(kernel_ContextOptions *context_options)
struct kernel_Block kernel_Block
Definition bitcoinkernel.h:207
struct kernel_ContextOptions kernel_ContextOptions
Definition bitcoinkernel.h:134
const kernel_ChainParameters * kernel_chain_parameters_create(const kernel_ChainType chain_type)
Creates a chain parameters struct with default parameters based on the passed in chain type.
void kernel_context_options_set_validation_interface(kernel_ContextOptions *context_options, kernel_ValidationInterfaceCallbacks validation_interface_callbacks)
Set the validation interface callbacks for the context options. The context created with the options ...
void kernel_chain_parameters_destroy(const kernel_ChainParameters *chain_parameters)
void kernel_chainstate_load_options_destroy(kernel_ChainstateLoadOptions *chainstate_load_options)
void kernel_block_destroy(kernel_Block *block)
@ kernel_CHAIN_TYPE_REGTEST
Definition bitcoinkernel.h:420
bool void kernel_chainstate_manager_destroy(kernel_ChainstateManager *chainstate_manager, const kernel_Context *context)
bool kernel_chainstate_manager_process_block(const kernel_Context *context, kernel_ChainstateManager *chainstate_manager, kernel_Block *block, bool *new_block) 2
Process and validate the passed in block with the chainstate manager. More detailed validation inform...
struct kernel_ChainParameters kernel_ChainParameters
Definition bitcoinkernel.h:123
struct kernel_BlockValidationState kernel_BlockValidationState
Definition bitcoinkernel.h:221
kernel_BlockManagerOptions * kernel_block_manager_options_create(const kernel_Context *context, const char *blocks_directory, size_t blocks_directory_len) 2)
Create options for the block manager. The block manager is used internally by the chainstate manager ...
void kernel_chainstate_manager_options_destroy(kernel_ChainstateManagerOptions *chainstate_manager_options)
struct kernel_BlockManagerOptions kernel_BlockManagerOptions
Definition bitcoinkernel.h:180
kernel_Context * kernel_context_create(const kernel_ContextOptions *context_options)
Create a new kernel context. If the options have not been previously set, their corresponding fields ...
kernel_ChainstateLoadOptions * kernel_chainstate_load_options_create()
kernel_ChainstateManager * kernel_chainstate_manager_create(const kernel_Context *context, const kernel_ChainstateManagerOptions *chainstate_manager_options, const kernel_BlockManagerOptions *block_manager_options, const kernel_ChainstateLoadOptions *chainstate_load_options) 2
Create a chainstate manager. This is the main object for many validation tasks as well as for retriev...
kernel_ChainstateManagerOptions * kernel_chainstate_manager_options_create(const kernel_Context *context, const char *data_directory, size_t data_directory_len) 2)
Create options for the chainstate manager.
kernel_ContextOptions * kernel_context_options_create()
void kernel_context_options_set_notifications(kernel_ContextOptions *context_options, kernel_NotificationInterfaceCallbacks notifications)
Set the kernel notifications for the context options. The context created with the options will be co...
struct kernel_ChainstateLoadOptions kernel_ChainstateLoadOptions
Definition bitcoinkernel.h:202
kernel_Block kernel_Block * kernel_block_create(const unsigned char *raw_block, size_t raw_block_len)
Parse a serialized raw block into a new block object.
struct kernel_BlockPointer kernel_BlockPointer
Definition bitcoinkernel.h:213
void kernel_context_destroy(kernel_Context *context)
struct kernel_ChainstateManager kernel_ChainstateManager
Definition bitcoinkernel.h:194
void kernel_block_manager_options_destroy(kernel_BlockManagerOptions *block_manager_options)
void kernel_context_options_set_chainparams(kernel_ContextOptions *context_options, const kernel_ChainParameters *chain_parameters) 2)
Sets the chain params for the context options. The context created with the options will be configure...
struct kernel_ChainstateManagerOptions kernel_ChainstateManagerOptions
Definition bitcoinkernel.h:171
struct kernel_Context kernel_Context
Definition bitcoinkernel.h:153
void handle_error(void *_, const char *msg, size_t msg_size)
Definition data_retrieval_example.c:6
Definition bitcoinkernel.h:328
const void * user_data
Holds a user-defined opaque structure that is passed to the notification callbacks.
Definition bitcoinkernel.h:329
Definition bitcoinkernel.h:313
const void * user_data
Definition bitcoinkernel.h:314
void block_checked(void *_, const kernel_BlockPointer *block, const kernel_BlockValidationState *state)
Definition validate_block_example.c:12

Data retrieval

The only difference when using the kernel library just for data retrieval compared to the "Full" validation case is that the chainstate manager does not issue validation interface callbacks, so no such callbacks need to be configured.

Once retrieved there are no restrictions on the lifetime of the data for the user. It can be retained for later processing, serialized, or used to more data.

#include "bitcoinkernel.h"
#include <stdio.h>
#include <stdlib.h>
void handle_error(void* _, const char* msg, size_t msg_size)
{
printf("%s\n", msg);
exit(0);
}
int main() {
.user_data = NULL,
.block_tip = NULL,
.header_tip = NULL,
.progress = NULL,
.warning_set = NULL,
.warning_unset = NULL,
.flush_error = handle_error,
.fatal_error = handle_error,
};
kernel_context_options_set_notifications(context_options, notifications);
kernel_context_options_set_chainparams(context_options, chainparams);
kernel_Context* context = kernel_context_create(context_options);
if (context == NULL) return 1;
const char data_dir[] = ".bitcoin";
kernel_ChainstateManagerOptions* chainman_options = kernel_chainstate_manager_options_create(context, data_dir, sizeof(data_dir) - 1);
if (chainman_options == NULL) return 1;
const char blocks_dir[] = ".bitcoin/blocks";
kernel_BlockManagerOptions* blockman_options = kernel_block_manager_options_create(context, blocks_dir, sizeof(blocks_dir) - 1);
if (blockman_options == NULL) return 1;
kernel_ChainstateManager* chainman = kernel_chainstate_manager_create(context, chainman_options, blockman_options, chainstate_load_options);
if (chainman == NULL) return 1;
kernel_chainstate_load_options_destroy(chainstate_load_options);
kernel_Block* genesis = kernel_read_block_from_disk(context, chainman, index);
// Now do something with this genesis block.
return 0;
}
kernel_Block * kernel_read_block_from_disk(const kernel_Context *context, kernel_ChainstateManager *chainstate_manager, const kernel_BlockIndex *block_index) 2
Reads the block the passed in block index points to from disk and returns it.
struct kernel_BlockIndex kernel_BlockIndex
Definition bitcoinkernel.h:162
kernel_BlockIndex * kernel_get_block_index_from_genesis(const kernel_Context *context, kernel_ChainstateManager *chainstate_manager) 2)
Get the block index entry of the genesis block.