Skip to content

Commit

Permalink
kernel: Add functions to get the block hash from a block
Browse files Browse the repository at this point in the history
This is useful for a host block processing feature where having an
identifier for the block is needed. Without this, external users need to
serialize the block and calculate the hash externally, which is less
efficient.
  • Loading branch information
TheCharlatan committed Jan 15, 2025
1 parent 1bf825f commit a58bbe6
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 8 deletions.
18 changes: 18 additions & 0 deletions src/kernel/bitcoinkernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,24 @@ kernel_ByteArray* kernel_copy_block_pointer_data(const kernel_BlockPointer* bloc
return byte_array;
}

kernel_BlockHash* kernel_block_get_hash(kernel_Block* block_)
{
auto block{cast_cblocksharedpointer(block_)};
auto hash{(*block)->GetHash()};
auto block_hash = new kernel_BlockHash{};
std::memcpy(block_hash->hash, hash.begin(), sizeof(hash));
return block_hash;
}

kernel_BlockHash* kernel_block_pointer_get_hash(const kernel_BlockPointer* block_)
{
auto block{cast_const_cblock(block_)};
auto hash{block->GetHash()};
auto block_hash = new kernel_BlockHash{};
std::memcpy(block_hash->hash, hash.begin(), sizeof(hash));
return block_hash;
}

void kernel_block_destroy(kernel_Block* block)
{
if (block) {
Expand Down
20 changes: 20 additions & 0 deletions src/kernel/bitcoinkernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,26 @@ kernel_Block* BITCOINKERNEL_WARN_UNUSED_RESULT kernel_block_create(
const unsigned char* raw_block, size_t raw_block_len
) BITCOINKERNEL_ARG_NONNULL(1);

/**
* @brief Calculate and return the hash of a block.
*
* @param[in] block Non-null.
* @return The block hash.
*/
kernel_BlockHash* BITCOINKERNEL_WARN_UNUSED_RESULT kernel_block_get_hash(
kernel_Block* block
) BITCOINKERNEL_ARG_NONNULL(1);

/** @name ByteArray
* @brief Calculate and return the hash of a block.
*
* @param[in] block Non-null.
* @return The block hash.
*/
kernel_BlockHash* BITCOINKERNEL_WARN_UNUSED_RESULT kernel_block_pointer_get_hash(
const kernel_BlockPointer* block
) BITCOINKERNEL_ARG_NONNULL(1);

/**
* @brief Copies block data into the returned byte array.
*
Expand Down
24 changes: 17 additions & 7 deletions src/kernel/bitcoinkernel_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,13 @@ class KernelNotifications
friend class ContextOptions;
};

struct BlockHashDeleter {
void operator()(kernel_BlockHash* ptr) const
{
kernel_block_hash_destroy(ptr);
}
};

class UnownedBlock
{
private:
Expand All @@ -232,6 +239,11 @@ class UnownedBlock
UnownedBlock(UnownedBlock&&) = delete;
UnownedBlock& operator=(UnownedBlock&&) = delete;

std::unique_ptr<kernel_BlockHash, BlockHashDeleter> GetHash() const noexcept
{
return std::unique_ptr<kernel_BlockHash, BlockHashDeleter>(kernel_block_pointer_get_hash(m_block));
}

std::vector<unsigned char> GetBlockData() const noexcept
{
auto serialized_block{kernel_copy_block_pointer_data(m_block)};
Expand Down Expand Up @@ -485,6 +497,11 @@ class Block

Block(kernel_Block* block) noexcept : m_block{block} {}

std::unique_ptr<kernel_BlockHash, BlockHashDeleter> GetHash() const noexcept
{
return std::unique_ptr<kernel_BlockHash, BlockHashDeleter>(kernel_block_get_hash(m_block.get()));
}

std::vector<unsigned char> GetBlockData() const noexcept
{
auto serialized_block{kernel_copy_block_data(m_block.get())};
Expand Down Expand Up @@ -533,13 +550,6 @@ class BlockUndo
}
};

struct BlockHashDeleter {
void operator()(kernel_BlockHash* ptr) const
{
kernel_block_hash_destroy(ptr);
}
};

class BlockIndex
{
private:
Expand Down
5 changes: 4 additions & 1 deletion src/test/kernel/test_kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,8 @@ void chainman_reindex_test(TestDirectory& test_directory)
auto tip_index{chainman->GetBlockIndexFromTip()};
auto tip_block_string{chainman->ReadBlock(tip_index).value().GetBlockData()};
auto second_index{chainman->GetBlockIndexByHeight(1).value()};
auto second_block_string{chainman->ReadBlock(second_index).value().GetBlockData()};
auto second_block{chainman->ReadBlock(second_index).value()};
auto second_block_string{second_block.GetBlockData()};
auto second_height{second_index.GetHeight()};
assert(second_height == 1);
assert(next_block_string == tip_block_string);
Expand All @@ -578,6 +579,8 @@ void chainman_reindex_test(TestDirectory& test_directory)
auto hash{second_index.GetHash()};
auto another_second_index{chainman->GetBlockIndexByHash(hash.get())};
auto another_second_height{another_second_index.GetHeight()};
auto block_hash{second_block.GetHash()};
assert(std::equal(std::begin(block_hash->hash), std::end(block_hash->hash), std::begin(hash->hash)));
assert(second_height == another_second_height);
}

Expand Down

0 comments on commit a58bbe6

Please sign in to comment.