mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-09-03 10:22:09 +00:00
WIP: RandomX.
This commit is contained in:
parent
88e0725bd9
commit
ecbc9fec10
@ -370,6 +370,7 @@ libbitcoin_cnutils_a_SOURCES = \
|
|||||||
cn_utils/cryptonote_basic/account.cpp \
|
cn_utils/cryptonote_basic/account.cpp \
|
||||||
cn_utils/crypto/random.c \
|
cn_utils/crypto/random.c \
|
||||||
cn_utils/crypto/tree-hash.c \
|
cn_utils/crypto/tree-hash.c \
|
||||||
|
cn_utils/crypto/rx-slow-hash.c \
|
||||||
cn_utils/crypto/oaes_lib.c \
|
cn_utils/crypto/oaes_lib.c \
|
||||||
cn_utils/crypto/aesb.c \
|
cn_utils/crypto/aesb.c \
|
||||||
cn_utils/crypto/hash-extra-groestl.c \
|
cn_utils/crypto/hash-extra-groestl.c \
|
||||||
|
@ -87,3 +87,11 @@ void hash_extra_jh(const void *data, size_t length, char *hash);
|
|||||||
void hash_extra_skein(const void *data, size_t length, char *hash);
|
void hash_extra_skein(const void *data, size_t length, char *hash);
|
||||||
|
|
||||||
void tree_hash(const char (*hashes)[HASH_SIZE], size_t count, char *root_hash);
|
void tree_hash(const char (*hashes)[HASH_SIZE], size_t count, char *root_hash);
|
||||||
|
|
||||||
|
#define RX_BLOCK_VERSION 12
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
357
src/cn_utils/crypto/rx-slow-hash.c
Normal file
357
src/cn_utils/crypto/rx-slow-hash.c
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
// Copyright (c) 2019, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#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)
|
||||||
|
#else
|
||||||
|
#define THREADV __thread
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct rx_state {
|
||||||
|
CTHR_MUTEX_TYPE rs_mutex;
|
||||||
|
char rs_hash[32];
|
||||||
|
uint64_t rs_height;
|
||||||
|
randomx_cache *rs_cache;
|
||||||
|
} rx_state;
|
||||||
|
|
||||||
|
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;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s\n", msg);
|
||||||
|
#ifdef NDEBUG
|
||||||
|
_exit(1);
|
||||||
|
#else
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief uses cpuid to determine if the CPU supports the AES instructions
|
||||||
|
* @return true if the CPU supports AES, false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline int force_software_aes(void)
|
||||||
|
{
|
||||||
|
static int use = -1;
|
||||||
|
|
||||||
|
if (use != -1)
|
||||||
|
return use;
|
||||||
|
|
||||||
|
const char *env = getenv("MONERO_USE_SOFTWARE_AES");
|
||||||
|
if (!env) {
|
||||||
|
use = 0;
|
||||||
|
}
|
||||||
|
else if (!strcmp(env, "0") || !strcmp(env, "no")) {
|
||||||
|
use = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
use = 1;
|
||||||
|
}
|
||||||
|
return use;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpuid(int CPUInfo[4], int InfoType)
|
||||||
|
{
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
__asm __volatile__
|
||||||
|
(
|
||||||
|
"cpuid":
|
||||||
|
"=a" (CPUInfo[0]),
|
||||||
|
"=b" (CPUInfo[1]),
|
||||||
|
"=c" (CPUInfo[2]),
|
||||||
|
"=d" (CPUInfo[3]) :
|
||||||
|
"a" (InfoType), "c" (0)
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
static inline int check_aes_hw(void)
|
||||||
|
{
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
int cpuid_results[4];
|
||||||
|
static int supported = -1;
|
||||||
|
|
||||||
|
if(supported >= 0)
|
||||||
|
return supported;
|
||||||
|
|
||||||
|
cpuid(cpuid_results,1);
|
||||||
|
return supported = cpuid_results[2] & (1 << 25);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static volatile int use_rx_jit_flag = -1;
|
||||||
|
|
||||||
|
static inline int use_rx_jit(void)
|
||||||
|
{
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
|
||||||
|
if (use_rx_jit_flag != -1)
|
||||||
|
return use_rx_jit_flag;
|
||||||
|
|
||||||
|
const char *env = getenv("MONERO_USE_RX_JIT");
|
||||||
|
if (!env) {
|
||||||
|
use_rx_jit_flag = 1;
|
||||||
|
}
|
||||||
|
else if (!strcmp(env, "0") || !strcmp(env, "no")) {
|
||||||
|
use_rx_jit_flag = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
use_rx_jit_flag = 1;
|
||||||
|
}
|
||||||
|
return use_rx_jit_flag;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SEEDHASH_EPOCH_BLOCKS 2048 /* Must be same as BLOCKS_SYNCHRONIZING_MAX_COUNT in cryptonote_config.h */
|
||||||
|
#define SEEDHASH_EPOCH_LAG 64
|
||||||
|
|
||||||
|
void rx_reorg(const uint64_t split_height) {
|
||||||
|
int i;
|
||||||
|
CTHR_MUTEX_LOCK(rx_mutex);
|
||||||
|
for (i=0; i<2; i++) {
|
||||||
|
if (split_height < rx_s[i].rs_height)
|
||||||
|
rx_s[i].rs_height = 1; /* set to an invalid seed height */
|
||||||
|
}
|
||||||
|
CTHR_MUTEX_UNLOCK(rx_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t rx_seedheight(const uint64_t height) {
|
||||||
|
uint64_t s_height = (height <= SEEDHASH_EPOCH_BLOCKS+SEEDHASH_EPOCH_LAG) ? 0 :
|
||||||
|
(height - SEEDHASH_EPOCH_LAG - 1) & ~(SEEDHASH_EPOCH_BLOCKS-1);
|
||||||
|
return s_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rx_seedheights(const uint64_t height, uint64_t *seedheight, uint64_t *nextheight) {
|
||||||
|
*seedheight = rx_seedheight(height);
|
||||||
|
*nextheight = rx_seedheight(height + SEEDHASH_EPOCH_LAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct seedinfo {
|
||||||
|
randomx_cache *si_cache;
|
||||||
|
unsigned long si_start;
|
||||||
|
unsigned long si_count;
|
||||||
|
} seedinfo;
|
||||||
|
|
||||||
|
static CTHR_THREAD_RTYPE rx_seedthread(void *arg) {
|
||||||
|
seedinfo *si = arg;
|
||||||
|
randomx_init_dataset(rx_dataset, si->si_cache, si->si_start, si->si_count);
|
||||||
|
CTHR_THREAD_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
int i;
|
||||||
|
seedinfo *si;
|
||||||
|
CTHR_THREAD_TYPE *st;
|
||||||
|
si = malloc(miners * sizeof(seedinfo));
|
||||||
|
if (si == NULL)
|
||||||
|
local_abort("Couldn't allocate RandomX mining threadinfo");
|
||||||
|
st = malloc(miners * sizeof(CTHR_THREAD_TYPE));
|
||||||
|
if (st == NULL) {
|
||||||
|
free(si);
|
||||||
|
local_abort("Couldn't allocate RandomX mining threadlist");
|
||||||
|
}
|
||||||
|
for (i=0; i<miners-1; i++) {
|
||||||
|
si[i].si_cache = rs_cache;
|
||||||
|
si[i].si_start = start;
|
||||||
|
si[i].si_count = delta;
|
||||||
|
start += delta;
|
||||||
|
}
|
||||||
|
si[i].si_cache = rs_cache;
|
||||||
|
si[i].si_start = start;
|
||||||
|
si[i].si_count = randomx_dataset_item_count() - start;
|
||||||
|
for (i=1; i<miners; i++) {
|
||||||
|
CTHR_THREAD_CREATE(st[i], rx_seedthread, &si[i]);
|
||||||
|
}
|
||||||
|
randomx_init_dataset(rx_dataset, rs_cache, 0, si[0].si_count);
|
||||||
|
for (i=1; i<miners; i++) {
|
||||||
|
CTHR_THREAD_JOIN(st[i]);
|
||||||
|
}
|
||||||
|
free(st);
|
||||||
|
free(si);
|
||||||
|
} else {
|
||||||
|
randomx_init_dataset(rx_dataset, rs_cache, 0, randomx_dataset_item_count());
|
||||||
|
}
|
||||||
|
rx_dataset_height = seedheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (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) {
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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()) {
|
||||||
|
flags |= RANDOMX_FLAG_JIT;
|
||||||
|
if (!miners)
|
||||||
|
flags |= RANDOMX_FLAG_SECURE;
|
||||||
|
}
|
||||||
|
if(!force_software_aes() && check_aes_hw())
|
||||||
|
flags |= RANDOMX_FLAG_HARD_AES;
|
||||||
|
if (miners) {
|
||||||
|
CTHR_MUTEX_LOCK(rx_dataset_mutex);
|
||||||
|
if (rx_dataset == NULL) {
|
||||||
|
rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES);
|
||||||
|
if (rx_dataset == NULL) {
|
||||||
|
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX dataset");
|
||||||
|
rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT);
|
||||||
|
}
|
||||||
|
if (rx_dataset != NULL)
|
||||||
|
rx_initdata(rx_sp->rs_cache, miners, seedheight);
|
||||||
|
}
|
||||||
|
if (rx_dataset != NULL)
|
||||||
|
flags |= RANDOMX_FLAG_FULL_MEM;
|
||||||
|
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
|
||||||
|
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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void rx_slow_hash_free_state(void) {
|
||||||
|
if (rx_vm != NULL) {
|
||||||
|
randomx_destroy_vm(rx_vm);
|
||||||
|
rx_vm = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rx_stop_mining(void) {
|
||||||
|
CTHR_MUTEX_LOCK(rx_dataset_mutex);
|
||||||
|
if (rx_dataset != NULL) {
|
||||||
|
randomx_dataset *rd = rx_dataset;
|
||||||
|
rx_dataset = NULL;
|
||||||
|
randomx_release_dataset(rd);
|
||||||
|
}
|
||||||
|
CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
|
||||||
|
}
|
@ -743,7 +743,7 @@ BOOL SetLockPagesPrivilege(HANDLE hProcess, BOOL bEnable)
|
|||||||
* the allocated buffer.
|
* the allocated buffer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void slow_hash_allocate_state(void)
|
void cn_slow_hash_allocate_state(void)
|
||||||
{
|
{
|
||||||
if(hp_state != NULL)
|
if(hp_state != NULL)
|
||||||
return;
|
return;
|
||||||
@ -800,10 +800,10 @@ void slow_hash_allocate_state(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*@brief frees the state allocated by slow_hash_allocate_state
|
*@brief frees the state allocated by cn_slow_hash_allocate_state
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void slow_hash_free_state(void)
|
void cn_slow_hash_free_state(void)
|
||||||
{
|
{
|
||||||
if(hp_state == NULL)
|
if(hp_state == NULL)
|
||||||
return;
|
return;
|
||||||
@ -891,7 +891,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
|||||||
|
|
||||||
// this isn't supposed to happen, but guard against it for now.
|
// this isn't supposed to happen, but guard against it for now.
|
||||||
if(hp_state == NULL)
|
if(hp_state == NULL)
|
||||||
slow_hash_allocate_state();
|
cn_slow_hash_allocate_state();
|
||||||
|
|
||||||
/* CryptoNight Step 1: Use Keccak1600 to initialize the 'state' (and 'text') buffers from the data. */
|
/* CryptoNight Step 1: Use Keccak1600 to initialize the 'state' (and 'text') buffers from the data. */
|
||||||
if (prehashed) {
|
if (prehashed) {
|
||||||
@ -1005,13 +1005,13 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
#elif !defined NO_AES && (defined(__arm__) || defined(__aarch64__))
|
#elif !defined NO_AES && (defined(__arm__) || defined(__aarch64__))
|
||||||
void slow_hash_allocate_state(void)
|
void cn_slow_hash_allocate_state(void)
|
||||||
{
|
{
|
||||||
// Do nothing, this is just to maintain compatibility with the upgraded slow-hash.c
|
// Do nothing, this is just to maintain compatibility with the upgraded slow-hash.c
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void slow_hash_free_state(void)
|
void cn_slow_hash_free_state(void)
|
||||||
{
|
{
|
||||||
// As above
|
// As above
|
||||||
return;
|
return;
|
||||||
@ -1578,13 +1578,13 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
|||||||
|
|
||||||
#define hp_jitfunc ((v4_random_math_JIT_func)NULL)
|
#define hp_jitfunc ((v4_random_math_JIT_func)NULL)
|
||||||
|
|
||||||
void slow_hash_allocate_state(void)
|
void cn_slow_hash_allocate_state(void)
|
||||||
{
|
{
|
||||||
// Do nothing, this is just to maintain compatibility with the upgraded slow-hash.c
|
// Do nothing, this is just to maintain compatibility with the upgraded slow-hash.c
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void slow_hash_free_state(void)
|
void cn_slow_hash_free_state(void)
|
||||||
{
|
{
|
||||||
// As above
|
// As above
|
||||||
return;
|
return;
|
||||||
@ -1761,3 +1761,15 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void slow_hash_allocate_state(void)
|
||||||
|
{
|
||||||
|
cn_slow_hash_allocate_state();
|
||||||
|
rx_slow_hash_allocate_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
void slow_hash_free_state(void)
|
||||||
|
{
|
||||||
|
cn_slow_hash_free_state();
|
||||||
|
rx_slow_hash_free_state();
|
||||||
|
}
|
||||||
|
@ -58,6 +58,8 @@ struct Params {
|
|||||||
int BIP65Height;
|
int BIP65Height;
|
||||||
/** Block height at which BIP66 becomes active */
|
/** Block height at which BIP66 becomes active */
|
||||||
int BIP66Height;
|
int BIP66Height;
|
||||||
|
/** Block height at which RandomX becomes active */
|
||||||
|
int RandomXHeight;
|
||||||
/**
|
/**
|
||||||
* Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period,
|
* Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period,
|
||||||
* (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments.
|
* (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments.
|
||||||
@ -75,7 +77,12 @@ struct Params {
|
|||||||
int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; }
|
int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; }
|
||||||
uint256 nMinimumChainWork;
|
uint256 nMinimumChainWork;
|
||||||
uint256 defaultAssumeValid;
|
uint256 defaultAssumeValid;
|
||||||
uint8_t GetCryptonoteMajorVersion() const { return 10; }
|
uint8_t GetCryptonoteMajorVersion(uint32_t height) const {
|
||||||
|
if (height >= RandomXHeight) {
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace Consensus
|
} // namespace Consensus
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
|||||||
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
|
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
|
||||||
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus());
|
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus());
|
||||||
pblock->nNonce = nHeight; // nNonce now holds the height for Cryptonight variant 4
|
pblock->nNonce = nHeight; // nNonce now holds the height for Cryptonight variant 4
|
||||||
pblock->cnHeader.major_version = Params().GetConsensus().GetCryptonoteMajorVersion();
|
pblock->cnHeader.major_version = Params().GetConsensus().GetCryptonoteMajorVersion(nHeight);
|
||||||
pblock->cnHeader.prev_id = pblock->GetOriginalBlockHash();
|
pblock->cnHeader.prev_id = pblock->GetOriginalBlockHash();
|
||||||
pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]);
|
pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]);
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <tinyformat.h>
|
#include <tinyformat.h>
|
||||||
#include <utilstrencodings.h>
|
#include <utilstrencodings.h>
|
||||||
#include <crypto/common.h>
|
#include <crypto/common.h>
|
||||||
|
#include <validation.h>
|
||||||
|
|
||||||
extern "C" void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed, uint64_t height);
|
extern "C" void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed, uint64_t height);
|
||||||
extern "C" void cn_fast_hash(const void *data, size_t length, char *hash);
|
extern "C" void cn_fast_hash(const void *data, size_t length, char *hash);
|
||||||
@ -50,7 +51,15 @@ uint256 CBlockHeader::GetPoWHash() const
|
|||||||
return thash;
|
return thash;
|
||||||
}
|
}
|
||||||
cryptonote::blobdata blob = cryptonote::t_serializable_object_to_blob(cnHeader);
|
cryptonote::blobdata blob = cryptonote::t_serializable_object_to_blob(cnHeader);
|
||||||
cn_slow_hash(blob.data(), blob.size(), BEGIN(thash), cnHeader.major_version - 6, 0, nNonce);
|
uint32_t height = nNonce;
|
||||||
|
if (cnHeader.major_version >= RX_BLOCK_VERSION) {
|
||||||
|
uint64_t seed_height;
|
||||||
|
seed_height = rx_seedheight(height);
|
||||||
|
CBlockIndex* pblockindex = chainActive[seed_height];
|
||||||
|
rx_slow_hash(height, seed_height, (const char*)(pblockindex->GetBlockHash().begin()), blob.data(), blob.size(), BEGIN(thash), 0, 0);
|
||||||
|
} else {
|
||||||
|
cn_slow_hash(blob.data(), blob.size(), BEGIN(thash), cnHeader.major_version - 6, 0, height);
|
||||||
|
}
|
||||||
return thash;
|
return thash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <uint256.h>
|
#include <uint256.h>
|
||||||
|
|
||||||
#include <cryptonote_basic/cryptonote_format_utils.h>
|
#include <cryptonote_basic/cryptonote_format_utils.h>
|
||||||
|
#include <crypto/hash-ops.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This header is to store the proof-of-work of cryptonote mining.
|
* This header is to store the proof-of-work of cryptonote mining.
|
||||||
|
@ -883,8 +883,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
|
|||||||
|
|
||||||
cryptonote::block cn_block;
|
cryptonote::block cn_block;
|
||||||
// block_header
|
// block_header
|
||||||
// const int cn_variant = b.major_version >= 7 ? b.major_version - 6 : 0;
|
cn_block.major_version = consensusParams.GetCryptonoteMajorVersion(pblock->nNonce);
|
||||||
cn_block.major_version = consensusParams.GetCryptonoteMajorVersion();
|
|
||||||
cn_block.minor_version = 0;
|
cn_block.minor_version = 0;
|
||||||
cn_block.timestamp = pblock->GetBlockTime();
|
cn_block.timestamp = pblock->GetBlockTime();
|
||||||
// The prev_id is used to store kevacoin block hash, as a proof of work.
|
// The prev_id is used to store kevacoin block hash, as a proof of work.
|
||||||
@ -957,6 +956,13 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
|
|||||||
result.push_back(Pair("prev_hash", pblock->hashPrevBlock.GetHex()));
|
result.push_back(Pair("prev_hash", pblock->hashPrevBlock.GetHex()));
|
||||||
result.push_back(Pair("reserved_offset", (uint64_t)reserved_offset));
|
result.push_back(Pair("reserved_offset", (uint64_t)reserved_offset));
|
||||||
|
|
||||||
|
if (cn_block.major_version >= RX_BLOCK_VERSION) {
|
||||||
|
uint64_t seed_height, next_height;
|
||||||
|
rx_seedheights(height, &seed_height, &next_height);
|
||||||
|
result.push_back(Pair("seed_hash", chainActive[seed_height]->GetBlockHash().GetHex()));
|
||||||
|
result.push_back(Pair("next_seed_hash", chainActive[next_height]->GetBlockHash().GetHex()));
|
||||||
|
}
|
||||||
|
|
||||||
// Kevacoin specific entries. Not used for now and may be useful in the future.
|
// Kevacoin specific entries. Not used for now and may be useful in the future.
|
||||||
result.push_back(Pair("rules", aRules));
|
result.push_back(Pair("rules", aRules));
|
||||||
result.push_back(Pair("vbavailable", vbavailable));
|
result.push_back(Pair("vbavailable", vbavailable));
|
||||||
|
@ -47,7 +47,7 @@ static CBlock BuildBlockTestCase() {
|
|||||||
bool mutated;
|
bool mutated;
|
||||||
block.hashMerkleRoot = BlockMerkleRoot(block, &mutated);
|
block.hashMerkleRoot = BlockMerkleRoot(block, &mutated);
|
||||||
assert(!mutated);
|
assert(!mutated);
|
||||||
block.cnHeader.major_version = Params().GetConsensus().GetCryptonoteMajorVersion();
|
block.cnHeader.major_version = Params().GetConsensus().GetCryptonoteMajorVersion(block.nNonce);
|
||||||
block.cnHeader.prev_id = block.GetOriginalBlockHash();
|
block.cnHeader.prev_id = block.GetOriginalBlockHash();
|
||||||
while (!CheckProofOfWork(block.GetPoWHash(), block.nBits, Params().GetConsensus())) ++block.cnHeader.nonce;
|
while (!CheckProofOfWork(block.GetPoWHash(), block.nBits, Params().GetConsensus())) ++block.cnHeader.nonce;
|
||||||
return block;
|
return block;
|
||||||
@ -294,7 +294,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest)
|
|||||||
bool mutated;
|
bool mutated;
|
||||||
block.hashMerkleRoot = BlockMerkleRoot(block, &mutated);
|
block.hashMerkleRoot = BlockMerkleRoot(block, &mutated);
|
||||||
assert(!mutated);
|
assert(!mutated);
|
||||||
block.cnHeader.major_version = Params().GetConsensus().GetCryptonoteMajorVersion();
|
block.cnHeader.major_version = Params().GetConsensus().GetCryptonoteMajorVersion(block.nNonce);
|
||||||
block.cnHeader.prev_id = block.GetOriginalHash();
|
block.cnHeader.prev_id = block.GetOriginalHash();
|
||||||
while (!CheckProofOfWork(block.GetPoWHash(), block.nBits, Params().GetConsensus())) ++block.cnHeader.nonce;
|
while (!CheckProofOfWork(block.GetPoWHash(), block.nBits, Params().GetConsensus())) ++block.cnHeader.nonce;
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>&
|
|||||||
IncrementExtraNonce(&block, chainActive.Tip(), extraNonce);
|
IncrementExtraNonce(&block, chainActive.Tip(), extraNonce);
|
||||||
}
|
}
|
||||||
|
|
||||||
block.cnHeader.major_version = Params().GetConsensus().GetCryptonoteMajorVersion();
|
block.cnHeader.major_version = Params().GetConsensus().GetCryptonoteMajorVersion(block.nNonce);
|
||||||
block.cnHeader.prev_id = block.GetOriginalBlockHash();
|
block.cnHeader.prev_id = block.GetOriginalBlockHash();
|
||||||
while (!CheckProofOfWork(block.GetPoWHash(), block.nBits, chainparams.GetConsensus())) ++block.cnHeader.nonce;
|
while (!CheckProofOfWork(block.GetPoWHash(), block.nBits, chainparams.GetConsensus())) ++block.cnHeader.nonce;
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ std::shared_ptr<CBlock> FinalizeBlock(std::shared_ptr<CBlock> pblock)
|
|||||||
{
|
{
|
||||||
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
|
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
|
||||||
|
|
||||||
pblock->cnHeader.major_version = Params().GetConsensus().GetCryptonoteMajorVersion();
|
pblock->cnHeader.major_version = Params().GetConsensus().GetCryptonoteMajorVersion(pblock->nNonce);
|
||||||
pblock->cnHeader.prev_id = pblock->GetOriginalBlockHash();
|
pblock->cnHeader.prev_id = pblock->GetOriginalBlockHash();
|
||||||
while (!CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus())) {
|
while (!CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus())) {
|
||||||
++(pblock->cnHeader.nonce);
|
++(pblock->cnHeader.nonce);
|
||||||
|
@ -3039,7 +3039,8 @@ static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos,
|
|||||||
|
|
||||||
static bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true)
|
static bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true)
|
||||||
{
|
{
|
||||||
if (block.cnHeader.major_version != consensusParams.GetCryptonoteMajorVersion()) {
|
uint32_t height = block.nNonce;
|
||||||
|
if (block.cnHeader.major_version != consensusParams.GetCryptonoteMajorVersion(height)) {
|
||||||
return state.Invalid(false, 0, "incorrect-major-version", "Cryptonote major version incorrect");
|
return state.Invalid(false, 0, "incorrect-major-version", "Cryptonote major version incorrect");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user