Reuse RandomX hashing context during mining

This commit is contained in:
Capri 2026-09-16 21:53:20 +00:00
commit fbac0a9d47
Signed by: VextaProject
SSH key fingerprint: SHA256:739BZv8LvIDY2tR7lXLy/IQ6MaGTQtYcG9GNvCjmpVM
5 changed files with 126 additions and 22 deletions

View file

@ -2,6 +2,77 @@
#include <randomx.h>
struct VextaRandomXHasher::Impl
{
randomx_cache* cache{nullptr};
randomx_vm* vm{nullptr};
Impl(const void* key, std::size_t key_size)
{
cache = randomx_alloc_cache(RANDOMX_FLAG_DEFAULT);
if (cache == nullptr) {
return;
}
randomx_init_cache(cache, key, key_size);
vm = randomx_create_vm(
RANDOMX_FLAG_DEFAULT,
cache,
nullptr);
if (vm == nullptr) {
randomx_release_cache(cache);
cache = nullptr;
}
}
~Impl()
{
if (vm != nullptr) {
randomx_destroy_vm(vm);
}
if (cache != nullptr) {
randomx_release_cache(cache);
}
}
};
VextaRandomXHasher::VextaRandomXHasher(
const void* key,
std::size_t key_size)
: m_impl(std::make_unique<Impl>(key, key_size))
{
}
VextaRandomXHasher::~VextaRandomXHasher() = default;
bool VextaRandomXHasher::IsValid() const
{
return m_impl != nullptr &&
m_impl->cache != nullptr &&
m_impl->vm != nullptr;
}
bool VextaRandomXHasher::Hash(
const void* input,
std::size_t input_size,
uint8_t output[VEXTA_RANDOMX_HASH_SIZE])
{
if (!IsValid()) {
return false;
}
randomx_calculate_hash(
m_impl->vm,
input,
input_size,
output);
return true;
}
bool VextaRandomXHash(
const void* input,
std::size_t input_size,
@ -9,27 +80,11 @@ bool VextaRandomXHash(
std::size_t key_size,
uint8_t output[VEXTA_RANDOMX_HASH_SIZE])
{
randomx_cache* cache = randomx_alloc_cache(RANDOMX_FLAG_DEFAULT);
if (cache == nullptr) {
VextaRandomXHasher hasher(key, key_size);
if (!hasher.IsValid()) {
return false;
}
randomx_init_cache(cache, key, key_size);
randomx_vm* vm = randomx_create_vm(
RANDOMX_FLAG_DEFAULT,
cache,
nullptr);
if (vm == nullptr) {
randomx_release_cache(cache);
return false;
}
randomx_calculate_hash(vm, input, input_size, output);
randomx_destroy_vm(vm);
randomx_release_cache(cache);
return true;
return hasher.Hash(input, input_size, output);
}

View file

@ -3,9 +3,31 @@
#include <cstddef>
#include <cstdint>
#include <memory>
static constexpr std::size_t VEXTA_RANDOMX_HASH_SIZE = 32;
class VextaRandomXHasher
{
public:
VextaRandomXHasher(const void* key, std::size_t key_size);
~VextaRandomXHasher();
VextaRandomXHasher(const VextaRandomXHasher&) = delete;
VextaRandomXHasher& operator=(const VextaRandomXHasher&) = delete;
bool IsValid() const;
bool Hash(
const void* input,
std::size_t input_size,
uint8_t output[VEXTA_RANDOMX_HASH_SIZE]);
private:
struct Impl;
std::unique_ptr<Impl> m_impl;
};
/**
* Calculate a RandomX hash using an explicit key.
*

View file

@ -33,15 +33,26 @@ int CBlockHeader::GetAlgo() const
}
bool CBlockHeader::GetRandomXPoWHash(const uint256& seed, uint256& result) const
{
VextaRandomXHasher hasher(seed.data(), seed.size());
if (!hasher.IsValid()) {
return false;
}
return GetRandomXPoWHash(hasher, result);
}
bool CBlockHeader::GetRandomXPoWHash(
VextaRandomXHasher& hasher,
uint256& result) const
{
CDataStream stream(SER_GETHASH, PROTOCOL_VERSION);
stream << *this;
return VextaRandomXHash(
return hasher.Hash(
stream.data(),
stream.size(),
seed.data(),
seed.size(),
result.begin());
}

View file

@ -51,6 +51,8 @@ inline int GetVersionForAlgo(int algo)
* in the block is a special one that creates a new coin owned by the creator
* of the block.
*/
class VextaRandomXHasher;
class CBlockHeader
{
public:
@ -101,6 +103,7 @@ public:
* The seed is supplied in raw uint256 serialization byte order.
*/
bool GetRandomXPoWHash(const uint256& seed, uint256& result) const;
bool GetRandomXPoWHash(VextaRandomXHasher& hasher, uint256& result) const;
int64_t GetBlockTime() const
{

View file

@ -11,6 +11,7 @@
#include <consensus/params.h>
#include <consensus/validation.h>
#include <core_io.h>
#include <crypto/randomx_hash.h>
#include <deploymentinfo.h>
#include <deploymentstatus.h>
#include <key_io.h>
@ -200,6 +201,8 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t&
const int algo = block.GetAlgo();
uint256 randomx_seed;
std::unique_ptr<VextaRandomXHasher> randomx_hasher;
if (algo == ALGO_RANDOMX) {
if (pindexPrev == nullptr ||
!GetRandomXSeed(
@ -211,6 +214,16 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t&
RPC_INTERNAL_ERROR,
"Failed to resolve RandomX seed");
}
randomx_hasher = std::make_unique<VextaRandomXHasher>(
randomx_seed.data(),
randomx_seed.size());
if (!randomx_hasher->IsValid()) {
throw JSONRPCError(
RPC_INTERNAL_ERROR,
"Failed to initialize RandomX hasher");
}
} else if (algo != ALGO_SHA256D) {
throw JSONRPCError(
RPC_INVALID_PARAMETER,
@ -225,7 +238,7 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t&
if (algo == ALGO_SHA256D) {
pow_hash = block.GetHash();
} else {
if (!block.GetRandomXPoWHash(randomx_seed, pow_hash)) {
if (!block.GetRandomXPoWHash(*randomx_hasher, pow_hash)) {
throw JSONRPCError(
RPC_INTERNAL_ERROR,
"Failed to calculate RandomX proof of work hash");