kernel: Add chain params context option to C header
What changed, and why it matters
This commit adds a new configuration option to the Bitcoin Core kernel library's C API, allowing users to choose which blockchain network (mainnet, testnet, signet, or regtest) the kernel should use. It is a feature addition with no apparent security relevance.
No security action required; review as normal feature code.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch extends the libbitcoinkernel C interface by introducing btck_ChainParameters, btck_ChainType, and a setter on btck_ContextOptions. It refactors Context construction to copy chain parameters from options if provided, otherwise falling back to mainnet defaults. The change includes wrapper helpers and unit tests.
Changed components
src/kernel/bitcoinkernel.cppsrc/kernel/bitcoinkernel.hsrc/kernel/bitcoinkernel_wrapper.hsrc/test/kernel/test_kernel.cppInspect captured patch +144 / −2
diff --git a/src/kernel/bitcoinkernel.cpp b/src/kernel/bitcoinkernel.cpp
index 8f29ac81..35e03372 100644
--- a/src/kernel/bitcoinkernel.cpp
+++ b/src/kernel/bitcoinkernel.cpp
@@ -18,6 +18,7 @@
#include <script/script.h>
#include <serialize.h>
#include <streams.h>
+#include <sync.h>
#include <tinyformat.h>
#include <util/result.h>
#include <util/signalinterrupt.h>
@@ -108,6 +109,11 @@ struct Handle {
return *reinterpret_cast<const CPP*>(ptr);
}
+ static CPP& get(C* ptr)
+ {
+ return *reinterpret_cast<CPP*>(ptr);
+ }
+
static void operator delete(void* ptr)
{
delete reinterpret_cast<CPP*>(ptr);
@@ -219,6 +225,8 @@ struct LoggingConnection {
};
struct ContextOptions {
+ mutable Mutex m_mutex;
+ std::unique_ptr<const CChainParams> m_chainparams GUARDED_BY(m_mutex);
};
class Context
@@ -235,9 +243,19 @@ public:
Context(const ContextOptions* options, bool& sane)
: m_context{std::make_unique<kernel::Context>()},
m_notifications{std::make_unique<kernel::Notifications>()},
- m_interrupt{std::make_unique<util::SignalInterrupt>()},
- m_chainparams{CChainParams::Main()}
+ m_interrupt{std::make_unique<util::SignalInterrupt>()}
{
+ if (options) {
+ LOCK(options->m_mutex);
+ if (options->m_chainparams) {
+ m_chainparams = std::make_unique<const CChainParams>(*options->m_chainparams);
+ }
+ }
+
+ if (!m_chainparams) {
+ m_chainparams = CChainParams::Main();
+ }
+
if (!kernel::SanityChecks(*m_context)) {
sane = false;
}
@@ -252,6 +270,7 @@ struct btck_ScriptPubkey : Handle<btck_ScriptPubkey, CScript> {};
struct btck_LoggingConnection : Handle<btck_LoggingConnection, LoggingConnection> {};
struct btck_ContextOptions : Handle<btck_ContextOptions, ContextOptions> {};
struct btck_Context : Handle<btck_Context, std::shared_ptr<const Context>> {};
+struct btck_ChainParameters : Handle<btck_ChainParameters, CChainParams> {};
btck_Transaction* btck_transaction_create(const void* raw_transaction, size_t raw_transaction_len)
{
@@ -448,11 +467,50 @@ void btck_logging_connection_destroy(btck_LoggingConnection* connection)
delete connection;
}
+btck_ChainParameters* btck_chain_parameters_create(const btck_ChainType chain_type)
+{
+ switch (chain_type) {
+ case btck_ChainType_MAINNET: {
+ return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::Main().release()));
+ }
+ case btck_ChainType_TESTNET: {
+ return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::TestNet().release()));
+ }
+ case btck_ChainType_TESTNET_4: {
+ return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::TestNet4().release()));
+ }
+ case btck_ChainType_SIGNET: {
+ return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::SigNet({}).release()));
+ }
+ case btck_ChainType_REGTEST: {
+ return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::RegTest({}).release()));
+ }
+ }
+ assert(false);
+}
+
+btck_ChainParameters* btck_chain_parameters_copy(const btck_ChainParameters* chain_parameters)
+{
+ return btck_ChainParameters::copy(chain_parameters);
+}
+
+void btck_chain_parameters_destroy(btck_ChainParameters* chain_parameters)
+{
+ delete chain_parameters;
+}
+
btck_ContextOptions* btck_context_options_create()
{
return btck_ContextOptions::create();
}
+void btck_context_options_set_chainparams(btck_ContextOptions* options, const btck_ChainParameters* chain_parameters)
+{
+ // Copy the chainparams, so the caller can free it again
+ LOCK(btck_ContextOptions::get(options).m_mutex);
+ btck_ContextOptions::get(options).m_chainparams = std::make_unique<const CChainParams>(btck_ChainParameters::get(chain_parameters));
+}
+
void btck_context_options_destroy(btck_ContextOptions* options)
{
delete options;
diff --git a/src/kernel/bitcoinkernel.h b/src/kernel/bitcoinkernel.h
index 2cf714db..f901dedd 100644
--- a/src/kernel/bitcoinkernel.h
+++ b/src/kernel/bitcoinkernel.h
@@ -115,6 +115,15 @@ typedef struct btck_TransactionOutput btck_TransactionOutput;
*/
typedef struct btck_LoggingConnection btck_LoggingConnection;
+/**
+ * Opaque data structure for holding the chain parameters.
+ *
+ * These are eventually placed into a kernel context through the kernel context
+ * options. The parameters describe the properties of a chain, and may be
+ * instantiated for either mainnet, testnet, signet, or regtest.
+ */
+typedef struct btck_ChainParameters btck_ChainParameters;
+
/**
* Opaque data structure for holding options for creating a new kernel context.
*
@@ -217,6 +226,13 @@ typedef uint32_t btck_ScriptVerificationFlags;
btck_ScriptVerificationFlags_WITNESS | \
btck_ScriptVerificationFlags_TAPROOT))
+typedef uint8_t btck_ChainType;
+#define btck_ChainType_MAINNET ((btck_ChainType)(0))
+#define btck_ChainType_TESTNET ((btck_ChainType)(1))
+#define btck_ChainType_TESTNET_4 ((btck_ChainType)(2))
+#define btck_ChainType_SIGNET ((btck_ChainType)(3))
+#define btck_ChainType_REGTEST ((btck_ChainType)(4))
+
/**
* Function signature for serializing data.
*/
@@ -507,6 +523,34 @@ BITCOINKERNEL_API void btck_logging_connection_destroy(btck_LoggingConnection* l
///@}
+/** @name ChainParameters
+ * Functions for working with chain parameters.
+ */
+///@{
+
+/**
+ * @brief Creates a chain parameters struct with default parameters based on the
+ * passed in chain type.
+ *
+ * @param[in] chain_type Controls the chain parameters type created.
+ * @return An allocated chain parameters opaque struct.
+ */
+BITCOINKERNEL_API btck_ChainParameters* BITCOINKERNEL_WARN_UNUSED_RESULT btck_chain_parameters_create(
+ const btck_ChainType chain_type);
+
+/**
+ * Copy the chain parameters.
+ */
+BITCOINKERNEL_API btck_ChainParameters* BITCOINKERNEL_WARN_UNUSED_RESULT btck_chain_parameters_copy(
+ const btck_ChainParameters* chain_parameters) BITCOINKERNEL_ARG_NONNULL(1);
+
+/**
+ * Destroy the chain parameters.
+ */
+BITCOINKERNEL_API void btck_chain_parameters_destroy(btck_ChainParameters* chain_parameters);
+
+///@}
+
/** @name ContextOptions
* Functions for working with context options.
*/
@@ -517,6 +561,17 @@ BITCOINKERNEL_API void btck_logging_connection_destroy(btck_LoggingConnection* l
*/
BITCOINKERNEL_API btck_ContextOptions* BITCOINKERNEL_WARN_UNUSED_RESULT btck_context_options_create();
+/**
+ * @brief Sets the chain params for the context options. The context created
+ * with the options will be configured for these chain parameters.
+ *
+ * @param[in] context_options Non-null, previously created by @ref btck_context_options_create.
+ * @param[in] chain_parameters Is set to the context options.
+ */
+BITCOINKERNEL_API void btck_context_options_set_chainparams(
+ btck_ContextOptions* context_options,
+ const btck_ChainParameters* chain_parameters) BITCOINKERNEL_ARG_NONNULL(1, 2);
+
/**
* Destroy the context options.
*/
diff --git a/src/kernel/bitcoinkernel_wrapper.h b/src/kernel/bitcoinkernel_wrapper.h
index 070592d8..b550c3a5 100644
--- a/src/kernel/bitcoinkernel_wrapper.h
+++ b/src/kernel/bitcoinkernel_wrapper.h
@@ -38,6 +38,14 @@ enum class LogLevel : btck_LogLevel {
INFO_LEVEL = btck_LogLevel_INFO
};
+enum class ChainType : btck_ChainType {
+ MAINNET = btck_ChainType_MAINNET,
+ TESTNET = btck_ChainType_TESTNET,
+ TESTNET_4 = btck_ChainType_TESTNET_4,
+ SIGNET = btck_ChainType_SIGNET,
+ REGTEST = btck_ChainType_REGTEST
+};
+
enum class ScriptVerifyStatus : btck_ScriptVerifyStatus {
OK = btck_ScriptVerifyStatus_OK,
ERROR_INVALID_FLAGS_COMBINATION = btck_ScriptVerifyStatus_ERROR_INVALID_FLAGS_COMBINATION,
@@ -523,10 +531,22 @@ public:
}
};
+class ChainParams : public Handle<btck_ChainParameters, btck_chain_parameters_copy, btck_chain_parameters_destroy>
+{
+public:
+ ChainParams(ChainType chain_type)
+ : Handle{btck_chain_parameters_create(static_cast<btck_ChainType>(chain_type))} {}
+};
+
class ContextOptions : public UniqueHandle<btck_ContextOptions, btck_context_options_destroy>
{
public:
ContextOptions() : UniqueHandle{btck_context_options_create()} {}
+
+ void SetChainParams(ChainParams& chain_params)
+ {
+ btck_context_options_set_chainparams(get(), chain_params.get());
+ }
};
class Context : public Handle<btck_Context, btck_context_copy, btck_context_destroy>
diff --git a/src/test/kernel/test_kernel.cpp b/src/test/kernel/test_kernel.cpp
index e349cedb..8fc0308c 100644
--- a/src/test/kernel/test_kernel.cpp
+++ b/src/test/kernel/test_kernel.cpp
@@ -390,8 +390,17 @@ BOOST_AUTO_TEST_CASE(btck_context_tests)
CheckHandle(context, context2);
}
+ { // test with context options, but not options set
+ ContextOptions options{};
+ Context context{options};
+ }
+
{ // test with context options
ContextOptions options{};
+ ChainParams params{ChainType::MAINNET};
+ ChainParams regtest_params{ChainType::REGTEST};
+ CheckHandle(params, regtest_params);
+ options.SetChainParams(params);
Context context{options};
}
}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.