kernel: Add support for block headers

Introduces btck_BlockHeader type with accessor methods and btck_chainstate_manager_process_block_header() for validating headers without full blocks. Also, adds btck_chainstate_manager_get_best_entry() to query the header with most cumulative proof-of-work.

Co-authored-by: TheCharlatan <seb.kung@gmail.com>
This commit is contained in:
yuvicc
2025-11-18 19:37:40 +05:30
parent b851ff6cae
commit 9a9d797ef6
4 changed files with 370 additions and 0 deletions

View File

@@ -496,6 +496,7 @@ struct btck_TransactionInput : Handle<btck_TransactionInput, CTxIn> {};
struct btck_TransactionOutPoint: Handle<btck_TransactionOutPoint, COutPoint> {};
struct btck_Txid: Handle<btck_Txid, Txid> {};
struct btck_PrecomputedTransactionData : Handle<btck_PrecomputedTransactionData, PrecomputedTransactionData> {};
struct btck_BlockHeader: Handle<btck_BlockHeader, CBlockHeader> {};
btck_Transaction* btck_transaction_create(const void* raw_transaction, size_t raw_transaction_len)
{
@@ -1044,6 +1045,12 @@ const btck_BlockTreeEntry* btck_chainstate_manager_get_block_tree_entry_by_hash(
return btck_BlockTreeEntry::ref(block_index);
}
const btck_BlockTreeEntry* btck_chainstate_manager_get_best_entry(const btck_ChainstateManager* chainstate_manager)
{
auto& chainman = *btck_ChainstateManager::get(chainstate_manager).m_chainman;
return btck_BlockTreeEntry::ref(WITH_LOCK(chainman.GetMutex(), return chainman.m_best_header));
}
void btck_chainstate_manager_destroy(btck_ChainstateManager* chainman)
{
{
@@ -1112,6 +1119,12 @@ const btck_Transaction* btck_block_get_transaction_at(const btck_Block* block, s
return btck_Transaction::ref(&btck_Block::get(block)->vtx[index]);
}
btck_BlockHeader* btck_block_get_header(const btck_Block* block)
{
const auto& block_ptr = btck_Block::get(block);
return btck_BlockHeader::create(static_cast<const CBlockHeader&>(*block_ptr));
}
int btck_block_to_bytes(const btck_Block* block, btck_WriteBytes writer, void* user_data)
{
try {
@@ -1143,6 +1156,11 @@ btck_Block* btck_block_read(const btck_ChainstateManager* chainman, const btck_B
return btck_Block::create(block);
}
btck_BlockHeader* btck_block_tree_entry_get_block_header(const btck_BlockTreeEntry* entry)
{
return btck_BlockHeader::create(btck_BlockTreeEntry::get(entry).GetBlockHeader());
}
int32_t btck_block_tree_entry_get_height(const btck_BlockTreeEntry* entry)
{
return btck_BlockTreeEntry::get(entry).nHeight;
@@ -1279,6 +1297,22 @@ int btck_chainstate_manager_process_block(
return result ? 0 : -1;
}
int btck_chainstate_manager_process_block_header(
btck_ChainstateManager* chainstate_manager,
const btck_BlockHeader* header,
btck_BlockValidationState* state)
{
try {
auto& chainman = btck_ChainstateManager::get(chainstate_manager).m_chainman;
auto result = chainman->ProcessNewBlockHeaders({&btck_BlockHeader::get(header), 1}, /*min_pow_checked=*/true, btck_BlockValidationState::get(state), /*ppindex=*/nullptr);
return result ? 0 : -1;
} catch (const std::exception& e) {
LogError("Failed to process block header: %s", e.what());
return -1;
}
}
const btck_Chain* btck_chainstate_manager_get_active_chain(const btck_ChainstateManager* chainman)
{
return btck_Chain::ref(&WITH_LOCK(btck_ChainstateManager::get(chainman).m_chainman->GetMutex(), return btck_ChainstateManager::get(chainman).m_chainman->ActiveChain()));
@@ -1301,3 +1335,61 @@ int btck_chain_contains(const btck_Chain* chain, const btck_BlockTreeEntry* entr
LOCK(::cs_main);
return btck_Chain::get(chain).Contains(&btck_BlockTreeEntry::get(entry)) ? 1 : 0;
}
btck_BlockHeader* btck_block_header_create(const void* raw_block_header, size_t raw_block_header_len)
{
if (raw_block_header == nullptr && raw_block_header_len != 0) {
return nullptr;
}
auto header{std::make_unique<CBlockHeader>()};
DataStream stream{std::span{reinterpret_cast<const std::byte*>(raw_block_header), raw_block_header_len}};
try {
stream >> *header;
} catch (...) {
LogError("Block header decode failed.");
return nullptr;
}
return btck_BlockHeader::ref(header.release());
}
btck_BlockHeader* btck_block_header_copy(const btck_BlockHeader* header)
{
return btck_BlockHeader::copy(header);
}
btck_BlockHash* btck_block_header_get_hash(const btck_BlockHeader* header)
{
return btck_BlockHash::create(btck_BlockHeader::get(header).GetHash());
}
const btck_BlockHash* btck_block_header_get_prev_hash(const btck_BlockHeader* header)
{
return btck_BlockHash::ref(&btck_BlockHeader::get(header).hashPrevBlock);
}
uint32_t btck_block_header_get_timestamp(const btck_BlockHeader* header)
{
return btck_BlockHeader::get(header).nTime;
}
uint32_t btck_block_header_get_bits(const btck_BlockHeader* header)
{
return btck_BlockHeader::get(header).nBits;
}
int32_t btck_block_header_get_version(const btck_BlockHeader* header)
{
return btck_BlockHeader::get(header).nVersion;
}
uint32_t btck_block_header_get_nonce(const btck_BlockHeader* header)
{
return btck_BlockHeader::get(header).nNonce;
}
void btck_block_header_destroy(btck_BlockHeader* header)
{
delete header;
}