mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-03-25 15:05:55 +01:00
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:
@@ -769,6 +769,40 @@ void btck_context_destroy(btck_Context* 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)
|
||||
{
|
||||
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_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
|
||||
* 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
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
@@ -58,6 +58,24 @@ enum class Warning : btck_Warning {
|
||||
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 {
|
||||
OK = btck_ScriptVerifyStatus_OK,
|
||||
ERROR_INVALID_FLAGS_COMBINATION = btck_ScriptVerifyStatus_ERROR_INVALID_FLAGS_COMBINATION,
|
||||
@@ -616,6 +634,16 @@ public:
|
||||
BlockValidationState& operator=(const BlockValidationState&) = delete;
|
||||
BlockValidationState(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
|
||||
|
||||
@@ -131,7 +131,53 @@ class TestValidationInterface : public ValidationInterface
|
||||
public:
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user