mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-03-30 18:35:54 +02:00
kernel: Add validation interface to C header
This adds the infrastructure required to process validation events. For
now the external validation interface only has support for the
`BlockChecked` , `NewPoWValidBlock`, `BlockConnected`, and
`BlockDisconnected` callback. Support for the other internal
validation interface methods can be added in the future.
The validation interface follows an architecture for defining its
callbacks and ownership that is similar to the notifications.
The task runner is created internally with a context, which itself
internally creates a unique ValidationSignals object. When the user
creates a new chainstate manager the validation signals are internally
passed to the chainstate manager through the context.
A validation interface can register for validation events with a
context. Internally the passed in validation interface is registerd with
the validation signals of a context.
The callbacks block any further validation execution when they are
called. It is up to the user to either multiplex them, or use them
otherwise in a multithreaded mechanism to make processing the validation
events non-blocking.
I.e. for a synchronous mechanism, the user executes instructions
directly at the end of the callback function:
```mermaid
sequenceDiagram
participant V as Validation
participant C as Callback
V->>C: Call callback
Note over C: Process event (blocks)
C-->>V: Return
Note over V: Validation resumes
```
To avoid blocking, the user can submit the data to e.g. a worker thread
or event manager, so processing happens asynchronously:
```mermaid
sequenceDiagram
participant V as Validation
participant C as Callback
participant W as Worker Thread
V->>C: Call callback
C->>W: Submit to worker thread
C-->>V: Return immediately
Note over V: Validation continues
Note over W: Process event async
```
This commit is contained in:
@@ -604,6 +604,34 @@ public:
|
||||
virtual void FatalErrorHandler(std::string_view error) {}
|
||||
};
|
||||
|
||||
class BlockValidationState
|
||||
{
|
||||
private:
|
||||
const btck_BlockValidationState* m_state;
|
||||
|
||||
public:
|
||||
BlockValidationState(const btck_BlockValidationState* state) : m_state{state} {}
|
||||
|
||||
BlockValidationState(const BlockValidationState&) = delete;
|
||||
BlockValidationState& operator=(const BlockValidationState&) = delete;
|
||||
BlockValidationState(BlockValidationState&&) = delete;
|
||||
BlockValidationState& operator=(BlockValidationState&&) = delete;
|
||||
};
|
||||
|
||||
class ValidationInterface
|
||||
{
|
||||
public:
|
||||
virtual ~ValidationInterface() = default;
|
||||
|
||||
virtual void BlockChecked(Block block, const BlockValidationState state) {}
|
||||
|
||||
virtual void PowValidBlock(BlockTreeEntry entry, Block block) {}
|
||||
|
||||
virtual void BlockConnected(Block block, BlockTreeEntry entry) {}
|
||||
|
||||
virtual void BlockDisconnected(Block block, BlockTreeEntry entry) {}
|
||||
};
|
||||
|
||||
class ChainParams : public Handle<btck_ChainParameters, btck_chain_parameters_copy, btck_chain_parameters_destroy>
|
||||
{
|
||||
public:
|
||||
@@ -641,6 +669,24 @@ public:
|
||||
.fatal_error = +[](void* user_data, const char* error, size_t error_len) { (*static_cast<user_type>(user_data))->FatalErrorHandler({error, error_len}); },
|
||||
});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SetValidationInterface(std::shared_ptr<T> validation_interface)
|
||||
{
|
||||
static_assert(std::is_base_of_v<ValidationInterface, T>);
|
||||
auto heap_vi = std::make_unique<std::shared_ptr<T>>(std::move(validation_interface));
|
||||
using user_type = std::shared_ptr<T>*;
|
||||
btck_context_options_set_validation_interface(
|
||||
get(),
|
||||
btck_ValidationInterfaceCallbacks{
|
||||
.user_data = heap_vi.release(),
|
||||
.user_data_destroy = +[](void* user_data) { delete static_cast<user_type>(user_data); },
|
||||
.block_checked = +[](void* user_data, btck_Block* block, const btck_BlockValidationState* state) { (*static_cast<user_type>(user_data))->BlockChecked(Block{block}, BlockValidationState{state}); },
|
||||
.pow_valid_block = +[](void* user_data, btck_Block* block, const btck_BlockTreeEntry* entry) { (*static_cast<user_type>(user_data))->PowValidBlock(BlockTreeEntry{entry}, Block{block}); },
|
||||
.block_connected = +[](void* user_data, btck_Block* block, const btck_BlockTreeEntry* entry) { (*static_cast<user_type>(user_data))->BlockConnected(Block{block}, BlockTreeEntry{entry}); },
|
||||
.block_disconnected = +[](void* user_data, btck_Block* block, const btck_BlockTreeEntry* entry) { (*static_cast<user_type>(user_data))->BlockDisconnected(Block{block}, BlockTreeEntry{entry}); },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class Context : public Handle<btck_Context, btck_context_copy, btck_context_destroy>
|
||||
|
||||
Reference in New Issue
Block a user