Reuse RandomX hashing context during mining
This commit is contained in:
parent
b46ce28c09
commit
fbac0a9d47
5 changed files with 126 additions and 22 deletions
|
|
@ -2,6 +2,77 @@
|
||||||
|
|
||||||
#include <randomx.h>
|
#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(
|
bool VextaRandomXHash(
|
||||||
const void* input,
|
const void* input,
|
||||||
std::size_t input_size,
|
std::size_t input_size,
|
||||||
|
|
@ -9,27 +80,11 @@ bool VextaRandomXHash(
|
||||||
std::size_t key_size,
|
std::size_t key_size,
|
||||||
uint8_t output[VEXTA_RANDOMX_HASH_SIZE])
|
uint8_t output[VEXTA_RANDOMX_HASH_SIZE])
|
||||||
{
|
{
|
||||||
randomx_cache* cache = randomx_alloc_cache(RANDOMX_FLAG_DEFAULT);
|
VextaRandomXHasher hasher(key, key_size);
|
||||||
if (cache == nullptr) {
|
|
||||||
|
if (!hasher.IsValid()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
randomx_init_cache(cache, key, key_size);
|
return hasher.Hash(input, input_size, output);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,31 @@
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
static constexpr std::size_t VEXTA_RANDOMX_HASH_SIZE = 32;
|
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.
|
* Calculate a RandomX hash using an explicit key.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -33,15 +33,26 @@ int CBlockHeader::GetAlgo() const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBlockHeader::GetRandomXPoWHash(const uint256& seed, uint256& result) 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);
|
CDataStream stream(SER_GETHASH, PROTOCOL_VERSION);
|
||||||
stream << *this;
|
stream << *this;
|
||||||
|
|
||||||
return VextaRandomXHash(
|
return hasher.Hash(
|
||||||
stream.data(),
|
stream.data(),
|
||||||
stream.size(),
|
stream.size(),
|
||||||
seed.data(),
|
|
||||||
seed.size(),
|
|
||||||
result.begin());
|
result.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
* in the block is a special one that creates a new coin owned by the creator
|
||||||
* of the block.
|
* of the block.
|
||||||
*/
|
*/
|
||||||
|
class VextaRandomXHasher;
|
||||||
|
|
||||||
class CBlockHeader
|
class CBlockHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -101,6 +103,7 @@ public:
|
||||||
* The seed is supplied in raw uint256 serialization byte order.
|
* The seed is supplied in raw uint256 serialization byte order.
|
||||||
*/
|
*/
|
||||||
bool GetRandomXPoWHash(const uint256& seed, uint256& result) const;
|
bool GetRandomXPoWHash(const uint256& seed, uint256& result) const;
|
||||||
|
bool GetRandomXPoWHash(VextaRandomXHasher& hasher, uint256& result) const;
|
||||||
|
|
||||||
int64_t GetBlockTime() const
|
int64_t GetBlockTime() const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <consensus/params.h>
|
#include <consensus/params.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
#include <core_io.h>
|
#include <core_io.h>
|
||||||
|
#include <crypto/randomx_hash.h>
|
||||||
#include <deploymentinfo.h>
|
#include <deploymentinfo.h>
|
||||||
#include <deploymentstatus.h>
|
#include <deploymentstatus.h>
|
||||||
#include <key_io.h>
|
#include <key_io.h>
|
||||||
|
|
@ -200,6 +201,8 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t&
|
||||||
const int algo = block.GetAlgo();
|
const int algo = block.GetAlgo();
|
||||||
|
|
||||||
uint256 randomx_seed;
|
uint256 randomx_seed;
|
||||||
|
std::unique_ptr<VextaRandomXHasher> randomx_hasher;
|
||||||
|
|
||||||
if (algo == ALGO_RANDOMX) {
|
if (algo == ALGO_RANDOMX) {
|
||||||
if (pindexPrev == nullptr ||
|
if (pindexPrev == nullptr ||
|
||||||
!GetRandomXSeed(
|
!GetRandomXSeed(
|
||||||
|
|
@ -211,6 +214,16 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t&
|
||||||
RPC_INTERNAL_ERROR,
|
RPC_INTERNAL_ERROR,
|
||||||
"Failed to resolve RandomX seed");
|
"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) {
|
} else if (algo != ALGO_SHA256D) {
|
||||||
throw JSONRPCError(
|
throw JSONRPCError(
|
||||||
RPC_INVALID_PARAMETER,
|
RPC_INVALID_PARAMETER,
|
||||||
|
|
@ -225,7 +238,7 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t&
|
||||||
if (algo == ALGO_SHA256D) {
|
if (algo == ALGO_SHA256D) {
|
||||||
pow_hash = block.GetHash();
|
pow_hash = block.GetHash();
|
||||||
} else {
|
} else {
|
||||||
if (!block.GetRandomXPoWHash(randomx_seed, pow_hash)) {
|
if (!block.GetRandomXPoWHash(*randomx_hasher, pow_hash)) {
|
||||||
throw JSONRPCError(
|
throw JSONRPCError(
|
||||||
RPC_INTERNAL_ERROR,
|
RPC_INTERNAL_ERROR,
|
||||||
"Failed to calculate RandomX proof of work hash");
|
"Failed to calculate RandomX proof of work hash");
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue