mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-15 01:58:09 +02:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user