bitcoin/src/kernel/bitcoinkernel.h
TheCharlatan 337ea860df
kernel: Add kernel library context object
The context introduced here holds the objects that will be required for
running validation tasks, such as the chosen chain parameters, callbacks
for validation events, and interrupt handling. These will be used by the
chainstate manager introduced in subsequent commits.

This commit also introduces conventions for defining option objects. A
common pattern throughout the C header will be:
```
options = object_option_create();
object = object_create(options);
```
This allows for more consistent usage of a "builder pattern" for
objects where options can be configured independently from
instantiation.
2025-11-04 08:31:57 +01:00

562 lines
22 KiB
C++

// Copyright (c) 2024-present The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_KERNEL_BITCOINKERNEL_H
#define BITCOIN_KERNEL_BITCOINKERNEL_H
#ifndef __cplusplus
#include <stddef.h>
#include <stdint.h>
#else
#include <cstddef>
#include <cstdint>
#endif // __cplusplus
#ifndef BITCOINKERNEL_API
#ifdef BITCOINKERNEL_BUILD
#if defined(_WIN32)
#define BITCOINKERNEL_API __declspec(dllexport)
#else
#define BITCOINKERNEL_API __attribute__((visibility("default")))
#endif
#else
#if defined(_WIN32) && !defined(BITCOINKERNEL_STATIC)
#define BITCOINKERNEL_API __declspec(dllimport)
#else
#define BITCOINKERNEL_API
#endif
#endif
#endif
/* Warning attributes */
#if defined(__GNUC__)
#define BITCOINKERNEL_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
#else
#define BITCOINKERNEL_WARN_UNUSED_RESULT
#endif
#if !defined(BITCOINKERNEL_BUILD) && defined(__GNUC__)
#define BITCOINKERNEL_ARG_NONNULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
#else
#define BITCOINKERNEL_ARG_NONNULL(...)
#endif
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/**
* @page remarks Remarks
*
* @section context Context
*
* The library provides a built-in static constant kernel context. This static
* context offers only limited functionality. It detects and self-checks the
* correct sha256 implementation, initializes the random number generator and
* self-checks the secp256k1 static context. It is used internally for
* otherwise "context-free" operations. This means that the user is not
* required to initialize their own context before using the library.
*
* The user should create their own context for passing it to state-rich validation
* functions and holding callbacks for kernel events.
*
* @section error Error handling
*
* Functions communicate an error through their return types, usually returning
* a nullptr, 0, or false if an error is encountered. Additionally, verification
* functions, e.g. for scripts, may communicate more detailed error information
* through status code out parameters.
*
* @section pointer Pointer and argument conventions
*
* The user is responsible for de-allocating the memory owned by pointers
* returned by functions. Typically pointers returned by *_create(...) functions
* can be de-allocated by corresponding *_destroy(...) functions.
*
* A function that takes pointer arguments makes no assumptions on their
* lifetime. Once the function returns the user can safely de-allocate the
* passed in arguments.
*
* Const pointers represent views, and do not transfer ownership. Lifetime
* guarantees of these objects are described in the respective documentation.
* Ownership of these resources may be taken by copying. They are typically
* used for iteration with minimal overhead and require some care by the
* programmer that their lifetime is not extended beyond that of the original
* object.
*
* Array lengths follow the pointer argument they describe.
*/
/**
* Opaque data structure for holding a transaction.
*/
typedef struct btck_Transaction btck_Transaction;
/**
* Opaque data structure for holding a script pubkey.
*/
typedef struct btck_ScriptPubkey btck_ScriptPubkey;
/**
* Opaque data structure for holding a transaction output.
*/
typedef struct btck_TransactionOutput btck_TransactionOutput;
/**
* Opaque data structure for holding a logging connection.
*
* The logging connection can be used to manually stop logging.
*
* Messages that were logged before a connection is created are buffered in a
* 1MB buffer. Logging can alternatively be permanently disabled by calling
* @ref btck_logging_disable. Functions changing the logging settings are
* global and change the settings for all existing btck_LoggingConnection
* instances.
*/
typedef struct btck_LoggingConnection btck_LoggingConnection;
/**
* Opaque data structure for holding options for creating a new kernel context.
*
* Once a kernel context has been created from these options, they may be
* destroyed. The options hold the notification and validation interface
* callbacks as well as the selected chain type until they are passed to the
* context. If no options are configured, the context will be instantiated with
* no callbacks and for mainnet. Their content and scope can be expanded over
* time.
*/
typedef struct btck_ContextOptions btck_ContextOptions;
/**
* Opaque data structure for holding a kernel context.
*
* The kernel context is used to initialize internal state and hold the chain
* parameters and callbacks for handling error and validation events. Once
* other validation objects are instantiated from it, the context is kept in
* memory for the duration of their lifetimes.
*
* A constructed context can be safely used from multiple threads.
*/
typedef struct btck_Context btck_Context;
/** Callback function types */
/**
* Function signature for the global logging callback. All bitcoin kernel
* internal logs will pass through this callback.
*/
typedef void (*btck_LogCallback)(void* user_data, const char* message, size_t message_len);
/**
* Function signature for freeing user data.
*/
typedef void (*btck_DestroyCallback)(void* user_data);
/**
* A collection of logging categories that may be encountered by kernel code.
*/
typedef uint8_t btck_LogCategory;
#define btck_LogCategory_ALL ((btck_LogCategory)(0))
#define btck_LogCategory_BENCH ((btck_LogCategory)(1))
#define btck_LogCategory_BLOCKSTORAGE ((btck_LogCategory)(2))
#define btck_LogCategory_COINDB ((btck_LogCategory)(3))
#define btck_LogCategory_LEVELDB ((btck_LogCategory)(4))
#define btck_LogCategory_MEMPOOL ((btck_LogCategory)(5))
#define btck_LogCategory_PRUNE ((btck_LogCategory)(6))
#define btck_LogCategory_RAND ((btck_LogCategory)(7))
#define btck_LogCategory_REINDEX ((btck_LogCategory)(8))
#define btck_LogCategory_VALIDATION ((btck_LogCategory)(9))
#define btck_LogCategory_KERNEL ((btck_LogCategory)(10))
/**
* The level at which logs should be produced.
*/
typedef uint8_t btck_LogLevel;
#define btck_LogLevel_TRACE ((btck_LogLevel)(0))
#define btck_LogLevel_DEBUG ((btck_LogLevel)(1))
#define btck_LogLevel_INFO ((btck_LogLevel)(2))
/**
* Options controlling the format of log messages.
*
* Set fields as non-zero to indicate true.
*/
typedef struct {
int log_timestamps; //!< Prepend a timestamp to log messages.
int log_time_micros; //!< Log timestamps in microsecond precision.
int log_threadnames; //!< Prepend the name of the thread to log messages.
int log_sourcelocations; //!< Prepend the source location to log messages.
int always_print_category_levels; //!< Prepend the log category and level to log messages.
} btck_LoggingOptions;
/**
* A collection of status codes that may be issued by the script verify function.
*/
typedef uint8_t btck_ScriptVerifyStatus;
#define btck_ScriptVerifyStatus_OK ((btck_ScriptVerifyStatus)(0))
#define btck_ScriptVerifyStatus_ERROR_INVALID_FLAGS_COMBINATION ((btck_ScriptVerifyStatus)(1)) //!< The flags were combined in an invalid way.
#define btck_ScriptVerifyStatus_ERROR_SPENT_OUTPUTS_REQUIRED ((btck_ScriptVerifyStatus)(2)) //!< The taproot flag was set, so valid spent_outputs have to be provided.
/**
* Script verification flags that may be composed with each other.
*/
typedef uint32_t btck_ScriptVerificationFlags;
#define btck_ScriptVerificationFlags_NONE ((btck_ScriptVerificationFlags)(0))
#define btck_ScriptVerificationFlags_P2SH ((btck_ScriptVerificationFlags)(1U << 0)) //!< evaluate P2SH (BIP16) subscripts
#define btck_ScriptVerificationFlags_DERSIG ((btck_ScriptVerificationFlags)(1U << 2)) //!< enforce strict DER (BIP66) compliance
#define btck_ScriptVerificationFlags_NULLDUMMY ((btck_ScriptVerificationFlags)(1U << 4)) //!< enforce NULLDUMMY (BIP147)
#define btck_ScriptVerificationFlags_CHECKLOCKTIMEVERIFY ((btck_ScriptVerificationFlags)(1U << 9)) //!< enable CHECKLOCKTIMEVERIFY (BIP65)
#define btck_ScriptVerificationFlags_CHECKSEQUENCEVERIFY ((btck_ScriptVerificationFlags)(1U << 10)) //!< enable CHECKSEQUENCEVERIFY (BIP112)
#define btck_ScriptVerificationFlags_WITNESS ((btck_ScriptVerificationFlags)(1U << 11)) //!< enable WITNESS (BIP141)
#define btck_ScriptVerificationFlags_TAPROOT ((btck_ScriptVerificationFlags)(1U << 17)) //!< enable TAPROOT (BIPs 341 & 342)
#define btck_ScriptVerificationFlags_ALL ((btck_ScriptVerificationFlags)(btck_ScriptVerificationFlags_P2SH | \
btck_ScriptVerificationFlags_DERSIG | \
btck_ScriptVerificationFlags_NULLDUMMY | \
btck_ScriptVerificationFlags_CHECKLOCKTIMEVERIFY | \
btck_ScriptVerificationFlags_CHECKSEQUENCEVERIFY | \
btck_ScriptVerificationFlags_WITNESS | \
btck_ScriptVerificationFlags_TAPROOT))
/**
* Function signature for serializing data.
*/
typedef int (*btck_WriteBytes)(const void* bytes, size_t size, void* userdata);
/** @name Transaction
* Functions for working with transactions.
*/
///@{
/**
* @brief Create a new transaction from the serialized data.
*
* @param[in] raw_transaction Non-null.
* @param[in] raw_transaction_len Length of the serialized transaction.
* @return The transaction, or null on error.
*/
BITCOINKERNEL_API btck_Transaction* BITCOINKERNEL_WARN_UNUSED_RESULT btck_transaction_create(
const void* raw_transaction, size_t raw_transaction_len) BITCOINKERNEL_ARG_NONNULL(1);
/**
* @brief Copy a transaction. Transactions are reference counted, so this just
* increments the reference count.
*
* @param[in] transaction Non-null.
* @return The copied transaction.
*/
BITCOINKERNEL_API btck_Transaction* BITCOINKERNEL_WARN_UNUSED_RESULT btck_transaction_copy(
const btck_Transaction* transaction) BITCOINKERNEL_ARG_NONNULL(1);
/**
* @brief Serializes the transaction through the passed in callback to bytes.
* This is consensus serialization that is also used for the P2P network.
*
* @param[in] transaction Non-null.
* @param[in] writer Non-null, callback to a write bytes function.
* @param[in] user_data Holds a user-defined opaque structure that will be
* passed back through the writer callback.
* @return 0 on success.
*/
BITCOINKERNEL_API int btck_transaction_to_bytes(
const btck_Transaction* transaction,
btck_WriteBytes writer,
void* user_data) BITCOINKERNEL_ARG_NONNULL(1, 2);
/**
* @brief Get the number of outputs of a transaction.
*
* @param[in] transaction Non-null.
* @return The number of outputs.
*/
BITCOINKERNEL_API size_t BITCOINKERNEL_WARN_UNUSED_RESULT btck_transaction_count_outputs(
const btck_Transaction* transaction) BITCOINKERNEL_ARG_NONNULL(1);
/**
* @brief Get the transaction outputs at the provided index. The returned
* transaction output is not owned and depends on the lifetime of the
* transaction.
*
* @param[in] transaction Non-null.
* @param[in] output_index The index of the transaction output to be retrieved.
* @return The transaction output
*/
BITCOINKERNEL_API const btck_TransactionOutput* BITCOINKERNEL_WARN_UNUSED_RESULT btck_transaction_get_output_at(
const btck_Transaction* transaction, size_t output_index) BITCOINKERNEL_ARG_NONNULL(1);
/**
* @brief Get the number of inputs of a transaction.
*
* @param[in] transaction Non-null.
* @return The number of inputs.
*/
BITCOINKERNEL_API size_t BITCOINKERNEL_WARN_UNUSED_RESULT btck_transaction_count_inputs(
const btck_Transaction* transaction) BITCOINKERNEL_ARG_NONNULL(1);
/**
* Destroy the transaction.
*/
BITCOINKERNEL_API void btck_transaction_destroy(btck_Transaction* transaction);
///@}
/** @name ScriptPubkey
* Functions for working with script pubkeys.
*/
///@{
/**
* @brief Create a script pubkey from serialized data.
* @param[in] script_pubkey Non-null.
* @param[in] script_pubkey_len Length of the script pubkey data.
* @return The script pubkey.
*/
BITCOINKERNEL_API btck_ScriptPubkey* BITCOINKERNEL_WARN_UNUSED_RESULT btck_script_pubkey_create(
const void* script_pubkey, size_t script_pubkey_len) BITCOINKERNEL_ARG_NONNULL(1);
/**
* @brief Copy a script pubkey.
*
* @param[in] script_pubkey Non-null.
* @return The copied script pubkey.
*/
BITCOINKERNEL_API btck_ScriptPubkey* BITCOINKERNEL_WARN_UNUSED_RESULT btck_script_pubkey_copy(
const btck_ScriptPubkey* script_pubkey) BITCOINKERNEL_ARG_NONNULL(1);
/**
* @brief Verify if the input at input_index of tx_to spends the script pubkey
* under the constraints specified by flags. If the
* `btck_ScriptVerificationFlags_WITNESS` flag is set in the flags bitfield, the
* amount parameter is used. If the taproot flag is set, the spent outputs
* parameter is used to validate taproot transactions.
*
* @param[in] script_pubkey Non-null, script pubkey to be spent.
* @param[in] amount Amount of the script pubkey's associated output. May be zero if
* the witness flag is not set.
* @param[in] tx_to Non-null, transaction spending the script_pubkey.
* @param[in] spent_outputs Nullable if the taproot flag is not set. Points to an array of
* outputs spent by the transaction.
* @param[in] spent_outputs_len Length of the spent_outputs array.
* @param[in] input_index Index of the input in tx_to spending the script_pubkey.
* @param[in] flags Bitfield of btck_ScriptVerificationFlags controlling validation constraints.
* @param[out] status Nullable, will be set to an error code if the operation fails, or OK otherwise.
* @return 1 if the script is valid, 0 otherwise.
*/
BITCOINKERNEL_API int BITCOINKERNEL_WARN_UNUSED_RESULT 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) BITCOINKERNEL_ARG_NONNULL(1, 3);
/**
* @brief Serializes the script pubkey through the passed in callback to bytes.
*
* @param[in] script_pubkey Non-null.
* @param[in] writer Non-null, callback to a write bytes function.
* @param[in] user_data Holds a user-defined opaque structure that will be
* passed back through the writer callback.
* @return 0 on success.
*/
BITCOINKERNEL_API int btck_script_pubkey_to_bytes(
const btck_ScriptPubkey* script_pubkey,
btck_WriteBytes writer,
void* user_data) BITCOINKERNEL_ARG_NONNULL(1, 2);
/**
* Destroy the script pubkey.
*/
BITCOINKERNEL_API void btck_script_pubkey_destroy(btck_ScriptPubkey* script_pubkey);
///@}
/** @name TransactionOutput
* Functions for working with transaction outputs.
*/
///@{
/**
* @brief Create a transaction output from a script pubkey and an amount.
*
* @param[in] script_pubkey Non-null.
* @param[in] amount The amount associated with the script pubkey for this output.
* @return The transaction output.
*/
BITCOINKERNEL_API btck_TransactionOutput* BITCOINKERNEL_WARN_UNUSED_RESULT btck_transaction_output_create(
const btck_ScriptPubkey* script_pubkey,
int64_t amount) BITCOINKERNEL_ARG_NONNULL(1);
/**
* @brief Get the script pubkey of the output. The returned
* script pubkey is not owned and depends on the lifetime of the
* transaction output.
*
* @param[in] transaction_output Non-null.
* @return The script pubkey.
*/
BITCOINKERNEL_API const btck_ScriptPubkey* BITCOINKERNEL_WARN_UNUSED_RESULT btck_transaction_output_get_script_pubkey(
const btck_TransactionOutput* transaction_output) BITCOINKERNEL_ARG_NONNULL(1);
/**
* @brief Get the amount in the output.
*
* @param[in] transaction_output Non-null.
* @return The amount.
*/
BITCOINKERNEL_API int64_t BITCOINKERNEL_WARN_UNUSED_RESULT btck_transaction_output_get_amount(
const btck_TransactionOutput* transaction_output) BITCOINKERNEL_ARG_NONNULL(1);
/**
* @brief Copy a transaction output.
*
* @param[in] transaction_output Non-null.
* @return The copied transaction output.
*/
BITCOINKERNEL_API btck_TransactionOutput* BITCOINKERNEL_WARN_UNUSED_RESULT btck_transaction_output_copy(
const btck_TransactionOutput* transaction_output) BITCOINKERNEL_ARG_NONNULL(1);
/**
* Destroy the transaction output.
*/
BITCOINKERNEL_API void btck_transaction_output_destroy(btck_TransactionOutput* transaction_output);
///@}
/** @name Logging
* Logging-related functions.
*/
///@{
/**
* @brief This disables the global internal logger. No log messages will be
* buffered internally anymore once this is called and the buffer is cleared.
* This function should only be called once and is not thread or re-entry safe.
* Log messages will be buffered until this function is called, or a logging
* connection is created. This must not be called while a logging connection
* already exists.
*/
BITCOINKERNEL_API void btck_logging_disable();
/**
* @brief Set some options for the global internal logger. This changes global
* settings and will override settings for all existing @ref
* btck_LoggingConnection instances.
*
* @param[in] options Sets formatting options of the log messages.
*/
BITCOINKERNEL_API void btck_logging_set_options(const btck_LoggingOptions options);
/**
* @brief Set the log level of the global internal logger. This does not
* enable the selected categories. Use @ref btck_logging_enable_category to
* start logging from a specific, or all categories. This changes a global
* setting and will override settings for all existing
* @ref btck_LoggingConnection instances.
*
* @param[in] category If btck_LogCategory_ALL is chosen, sets both the global fallback log level
* used by all categories that don't have a specific level set, and also
* sets the log level for messages logged with the btck_LogCategory_ALL category itself.
* For any other category, sets a category-specific log level that overrides
* the global fallback for that category only.
* @param[in] level Log level at which the log category is set.
*/
BITCOINKERNEL_API void btck_logging_set_level_category(btck_LogCategory category, btck_LogLevel level);
/**
* @brief Enable a specific log category for the global internal logger. This
* changes a global setting and will override settings for all existing @ref
* btck_LoggingConnection instances.
*
* @param[in] category If btck_LogCategory_ALL is chosen, all categories will be enabled.
*/
BITCOINKERNEL_API void btck_logging_enable_category(btck_LogCategory category);
/**
* @brief Disable a specific log category for the global internal logger. This
* changes a global setting and will override settings for all existing @ref
* btck_LoggingConnection instances.
*
* @param[in] category If btck_LogCategory_ALL is chosen, all categories will be disabled.
*/
BITCOINKERNEL_API void btck_logging_disable_category(btck_LogCategory category);
/**
* @brief Start logging messages through the provided callback. Log messages
* produced before this function is first called are buffered and on calling this
* function are logged immediately.
*
* @param[in] log_callback Non-null, function through which messages will be logged.
* @param[in] user_data Nullable, holds a user-defined opaque structure. Is passed back
* to the user through the callback. If the user_data_destroy_callback
* is also defined it is assumed that ownership of the user_data is passed
* to the created logging connection.
* @param[in] user_data_destroy_callback Nullable, function for freeing the user data.
* @return A new kernel logging connection, or null on error.
*/
BITCOINKERNEL_API btck_LoggingConnection* BITCOINKERNEL_WARN_UNUSED_RESULT btck_logging_connection_create(
btck_LogCallback log_callback,
void* user_data,
btck_DestroyCallback user_data_destroy_callback) BITCOINKERNEL_ARG_NONNULL(1);
/**
* Stop logging and destroy the logging connection.
*/
BITCOINKERNEL_API void btck_logging_connection_destroy(btck_LoggingConnection* logging_connection);
///@}
/** @name ContextOptions
* Functions for working with context options.
*/
///@{
/**
* Creates an empty context options.
*/
BITCOINKERNEL_API btck_ContextOptions* BITCOINKERNEL_WARN_UNUSED_RESULT btck_context_options_create();
/**
* Destroy the context options.
*/
BITCOINKERNEL_API void btck_context_options_destroy(btck_ContextOptions* context_options);
///@}
/** @name Context
* Functions for working with contexts.
*/
///@{
/**
* @brief Create a new kernel context. If the options have not been previously
* set, their corresponding fields will be initialized to default values; the
* context will assume mainnet chain parameters and won't attempt to call the
* kernel notification callbacks.
*
* @param[in] context_options Nullable, created by @ref btck_context_options_create.
* @return The allocated kernel context, or null on error.
*/
BITCOINKERNEL_API btck_Context* BITCOINKERNEL_WARN_UNUSED_RESULT btck_context_create(
const btck_ContextOptions* context_options);
/**
* Copy the context.
*/
BITCOINKERNEL_API btck_Context* BITCOINKERNEL_WARN_UNUSED_RESULT btck_context_copy(
const btck_Context* context) BITCOINKERNEL_ARG_NONNULL(1);
/**
* Destroy the context.
*/
BITCOINKERNEL_API void btck_context_destroy(btck_Context* context);
///@}
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // BITCOIN_KERNEL_BITCOINKERNEL_H