mirror of
https://github.com/oxen-io/oxen-core.git
synced 2023-12-14 02:22:56 +01:00
Updated RandomX integration from upstream
Support RandomX PoW algorithm
This commit is contained in:
parent
f0ab90e99e
commit
3b8dd4b25b
|
@ -500,7 +500,10 @@ static bool mlog(el::Level level, const char *category, const char *format, va_l
|
|||
|
||||
try
|
||||
{
|
||||
/* TODO(loki): when pulling upstream epee changes change this to:
|
||||
MCLOG(level, category, el::Color::Default, p);
|
||||
*/
|
||||
MCLOG(level, category, p);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
|
|
@ -75,8 +75,5 @@ void rx_slow_hash_allocate_state(void);
|
|||
void rx_slow_hash_free_state(void);
|
||||
uint64_t rx_seedheight(const uint64_t height);
|
||||
void rx_seedheights(const uint64_t height, uint64_t *seed_height, uint64_t *next_height);
|
||||
bool rx_needhash(const uint64_t height, uint64_t *seedheight);
|
||||
void rx_seedhash(const uint64_t seedheight, const char *hash, const int miners);
|
||||
void rx_slow_hash(const void *data, size_t length, char *hash, const int miners);
|
||||
void rx_alt_slowhash(const uint64_t mainheight, const uint64_t seedheight, const char *seedhash, const void *data, size_t length, char *hash);
|
||||
void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const char *seedhash, const void *data, size_t length, char *hash, int miners, int is_alt);
|
||||
void rx_reorg(const uint64_t split_height);
|
||||
|
|
|
@ -38,6 +38,9 @@
|
|||
#include "randomx.h"
|
||||
#include "c_threads.h"
|
||||
#include "hash-ops.h"
|
||||
#include "misc_log_ex.h"
|
||||
|
||||
#define RX_LOGCAT "randomx"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define THREADV __declspec(thread)
|
||||
|
@ -45,18 +48,22 @@
|
|||
#define THREADV __thread
|
||||
#endif
|
||||
|
||||
static CTHR_MUTEX_TYPE rx_mutex = CTHR_MUTEX_INIT;
|
||||
|
||||
typedef struct rx_state {
|
||||
volatile uint64_t rs_height;
|
||||
CTHR_MUTEX_TYPE rs_mutex;
|
||||
char rs_hash[32];
|
||||
uint64_t rs_height;
|
||||
randomx_cache *rs_cache;
|
||||
} rx_state;
|
||||
|
||||
static rx_state rx_s[2];
|
||||
static CTHR_MUTEX_TYPE rx_mutex = CTHR_MUTEX_INIT;
|
||||
static CTHR_MUTEX_TYPE rx_dataset_mutex = CTHR_MUTEX_INIT;
|
||||
|
||||
static rx_state rx_s[2] = {{CTHR_MUTEX_INIT,{0},0,0},{CTHR_MUTEX_INIT,{0},0,0}};
|
||||
|
||||
static randomx_dataset *rx_dataset;
|
||||
THREADV int rx_s_toggle;
|
||||
THREADV randomx_vm *rx_vm = NULL;
|
||||
static uint64_t rx_dataset_height;
|
||||
static THREADV randomx_vm *rx_vm = NULL;
|
||||
static THREADV int rx_toggle;
|
||||
|
||||
static void local_abort(const char *msg)
|
||||
{
|
||||
|
@ -93,9 +100,9 @@ static inline int force_software_aes(void)
|
|||
return use;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
static void cpuid(int CPUInfo[4], int InfoType)
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
__asm __volatile__
|
||||
(
|
||||
"cpuid":
|
||||
|
@ -105,9 +112,8 @@ static void cpuid(int CPUInfo[4], int InfoType)
|
|||
"=d" (CPUInfo[3]) :
|
||||
"a" (InfoType), "c" (0)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
static inline int check_aes_hw(void)
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
|
@ -173,22 +179,6 @@ void rx_seedheights(const uint64_t height, uint64_t *seedheight, uint64_t *nexth
|
|||
*nextheight = rx_seedheight(height + SEEDHASH_EPOCH_LAG);
|
||||
}
|
||||
|
||||
bool rx_needhash(const uint64_t height, uint64_t *seedheight) {
|
||||
rx_state *rx_sp;
|
||||
uint64_t s_height = rx_seedheight(height);
|
||||
int toggle = (s_height & SEEDHASH_EPOCH_BLOCKS) != 0;
|
||||
bool ret;
|
||||
bool changed = (toggle != rx_s_toggle);
|
||||
*seedheight = s_height;
|
||||
rx_s_toggle = toggle;
|
||||
rx_sp = &rx_s[rx_s_toggle];
|
||||
ret = (rx_sp->rs_cache == NULL) || (rx_sp->rs_height != s_height);
|
||||
/* if cache is ok but we've flipped caches, reset vm */
|
||||
if (!ret && changed && rx_vm != NULL)
|
||||
randomx_vm_set_cache(rx_vm, rx_sp->rs_cache);
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct seedinfo {
|
||||
randomx_cache *si_cache;
|
||||
unsigned long si_start;
|
||||
|
@ -201,7 +191,7 @@ static CTHR_THREAD_RTYPE rx_seedthread(void *arg) {
|
|||
CTHR_THREAD_RETURN;
|
||||
}
|
||||
|
||||
static void rx_initdata(randomx_cache *rs_cache, const int miners) {
|
||||
static void rx_initdata(randomx_cache *rs_cache, const int miners, const uint64_t seedheight) {
|
||||
if (miners > 1) {
|
||||
unsigned long delta = randomx_dataset_item_count() / miners;
|
||||
unsigned long start = 0;
|
||||
|
@ -237,106 +227,113 @@ static void rx_initdata(randomx_cache *rs_cache, const int miners) {
|
|||
} else {
|
||||
randomx_init_dataset(rx_dataset, rs_cache, 0, randomx_dataset_item_count());
|
||||
}
|
||||
rx_dataset_height = seedheight;
|
||||
}
|
||||
|
||||
static void rx_seedhash_int(rx_state *rx_sp, const uint64_t height, const char *hash, const int miners) {
|
||||
void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const char *seedhash, const void *data, size_t length,
|
||||
char *hash, int miners, int is_alt) {
|
||||
uint64_t s_height = rx_seedheight(mainheight);
|
||||
int changed = 0;
|
||||
int toggle = is_alt ? s_height : seedheight;
|
||||
randomx_flags flags = RANDOMX_FLAG_DEFAULT;
|
||||
rx_state *rx_sp;
|
||||
randomx_cache *cache;
|
||||
|
||||
toggle = (toggle & SEEDHASH_EPOCH_BLOCKS) != 0;
|
||||
CTHR_MUTEX_LOCK(rx_mutex);
|
||||
|
||||
/* if alt block but with same seed as mainchain, no need for alt cache */
|
||||
if (is_alt && s_height == seedheight && !memcmp(rx_s[toggle].rs_hash, seedhash, sizeof(rx_s[toggle].rs_hash)))
|
||||
is_alt = 0;
|
||||
|
||||
/* RPC could request an earlier block on mainchain */
|
||||
if (!is_alt && s_height > seedheight)
|
||||
is_alt = 1;
|
||||
|
||||
toggle ^= (is_alt != 0);
|
||||
if (toggle != rx_toggle)
|
||||
changed = 1;
|
||||
rx_toggle = toggle;
|
||||
|
||||
rx_sp = &rx_s[toggle];
|
||||
CTHR_MUTEX_LOCK(rx_sp->rs_mutex);
|
||||
CTHR_MUTEX_UNLOCK(rx_mutex);
|
||||
|
||||
cache = rx_sp->rs_cache;
|
||||
if (rx_sp->rs_height != height || cache == NULL) {
|
||||
if (cache == NULL) {
|
||||
if (use_rx_jit())
|
||||
flags |= RANDOMX_FLAG_JIT;
|
||||
if (cache == NULL) {
|
||||
cache = randomx_alloc_cache(flags | RANDOMX_FLAG_LARGE_PAGES);
|
||||
if (cache == NULL)
|
||||
if (cache == NULL) {
|
||||
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX cache");
|
||||
cache = randomx_alloc_cache(flags);
|
||||
}
|
||||
if (cache == NULL)
|
||||
local_abort("Couldn't allocate RandomX cache");
|
||||
}
|
||||
randomx_init_cache(cache, hash, 32);
|
||||
if (miners && rx_dataset != NULL)
|
||||
rx_initdata(cache, miners);
|
||||
rx_sp->rs_height = height;
|
||||
if (rx_sp->rs_cache == NULL)
|
||||
rx_sp->rs_cache = cache;
|
||||
}
|
||||
CTHR_MUTEX_UNLOCK(rx_mutex);
|
||||
if (rx_vm != NULL)
|
||||
randomx_vm_set_cache(rx_vm, rx_sp->rs_cache);
|
||||
}
|
||||
|
||||
void rx_seedhash(const uint64_t height, const char *hash, const int miners) {
|
||||
rx_state *rx_sp = &rx_s[rx_s_toggle];
|
||||
rx_seedhash_int(rx_sp, height, hash, miners);
|
||||
}
|
||||
|
||||
static char rx_althash[32]; // seedhash for alternate blocks
|
||||
|
||||
void rx_alt_slowhash(const uint64_t mainheight, const uint64_t seedheight, const char *seedhash, const void *data, size_t length, char *hash) {
|
||||
uint64_t s_height = rx_seedheight(mainheight);
|
||||
int alt_toggle = (s_height & SEEDHASH_EPOCH_BLOCKS) == 0;
|
||||
rx_state *rx_sp = &rx_s[alt_toggle];
|
||||
if (rx_sp->rs_height != seedheight || rx_sp->rs_cache == NULL || memcmp(seedhash, rx_althash, sizeof(rx_althash))) {
|
||||
memcpy(rx_althash, seedhash, sizeof(rx_althash));
|
||||
rx_sp->rs_height = 1;
|
||||
rx_seedhash_int(rx_sp, seedheight, seedhash, 0);
|
||||
if (rx_sp->rs_height != seedheight || rx_sp->rs_cache == NULL || memcmp(seedhash, rx_sp->rs_hash, sizeof(rx_sp->rs_hash))) {
|
||||
randomx_init_cache(cache, seedhash, 32);
|
||||
rx_sp->rs_cache = cache;
|
||||
rx_sp->rs_height = seedheight;
|
||||
memcpy(rx_sp->rs_hash, seedhash, sizeof(rx_sp->rs_hash));
|
||||
changed = 1;
|
||||
}
|
||||
if (rx_vm == NULL) {
|
||||
randomx_flags flags = RANDOMX_FLAG_DEFAULT;
|
||||
if (use_rx_jit())
|
||||
if (use_rx_jit()) {
|
||||
flags |= RANDOMX_FLAG_JIT;
|
||||
if(!force_software_aes() && check_aes_hw())
|
||||
flags |= RANDOMX_FLAG_HARD_AES;
|
||||
rx_vm = randomx_create_vm(flags | RANDOMX_FLAG_LARGE_PAGES, rx_sp->rs_cache, NULL);
|
||||
if(rx_vm == NULL) //large pages failed
|
||||
rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, NULL);
|
||||
if(rx_vm == NULL) {//fallback if everything fails
|
||||
flags = RANDOMX_FLAG_DEFAULT;
|
||||
rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, NULL);
|
||||
if (!miners)
|
||||
flags |= RANDOMX_FLAG_SECURE;
|
||||
}
|
||||
if (rx_vm == NULL)
|
||||
local_abort("Couldn't allocate RandomX VM");
|
||||
}
|
||||
randomx_calculate_hash(rx_vm, data, length, hash);
|
||||
}
|
||||
|
||||
void rx_slow_hash(const void *data, size_t length, char *hash, int miners) {
|
||||
if (rx_vm == NULL) {
|
||||
rx_state *rx_sp = &rx_s[rx_s_toggle];
|
||||
randomx_flags flags = RANDOMX_FLAG_DEFAULT;
|
||||
if (use_rx_jit())
|
||||
flags |= RANDOMX_FLAG_JIT;
|
||||
if(!force_software_aes() && check_aes_hw())
|
||||
flags |= RANDOMX_FLAG_HARD_AES;
|
||||
if (miners) {
|
||||
CTHR_MUTEX_LOCK(rx_dataset_mutex);
|
||||
if (rx_dataset == NULL) {
|
||||
CTHR_MUTEX_LOCK(rx_mutex);
|
||||
rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES);
|
||||
if (rx_dataset == NULL) {
|
||||
rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES);
|
||||
if (rx_dataset == NULL)
|
||||
rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT);
|
||||
if (rx_dataset != NULL)
|
||||
rx_initdata(rx_sp->rs_cache, miners);
|
||||
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX dataset");
|
||||
rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT);
|
||||
}
|
||||
CTHR_MUTEX_UNLOCK(rx_mutex);
|
||||
if (rx_dataset != NULL)
|
||||
rx_initdata(rx_sp->rs_cache, miners, seedheight);
|
||||
}
|
||||
if (rx_dataset != NULL)
|
||||
flags |= RANDOMX_FLAG_FULL_MEM;
|
||||
else
|
||||
else {
|
||||
miners = 0;
|
||||
mwarning(RX_LOGCAT, "Couldn't allocate RandomX dataset for miner");
|
||||
}
|
||||
CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
|
||||
}
|
||||
rx_vm = randomx_create_vm(flags | RANDOMX_FLAG_LARGE_PAGES, rx_sp->rs_cache, rx_dataset);
|
||||
if(rx_vm == NULL) //large pages failed
|
||||
if(rx_vm == NULL) { //large pages failed
|
||||
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX VM");
|
||||
rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, rx_dataset);
|
||||
}
|
||||
if(rx_vm == NULL) {//fallback if everything fails
|
||||
flags = RANDOMX_FLAG_DEFAULT | (miners ? RANDOMX_FLAG_FULL_MEM : 0);
|
||||
rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, rx_dataset);
|
||||
}
|
||||
if (rx_vm == NULL)
|
||||
local_abort("Couldn't allocate RandomX VM");
|
||||
} else if (miners) {
|
||||
CTHR_MUTEX_LOCK(rx_dataset_mutex);
|
||||
if (rx_dataset != NULL && rx_dataset_height != seedheight)
|
||||
rx_initdata(cache, miners, seedheight);
|
||||
CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
|
||||
} else if (changed) {
|
||||
randomx_vm_set_cache(rx_vm, rx_sp->rs_cache);
|
||||
}
|
||||
/* mainchain users can run in parallel */
|
||||
if (!is_alt)
|
||||
CTHR_MUTEX_UNLOCK(rx_sp->rs_mutex);
|
||||
randomx_calculate_hash(rx_vm, data, length, hash);
|
||||
/* altchain slot users always get fully serialized */
|
||||
if (is_alt)
|
||||
CTHR_MUTEX_UNLOCK(rx_sp->rs_mutex);
|
||||
}
|
||||
|
||||
void rx_slow_hash_allocate_state(void) {
|
||||
|
@ -350,8 +347,11 @@ void rx_slow_hash_free_state(void) {
|
|||
}
|
||||
|
||||
void rx_stop_mining(void) {
|
||||
CTHR_MUTEX_LOCK(rx_dataset_mutex);
|
||||
if (rx_dataset != NULL) {
|
||||
randomx_release_dataset(rx_dataset);
|
||||
rx_dataset = NULL;
|
||||
randomx_dataset *rd = rx_dataset;
|
||||
rx_dataset = NULL;
|
||||
randomx_release_dataset(rd);
|
||||
}
|
||||
CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
|
||||
}
|
||||
|
|
|
@ -759,7 +759,7 @@ namespace cryptonote
|
|||
|
||||
block_sync_size = command_line::get_arg(vm, arg_block_sync_size);
|
||||
if (block_sync_size > BLOCKS_SYNCHRONIZING_MAX_COUNT)
|
||||
MERROR("Error --dblock-sync-size cannot be greater than " << BLOCKS_SYNCHRONIZING_MAX_COUNT);
|
||||
MERROR("Error --block-sync-size cannot be greater than " << BLOCKS_SYNCHRONIZING_MAX_COUNT);
|
||||
|
||||
MGINFO("Loading checkpoints");
|
||||
CHECK_AND_ASSERT_MES(update_checkpoints_from_json_file(), false, "One or more checkpoints loaded from json conflicted with existing checkpoints.");
|
||||
|
|
|
@ -980,10 +980,10 @@ namespace cryptonote
|
|||
void get_altblock_longhash(const block& b, crypto::hash& res, const uint64_t main_height, const uint64_t height, const uint64_t seed_height, const crypto::hash& seed_hash)
|
||||
{
|
||||
blobdata bd = get_block_hashing_blob(b);
|
||||
rx_alt_slowhash(main_height, seed_height, seed_hash.data, bd.data(), bd.size(), res.data);
|
||||
rx_slow_hash(main_height, seed_height, seed_hash.data, bd.data(), bd.size(), res.data, 0, 1);
|
||||
}
|
||||
|
||||
bool get_block_longhash(const Blockchain *pbc, const block &b, crypto::hash &res, const uint64_t height, const int miners)
|
||||
bool get_block_longhash(const Blockchain *pbc, const block& b, crypto::hash& res, const uint64_t height, const int miners)
|
||||
{
|
||||
const blobdata bd = get_block_hashing_blob(b);
|
||||
const uint8_t hf_version = b.major_version;
|
||||
|
@ -994,16 +994,20 @@ namespace cryptonote
|
|||
#endif
|
||||
|
||||
if (hf_version >= network_version_12_checkpointing) {
|
||||
uint64_t seed_height;
|
||||
if (rx_needhash(height, &seed_height)) {
|
||||
crypto::hash hash;
|
||||
if (pbc != NULL)
|
||||
hash = pbc->get_pending_block_id_by_height(seed_height);
|
||||
else
|
||||
memset(&hash, 0, sizeof(hash)); // only happens when generating genesis block
|
||||
rx_seedhash(seed_height, hash.data, miners);
|
||||
uint64_t seed_height, main_height;
|
||||
crypto::hash hash;
|
||||
if (pbc != NULL)
|
||||
{
|
||||
seed_height = rx_seedheight(height);
|
||||
hash = pbc->get_pending_block_id_by_height(seed_height);
|
||||
main_height = pbc->get_current_blockchain_height();
|
||||
} else
|
||||
{
|
||||
memset(&hash, 0, sizeof(hash)); // only happens when generating genesis block
|
||||
seed_height = 0;
|
||||
main_height = 0;
|
||||
}
|
||||
rx_slow_hash(bd.data(), bd.size(), res.data, miners);
|
||||
rx_slow_hash(main_height, seed_height, hash.data, bd.data(), bd.size(), res.data, miners, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -207,7 +207,8 @@ namespace cryptonote
|
|||
, uint32_t nonce
|
||||
);
|
||||
|
||||
bool get_block_longhash(const class Blockchain *pb, const block& b, crypto::hash& res, const uint64_t height, const int miners);
|
||||
class Blockchain;
|
||||
bool get_block_longhash(const Blockchain *pb, const block& b, crypto::hash& res, const uint64_t height, const int miners);
|
||||
void get_altblock_longhash(const block& b, crypto::hash& res, const uint64_t main_height, const uint64_t height,
|
||||
const uint64_t seed_height, const crypto::hash& seed_hash);
|
||||
crypto::hash get_block_longhash(const Blockchain *pb, const block& b, const uint64_t height, const int miners);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2014-2019, The Monero Project
|
||||
// Copyright (c) 2018, The Loki Project
|
||||
// Copyright (c) 2019, The Loki Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
@ -83,6 +83,9 @@ using namespace epee;
|
|||
|
||||
#include "miner.h"
|
||||
|
||||
extern "C" void rx_slow_hash_allocate_state();
|
||||
extern "C" void rx_slow_hash_free_state();
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
|
||||
|
@ -526,6 +529,7 @@ namespace cryptonote
|
|||
difficulty_type local_diff = 0;
|
||||
uint32_t local_template_ver = 0;
|
||||
block b;
|
||||
rx_slow_hash_allocate_state();
|
||||
++m_threads_active;
|
||||
while(!m_stop)
|
||||
{
|
||||
|
@ -598,6 +602,7 @@ namespace cryptonote
|
|||
++m_hashes;
|
||||
++m_total_hashes;
|
||||
}
|
||||
rx_slow_hash_free_state();
|
||||
MGINFO("Miner thread stopped ["<< th_local_index << "]");
|
||||
--m_threads_active;
|
||||
#if defined(LOKI_ENABLE_INTEGRATION_TEST_HOOKS)
|
||||
|
|
Loading…
Reference in a new issue