mirror of https://github.com/bitcoin/bitcoin.git
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.
This commit is contained in:
parent
4a0f6ba7a7
commit
cc89fcc6da
|
@ -7,8 +7,11 @@
|
|||
#include <kernel/bitcoinkernel.h>
|
||||
|
||||
#include <consensus/amount.h>
|
||||
#include <kernel/chainparams.h>
|
||||
#include <kernel/checks.h>
|
||||
#include <kernel/context.h>
|
||||
#include <kernel/cs_main.h>
|
||||
#include <kernel/notifications_interface.h>
|
||||
#include <logging.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <script/interpreter.h>
|
||||
|
@ -16,6 +19,8 @@
|
|||
#include <serialize.h>
|
||||
#include <streams.h>
|
||||
#include <tinyformat.h>
|
||||
#include <util/result.h>
|
||||
#include <util/signalinterrupt.h>
|
||||
#include <util/translation.h>
|
||||
|
||||
#include <cassert>
|
||||
|
@ -24,6 +29,7 @@
|
|||
#include <exception>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
@ -221,12 +227,40 @@ struct LoggingConnection {
|
|||
}
|
||||
};
|
||||
|
||||
struct ContextOptions {
|
||||
};
|
||||
|
||||
class Context
|
||||
{
|
||||
public:
|
||||
std::unique_ptr<kernel::Context> m_context;
|
||||
|
||||
std::unique_ptr<kernel::Notifications> m_notifications;
|
||||
|
||||
std::unique_ptr<util::SignalInterrupt> m_interrupt;
|
||||
|
||||
std::unique_ptr<const CChainParams> m_chainparams;
|
||||
|
||||
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()}
|
||||
{
|
||||
if (!kernel::SanityChecks(*m_context)) {
|
||||
sane = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
struct btck_Transaction : Handle<btck_Transaction, std::shared_ptr<const CTransaction>> {};
|
||||
struct btck_TransactionOutput : Handle<btck_TransactionOutput, CTxOut> {};
|
||||
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>> {};
|
||||
|
||||
btck_Transaction* btck_transaction_create(const void* raw_transaction, size_t raw_transaction_len)
|
||||
{
|
||||
|
@ -408,3 +442,35 @@ void btck_logging_connection_destroy(btck_LoggingConnection* connection)
|
|||
{
|
||||
delete connection;
|
||||
}
|
||||
|
||||
btck_ContextOptions* btck_context_options_create()
|
||||
{
|
||||
return btck_ContextOptions::create();
|
||||
}
|
||||
|
||||
void btck_context_options_destroy(btck_ContextOptions* options)
|
||||
{
|
||||
delete options;
|
||||
}
|
||||
|
||||
btck_Context* btck_context_create(const btck_ContextOptions* options)
|
||||
{
|
||||
bool sane{true};
|
||||
const ContextOptions* opts = options ? &btck_ContextOptions::get(options) : nullptr;
|
||||
auto context{std::make_shared<const Context>(opts, sane)};
|
||||
if (!sane) {
|
||||
LogError("Kernel context sanity check failed.");
|
||||
return nullptr;
|
||||
}
|
||||
return btck_Context::create(context);
|
||||
}
|
||||
|
||||
btck_Context* btck_context_copy(const btck_Context* context)
|
||||
{
|
||||
return btck_Context::copy(context);
|
||||
}
|
||||
|
||||
void btck_context_destroy(btck_Context* context)
|
||||
{
|
||||
delete context;
|
||||
}
|
||||
|
|
|
@ -57,6 +57,9 @@ extern "C" {
|
|||
* 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
|
||||
|
@ -112,6 +115,29 @@ typedef struct btck_TransactionOutput btck_TransactionOutput;
|
|||
*/
|
||||
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 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 */
|
||||
|
||||
/**
|
||||
|
@ -470,6 +496,53 @@ BITCOINKERNEL_API void btck_logging_connection_destroy(btck_LoggingConnection* l
|
|||
|
||||
///@}
|
||||
|
||||
/** @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
|
||||
|
|
|
@ -318,8 +318,8 @@ protected:
|
|||
public:
|
||||
explicit UniqueHandle(CType* ptr) : m_ptr{check(ptr)} {}
|
||||
|
||||
CType* get() { return m_ptr; }
|
||||
const CType* get() const { return m_ptr; }
|
||||
CType* get() { return m_ptr.get(); }
|
||||
const CType* get() const { return m_ptr.get(); }
|
||||
};
|
||||
|
||||
class Transaction;
|
||||
|
@ -505,7 +505,7 @@ concept Log = requires(T a, std::string_view message) {
|
|||
};
|
||||
|
||||
template <Log T>
|
||||
class Logger : public UniqueHandle<btck_LoggingConnection, btck_logging_connection_destroy>
|
||||
class Logger : UniqueHandle<btck_LoggingConnection, btck_logging_connection_destroy>
|
||||
{
|
||||
public:
|
||||
Logger(std::unique_ptr<T> log, const btck_LoggingOptions& logging_options)
|
||||
|
@ -518,6 +518,24 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class ContextOptions : UniqueHandle<btck_ContextOptions, btck_context_options_destroy>
|
||||
{
|
||||
public:
|
||||
ContextOptions() : UniqueHandle{btck_context_options_create()} {}
|
||||
|
||||
friend class Context;
|
||||
};
|
||||
|
||||
class Context : public Handle<btck_Context, btck_context_copy, btck_context_destroy>
|
||||
{
|
||||
public:
|
||||
Context(ContextOptions& opts)
|
||||
: Handle{btck_context_create(opts.get())} {}
|
||||
|
||||
Context()
|
||||
: Handle{btck_context_create(ContextOptions{}.get())} {}
|
||||
};
|
||||
|
||||
} // namespace btck
|
||||
|
||||
#endif // BITCOIN_KERNEL_BITCOINKERNEL_WRAPPER_H
|
||||
|
|
|
@ -384,3 +384,17 @@ BOOST_AUTO_TEST_CASE(logging_tests)
|
|||
}
|
||||
Logger logger{std::make_unique<TestLog>(TestLog{}), logging_options};
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(btck_context_tests)
|
||||
{
|
||||
{ // test default context
|
||||
Context context{};
|
||||
Context context2{};
|
||||
CheckHandle(context, context2);
|
||||
}
|
||||
|
||||
{ // test with context options
|
||||
ContextOptions options{};
|
||||
Context context{options};
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue