kernel: Add functions for the block validation state to C header
These allow for the interpretation of the data in a `BlockChecked` validation interface callback. The validation state passed through `BlockChecked` is the source of truth for the validity of a block (the mode). It is also useful to get richer information in case a block failed to validate (the result).
This commit is contained in:
4 files changed
+151
-1
No files matched your search
@@ -769,6 +769,40 @@ void btck_context_destroy(btck_Context* context)
|
|||||||
delete context;
|
delete context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
btck_ValidationMode btck_block_validation_state_get_validation_mode(const btck_BlockValidationState* block_validation_state_)
|
||||||
|
{
|
||||||
|
auto& block_validation_state = btck_BlockValidationState::get(block_validation_state_);
|
||||||
|
if (block_validation_state.IsValid()) return btck_ValidationMode_VALID;
|
||||||
|
if (block_validation_state.IsInvalid()) return btck_ValidationMode_INVALID;
|
||||||
|
return btck_ValidationMode_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
btck_BlockValidationResult btck_block_validation_state_get_block_validation_result(const btck_BlockValidationState* block_validation_state_)
|
||||||
|
{
|
||||||
|
auto& block_validation_state = btck_BlockValidationState::get(block_validation_state_);
|
||||||
|
switch (block_validation_state.GetResult()) {
|
||||||
|
case BlockValidationResult::BLOCK_RESULT_UNSET:
|
||||||
|
return btck_BlockValidationResult_UNSET;
|
||||||
|
case BlockValidationResult::BLOCK_CONSENSUS:
|
||||||
|
return btck_BlockValidationResult_CONSENSUS;
|
||||||
|
case BlockValidationResult::BLOCK_CACHED_INVALID:
|
||||||
|
return btck_BlockValidationResult_CACHED_INVALID;
|
||||||
|
case BlockValidationResult::BLOCK_INVALID_HEADER:
|
||||||
|
return btck_BlockValidationResult_INVALID_HEADER;
|
||||||
|
case BlockValidationResult::BLOCK_MUTATED:
|
||||||
|
return btck_BlockValidationResult_MUTATED;
|
||||||
|
case BlockValidationResult::BLOCK_MISSING_PREV:
|
||||||
|
return btck_BlockValidationResult_MISSING_PREV;
|
||||||
|
case BlockValidationResult::BLOCK_INVALID_PREV:
|
||||||
|
return btck_BlockValidationResult_INVALID_PREV;
|
||||||
|
case BlockValidationResult::BLOCK_TIME_FUTURE:
|
||||||
|
return btck_BlockValidationResult_TIME_FUTURE;
|
||||||
|
case BlockValidationResult::BLOCK_HEADER_LOW_WORK:
|
||||||
|
return btck_BlockValidationResult_HEADER_LOW_WORK;
|
||||||
|
} // no default case, so the compiler can warn about missing cases
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
btck_ChainstateManagerOptions* btck_chainstate_manager_options_create(const btck_Context* context, const char* data_dir, size_t data_dir_len, const char* blocks_dir, size_t blocks_dir_len)
|
btck_ChainstateManagerOptions* btck_chainstate_manager_options_create(const btck_Context* context, const char* data_dir, size_t data_dir_len, const char* blocks_dir, size_t blocks_dir_len)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -249,6 +249,29 @@ typedef void (*btck_ValidationInterfacePoWValidBlock)(void* user_data, btck_Bloc
|
|||||||
typedef void (*btck_ValidationInterfaceBlockConnected)(void* user_data, btck_Block* block, const btck_BlockTreeEntry* entry);
|
typedef void (*btck_ValidationInterfaceBlockConnected)(void* user_data, btck_Block* block, const btck_BlockTreeEntry* entry);
|
||||||
typedef void (*btck_ValidationInterfaceBlockDisconnected)(void* user_data, btck_Block* block, const btck_BlockTreeEntry* entry);
|
typedef void (*btck_ValidationInterfaceBlockDisconnected)(void* user_data, btck_Block* block, const btck_BlockTreeEntry* entry);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether a validated data structure is valid, invalid, or an error was
|
||||||
|
* encountered during processing.
|
||||||
|
*/
|
||||||
|
typedef uint8_t btck_ValidationMode;
|
||||||
|
#define btck_ValidationMode_VALID ((btck_ValidationMode)(0))
|
||||||
|
#define btck_ValidationMode_INVALID ((btck_ValidationMode)(1))
|
||||||
|
#define btck_ValidationMode_INTERNAL_ERROR ((btck_ValidationMode)(2))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A granular "reason" why a block was invalid.
|
||||||
|
*/
|
||||||
|
typedef uint32_t btck_BlockValidationResult;
|
||||||
|
#define btck_BlockValidationResult_UNSET ((btck_BlockValidationResult)(0)) //!< initial value. Block has not yet been rejected
|
||||||
|
#define btck_BlockValidationResult_CONSENSUS ((btck_BlockValidationResult)(1)) //!< invalid by consensus rules (excluding any below reasons)
|
||||||
|
#define btck_BlockValidationResult_CACHED_INVALID ((btck_BlockValidationResult)(2)) //!< this block was cached as being invalid and we didn't store the reason why
|
||||||
|
#define btck_BlockValidationResult_INVALID_HEADER ((btck_BlockValidationResult)(3)) //!< invalid proof of work or time too old
|
||||||
|
#define btck_BlockValidationResult_MUTATED ((btck_BlockValidationResult)(4)) //!< the block's data didn't match the data committed to by the PoW
|
||||||
|
#define btck_BlockValidationResult_MISSING_PREV ((btck_BlockValidationResult)(5)) //!< We don't have the previous block the checked one is built on
|
||||||
|
#define btck_BlockValidationResult_INVALID_PREV ((btck_BlockValidationResult)(6)) //!< A block this one builds on is invalid
|
||||||
|
#define btck_BlockValidationResult_TIME_FUTURE ((btck_BlockValidationResult)(7)) //!< block timestamp was > 2 hours in the future (or our clock is bad)
|
||||||
|
#define btck_BlockValidationResult_HEADER_LOW_WORK ((btck_BlockValidationResult)(8)) //!< the block header may be on a too-little-work chain
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the validation interface callbacks. The user data pointer may be used
|
* Holds the validation interface callbacks. The user data pointer may be used
|
||||||
* to point to user-defined structures to make processing the validation
|
* to point to user-defined structures to make processing the validation
|
||||||
@@ -967,6 +990,25 @@ BITCOINKERNEL_API void btck_block_destroy(btck_Block* block);
|
|||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
|
/** @name BlockValidationState
|
||||||
|
* Functions for working with block validation states.
|
||||||
|
*/
|
||||||
|
///@{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the validation mode from an opaque block validation state pointer.
|
||||||
|
*/
|
||||||
|
BITCOINKERNEL_API btck_ValidationMode btck_block_validation_state_get_validation_mode(
|
||||||
|
const btck_BlockValidationState* block_validation_state) BITCOINKERNEL_ARG_NONNULL(1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the validation result from an opaque block validation state pointer.
|
||||||
|
*/
|
||||||
|
BITCOINKERNEL_API btck_BlockValidationResult btck_block_validation_state_get_block_validation_result(
|
||||||
|
const btck_BlockValidationState* block_validation_state) BITCOINKERNEL_ARG_NONNULL(1);
|
||||||
|
|
||||||
|
///@}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|||||||
@@ -58,6 +58,24 @@ enum class Warning : btck_Warning {
|
|||||||
LARGE_WORK_INVALID_CHAIN = btck_Warning_LARGE_WORK_INVALID_CHAIN
|
LARGE_WORK_INVALID_CHAIN = btck_Warning_LARGE_WORK_INVALID_CHAIN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ValidationMode : btck_ValidationMode {
|
||||||
|
VALID = btck_ValidationMode_VALID,
|
||||||
|
INVALID = btck_ValidationMode_INVALID,
|
||||||
|
INTERNAL_ERROR = btck_ValidationMode_INTERNAL_ERROR
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BlockValidationResult : btck_BlockValidationResult {
|
||||||
|
UNSET = btck_BlockValidationResult_UNSET,
|
||||||
|
CONSENSUS = btck_BlockValidationResult_CONSENSUS,
|
||||||
|
CACHED_INVALID = btck_BlockValidationResult_CACHED_INVALID,
|
||||||
|
INVALID_HEADER = btck_BlockValidationResult_INVALID_HEADER,
|
||||||
|
MUTATED = btck_BlockValidationResult_MUTATED,
|
||||||
|
MISSING_PREV = btck_BlockValidationResult_MISSING_PREV,
|
||||||
|
INVALID_PREV = btck_BlockValidationResult_INVALID_PREV,
|
||||||
|
TIME_FUTURE = btck_BlockValidationResult_TIME_FUTURE,
|
||||||
|
HEADER_LOW_WORK = btck_BlockValidationResult_HEADER_LOW_WORK
|
||||||
|
};
|
||||||
|
|
||||||
enum class ScriptVerifyStatus : btck_ScriptVerifyStatus {
|
enum class ScriptVerifyStatus : btck_ScriptVerifyStatus {
|
||||||
OK = btck_ScriptVerifyStatus_OK,
|
OK = btck_ScriptVerifyStatus_OK,
|
||||||
ERROR_INVALID_FLAGS_COMBINATION = btck_ScriptVerifyStatus_ERROR_INVALID_FLAGS_COMBINATION,
|
ERROR_INVALID_FLAGS_COMBINATION = btck_ScriptVerifyStatus_ERROR_INVALID_FLAGS_COMBINATION,
|
||||||
@@ -616,6 +634,16 @@ public:
|
|||||||
BlockValidationState& operator=(const BlockValidationState&) = delete;
|
BlockValidationState& operator=(const BlockValidationState&) = delete;
|
||||||
BlockValidationState(BlockValidationState&&) = delete;
|
BlockValidationState(BlockValidationState&&) = delete;
|
||||||
BlockValidationState& operator=(BlockValidationState&&) = delete;
|
BlockValidationState& operator=(BlockValidationState&&) = delete;
|
||||||
|
|
||||||
|
ValidationMode GetValidationMode() const
|
||||||
|
{
|
||||||
|
return static_cast<ValidationMode>(btck_block_validation_state_get_validation_mode(m_state));
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockValidationResult GetBlockValidationResult() const
|
||||||
|
{
|
||||||
|
return static_cast<BlockValidationResult>(btck_block_validation_state_get_block_validation_result(m_state));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ValidationInterface
|
class ValidationInterface
|
||||||
|
|||||||
@@ -131,7 +131,53 @@ class TestValidationInterface : public ValidationInterface
|
|||||||
public:
|
public:
|
||||||
void BlockChecked(Block block, const BlockValidationState state) override
|
void BlockChecked(Block block, const BlockValidationState state) override
|
||||||
{
|
{
|
||||||
std::cout << "Block checked." << std::endl;
|
std::cout << "Block checked: ";
|
||||||
|
|
||||||
|
auto mode{state.GetValidationMode()};
|
||||||
|
switch (mode) {
|
||||||
|
case ValidationMode::VALID: {
|
||||||
|
std::cout << "Valid block" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case ValidationMode::INVALID: {
|
||||||
|
std::cout << "Invalid block: ";
|
||||||
|
auto result{state.GetBlockValidationResult()};
|
||||||
|
switch (result) {
|
||||||
|
case BlockValidationResult::UNSET:
|
||||||
|
std::cout << "initial value. Block has not yet been rejected" << std::endl;
|
||||||
|
break;
|
||||||
|
case BlockValidationResult::HEADER_LOW_WORK:
|
||||||
|
std::cout << "the block header may be on a too-little-work chain" << std::endl;
|
||||||
|
break;
|
||||||
|
case BlockValidationResult::CONSENSUS:
|
||||||
|
std::cout << "invalid by consensus rules (excluding any below reasons)" << std::endl;
|
||||||
|
break;
|
||||||
|
case BlockValidationResult::CACHED_INVALID:
|
||||||
|
std::cout << "this block was cached as being invalid and we didn't store the reason why" << std::endl;
|
||||||
|
break;
|
||||||
|
case BlockValidationResult::INVALID_HEADER:
|
||||||
|
std::cout << "invalid proof of work or time too old" << std::endl;
|
||||||
|
break;
|
||||||
|
case BlockValidationResult::MUTATED:
|
||||||
|
std::cout << "the block's data didn't match the data committed to by the PoW" << std::endl;
|
||||||
|
break;
|
||||||
|
case BlockValidationResult::MISSING_PREV:
|
||||||
|
std::cout << "We don't have the previous block the checked one is built on" << std::endl;
|
||||||
|
break;
|
||||||
|
case BlockValidationResult::INVALID_PREV:
|
||||||
|
std::cout << "A block this one builds on is invalid" << std::endl;
|
||||||
|
break;
|
||||||
|
case BlockValidationResult::TIME_FUTURE:
|
||||||
|
std::cout << "block timestamp was > 2 hours in the future (or our clock is bad)" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case ValidationMode::INTERNAL_ERROR: {
|
||||||
|
std::cout << "Internal error" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockConnected(Block block, BlockTreeEntry entry) override
|
void BlockConnected(Block block, BlockTreeEntry entry) override
|
||||||
|
|||||||
Reference in new issue
Block a user