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
};
btck_Transaction* transaction = btck_transaction_create(tx, sizeof(tx));
if (transaction == NULL) return 1;
btck_ScriptPubkey* script_pubkey = btck_script_pubkey_create(script, sizeof(script));
if (script_pubkey == NULL) return 1;
int64_t amount = 88480;
btck_TransactionOutput* output = btck_transaction_output_create(script_pubkey, amount);
const btck_TransactionOutput* output_ = output;
/*script_pubkey=*/ script_pubkey,
/*amount=*/ amount,
/*tx_to=*/ transaction,
/*spent_outputs=*/ &output_,
/*spent_outputs_len=*/1,
/*input_index=*/ 0,
/*status*/ &status);
return !(result && status == btck_ScriptVerifyStatus_SCRIPT_VERIFY_OK);
}
BITCOINKERNEL_API btck_TransactionOutput * btck_transaction_output_create(const btck_ScriptPubkey *script_pubkey, int64_t amount)
Create a transaction output from a script pubkey and an amount.
#define btck_ScriptVerifyStatus_SCRIPT_VERIFY_OK
Definition bitcoinkernel.h:402
BITCOINKERNEL_API void btck_transaction_destroy(btck_Transaction *transaction)
#define btck_ScriptVerificationFlags_ALL
Definition bitcoinkernel.h:418
struct btck_ScriptPubkey btck_ScriptPubkey
Definition bitcoinkernel.h:118
BITCOINKERNEL_API int btck_script_pubkey_verify(const btck_ScriptPubkey *script_pubkey, int64_t amount, const btck_Transaction *tx_to, const btck_TransactionOutput **spent_outputs, size_t spent_outputs_len, unsigned int input_index, unsigned int flags, btck_ScriptVerifyStatus *status) 3)
Verify if the input at input_index of tx_to spends the script pubkey under the constraints specified ...
BITCOINKERNEL_API btck_Transaction * btck_transaction_create(const void *raw_transaction, size_t raw_transaction_len)
Create a new transaction from the serialized data.
BITCOINKERNEL_API void btck_script_pubkey_destroy(btck_ScriptPubkey *script_pubkey)
BITCOINKERNEL_API void btck_transaction_output_destroy(btck_TransactionOutput *transaction_output)
BITCOINKERNEL_API btck_ScriptPubkey * btck_script_pubkey_create(const void *script_pubkey, size_t script_pubkey_len)
Create a script pubkey from serialized data.
uint8_t btck_ScriptVerifyStatus
Definition bitcoinkernel.h:401
struct btck_TransactionOutput btck_TransactionOutput
Definition bitcoinkernel.h:123
struct btck_Transaction btck_Transaction
Definition bitcoinkernel.h:113
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* _, btck_Block* block, const btck_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,
};
btck_context_options_set_notifications(context_options, notifications);
btck_ValidationInterfaceCallbacks validation_interface = {
.user_data = NULL,
.block_checked = block_checked,
};
btck_context_options_set_validation_interface(context_options, validation_interface);
btck_context_options_set_chainparams(context_options, chainparams);
btck_Context* context = btck_context_create(context_options);
btck_context_options_destroy(context_options);
if (context == NULL) return 1;
const char data_dir[] = ".bitcoin";
const char blocks_dir[] = ".bitcoin/blocks";
btck_ChainstateManagerOptions* chainman_options = btck_chainstate_manager_options_create(context, data_dir, sizeof(data_dir) - 1, blocks_dir, sizeof(blocks_dir) - 1);
if (chainman_options == NULL) return 1;
if (chainman == NULL) return 1;
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,
};
btck_Block* block = btck_block_create(block_data, sizeof(block_data));
if (block == NULL) return 1;
int new_block = 1;
int res = btck_chainstate_manager_process_block(chainman, block, &new_block);
return !(res && new_block);
}
#define btck_ChainType_REGTEST
Definition bitcoinkernel.h:431
struct btck_ContextOptions btck_ContextOptions
Definition bitcoinkernel.h:156
struct btck_Context btck_Context
Definition bitcoinkernel.h:172
BITCOINKERNEL_API btck_ChainstateManagerOptions * btck_chainstate_manager_options_create(const btck_Context *context, const char *data_directory, size_t data_directory_len, const char *blocks_directory, size_t blocks_directory_len) 2)
Create options for the chainstate manager.
BITCOINKERNEL_API void btck_chainstate_manager_destroy(btck_ChainstateManager *chainstate_manager)
BITCOINKERNEL_API void btck_context_options_destroy(btck_ContextOptions *context_options)
BITCOINKERNEL_API void btck_chainstate_manager_options_destroy(btck_ChainstateManagerOptions *chainstate_manager_options)
BITCOINKERNEL_API btck_Block * btck_block_create(const void *raw_block, size_t raw_block_len)
Parse a serialized raw block into a new block object.
BITCOINKERNEL_API btck_Context * btck_context_create(const btck_ContextOptions *context_options)
Create a new kernel context. If the options have not been previously set, their corresponding fields ...
BITCOINKERNEL_API void btck_context_options_set_validation_interface(btck_ContextOptions *context_options, btck_ValidationInterfaceCallbacks validation_interface_callbacks)
Set the validation interface callbacks for the context options. The context created with the options ...
struct btck_ChainstateManager btck_ChainstateManager
Definition bitcoinkernel.h:205
BITCOINKERNEL_API void btck_chain_parameters_destroy(btck_ChainParameters *chain_parameters)
BITCOINKERNEL_API int btck_chainstate_manager_process_block(btck_ChainstateManager *chainstate_manager, const btck_Block *block, int *new_block) 2
Process and validate the passed in block with the chainstate manager. More detailed validation inform...
BITCOINKERNEL_API btck_ChainstateManager * btck_chainstate_manager_create(const btck_ChainstateManagerOptions *chainstate_manager_options)
Create a chainstate manager. This is the main object for many validation tasks as well as for retriev...
struct btck_BlockValidationState btck_BlockValidationState
Definition bitcoinkernel.h:218
BITCOINKERNEL_API void btck_block_destroy(btck_Block *block)
struct btck_ChainstateManagerOptions btck_ChainstateManagerOptions
Definition bitcoinkernel.h:194
BITCOINKERNEL_API void btck_context_options_set_chainparams(btck_ContextOptions *context_options, const btck_ChainParameters *chain_parameters) 2)
Sets the chain params for the context options. The context created with the options will be configure...
struct btck_ChainParameters btck_ChainParameters
Definition bitcoinkernel.h:145
struct btck_Block btck_Block
Definition bitcoinkernel.h:210
BITCOINKERNEL_API void btck_context_options_set_notifications(btck_ContextOptions *context_options, btck_NotificationInterfaceCallbacks notifications)
Set the kernel notifications for the context options. The context created with the options will be co...
BITCOINKERNEL_API void btck_context_destroy(btck_Context *context)
BITCOINKERNEL_API btck_ContextOptions * btck_context_options_create()
BITCOINKERNEL_API btck_ChainParameters * btck_chain_parameters_create(const btck_ChainType chain_type)
Creates a chain parameters struct with default parameters based on the passed in chain type.
void handle_error(void *_, const char *msg, size_t msg_size)
Definition data_retrieval_example.c:6
Definition bitcoinkernel.h:347
void * user_data
Definition bitcoinkernel.h:348
Definition bitcoinkernel.h:330
void * user_data
Definition bitcoinkernel.h:331
void block_checked(void *_, btck_Block *block, const btck_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,
};
btck_context_options_set_notifications(context_options, notifications);
btck_context_options_set_chainparams(context_options, chainparams);
btck_Context* context = btck_context_create(context_options);
btck_context_options_destroy(context_options);
if (context == NULL) return 1;
const char data_dir[] = ".bitcoin";
const char blocks_dir[] = ".bitcoin/blocks";
btck_ChainstateManagerOptions* chainman_options = btck_chainstate_manager_options_create(context, data_dir, sizeof(data_dir) - 1, blocks_dir, sizeof(blocks_dir));
if (chainman_options == NULL) return 1;
if (chainman == NULL) return 1;
btck_Block* genesis = btck_block_read(chainman, entry);
// Now do something with this genesis block.
return 0;
}
struct btck_BlockTreeEntry btck_BlockTreeEntry
Definition bitcoinkernel.h:185
struct btck_Chain btck_Chain
Definition bitcoinkernel.h:224
BITCOINKERNEL_API btck_BlockTreeEntry * btck_chain_get_genesis(const btck_Chain *chain)
BITCOINKERNEL_API btck_Block * btck_block_read(const btck_ChainstateManager *chainstate_manager, const btck_BlockTreeEntry *block_tree_entry) 2)
Reads the block the passed in block index points to from disk and returns it.
BITCOINKERNEL_API int BITCOINKERNEL_API const btck_Chain * btck_chainstate_manager_get_active_chain(const btck_ChainstateManager *chainstate_manager)
Returns the best known currently active chain. Its lifetime is dependent on the chainstate manager an...