mirror of
https://github.com/monero-project/monero.git
synced 2024-12-22 19:49:30 +00:00
RandomX integration
Support RandomX PoW algorithm
This commit is contained in:
parent
cb6f96b9d1
commit
81c2ad6d5b
24 changed files with 610 additions and 49 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -12,3 +12,6 @@
|
||||||
[submodule "external/trezor-common"]
|
[submodule "external/trezor-common"]
|
||||||
path = external/trezor-common
|
path = external/trezor-common
|
||||||
url = https://github.com/trezor/trezor-common.git
|
url = https://github.com/trezor/trezor-common.git
|
||||||
|
[submodule "external/randomx"]
|
||||||
|
path = external/randomx
|
||||||
|
url = https://github.com/tevador/RandomX
|
||||||
|
|
|
@ -200,6 +200,7 @@ if(NOT MANUAL_SUBMODULES)
|
||||||
check_submodule(external/unbound)
|
check_submodule(external/unbound)
|
||||||
check_submodule(external/rapidjson)
|
check_submodule(external/rapidjson)
|
||||||
check_submodule(external/trezor-common)
|
check_submodule(external/trezor-common)
|
||||||
|
check_submodule(external/randomx)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
1
external/CMakeLists.txt
vendored
1
external/CMakeLists.txt
vendored
|
@ -80,3 +80,4 @@ endif()
|
||||||
|
|
||||||
add_subdirectory(db_drivers)
|
add_subdirectory(db_drivers)
|
||||||
add_subdirectory(easylogging++)
|
add_subdirectory(easylogging++)
|
||||||
|
add_subdirectory(randomx EXCLUDE_FROM_ALL)
|
||||||
|
|
1
external/randomx
vendored
Submodule
1
external/randomx
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 519b9cf70540bdd996e806251cde335c8eef8aca
|
|
@ -46,6 +46,7 @@ set(crypto_sources
|
||||||
random.c
|
random.c
|
||||||
skein.c
|
skein.c
|
||||||
slow-hash.c
|
slow-hash.c
|
||||||
|
rx-slow-hash.c
|
||||||
CryptonightR_JIT.c
|
CryptonightR_JIT.c
|
||||||
tree-hash.c)
|
tree-hash.c)
|
||||||
|
|
||||||
|
@ -53,6 +54,8 @@ if(ARCH_ID STREQUAL "i386" OR ARCH_ID STREQUAL "x86_64" OR ARCH_ID STREQUAL "x86
|
||||||
list(APPEND crypto_sources CryptonightR_template.S)
|
list(APPEND crypto_sources CryptonightR_template.S)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
include_directories(${RANDOMX_INCLUDE})
|
||||||
|
|
||||||
set(crypto_headers)
|
set(crypto_headers)
|
||||||
|
|
||||||
set(crypto_private_headers
|
set(crypto_private_headers
|
||||||
|
@ -86,6 +89,7 @@ monero_add_library(cncrypto
|
||||||
target_link_libraries(cncrypto
|
target_link_libraries(cncrypto
|
||||||
PUBLIC
|
PUBLIC
|
||||||
epee
|
epee
|
||||||
|
randomx
|
||||||
${Boost_SYSTEM_LIBRARY}
|
${Boost_SYSTEM_LIBRARY}
|
||||||
${SODIUM_LIBRARY}
|
${SODIUM_LIBRARY}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
|
58
src/crypto/c_threads.h
Normal file
58
src/crypto/c_threads.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
/* Brain-dead simple portability wrapper over thread APIs for C */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#define CTHR_MUTEX_TYPE HANDLE
|
||||||
|
#define CTHR_MUTEX_INIT NULL
|
||||||
|
#define CTHR_MUTEX_LOCK(x) do { if (x == NULL) { \
|
||||||
|
HANDLE p = CreateMutex(NULL, FALSE, NULL); \
|
||||||
|
if (InterlockedCompareExchangePointer((PVOID*)&x, (PVOID)p, NULL) != NULL) \
|
||||||
|
CloseHandle(p); \
|
||||||
|
} WaitForSingleObject(x, INFINITE); } while(0)
|
||||||
|
#define CTHR_MUTEX_UNLOCK(x) ReleaseMutex(x)
|
||||||
|
#define CTHR_THREAD_TYPE HANDLE
|
||||||
|
#define CTHR_THREAD_RTYPE void
|
||||||
|
#define CTHR_THREAD_RETURN return
|
||||||
|
#define CTHR_THREAD_CREATE(thr, func, arg) thr = (HANDLE)_beginthread(func, 0, arg)
|
||||||
|
#define CTHR_THREAD_JOIN(thr) WaitForSingleObject(thr, INFINITE)
|
||||||
|
#else
|
||||||
|
#include <pthread.h>
|
||||||
|
#define CTHR_MUTEX_TYPE pthread_mutex_t
|
||||||
|
#define CTHR_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
|
||||||
|
#define CTHR_MUTEX_LOCK(x) pthread_mutex_lock(&x)
|
||||||
|
#define CTHR_MUTEX_UNLOCK(x) pthread_mutex_unlock(&x)
|
||||||
|
#define CTHR_THREAD_TYPE pthread_t
|
||||||
|
#define CTHR_THREAD_RTYPE void *
|
||||||
|
#define CTHR_THREAD_RETURN return NULL
|
||||||
|
#define CTHR_THREAD_CREATE(thr, func, arg) pthread_create(&thr, NULL, func, arg)
|
||||||
|
#define CTHR_THREAD_JOIN(thr) pthread_join(thr, NULL)
|
||||||
|
#endif
|
|
@ -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/crypto/rx-slow-hash.c
Normal file
357
src/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);
|
||||||
|
}
|
|
@ -742,7 +742,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;
|
||||||
|
@ -804,7 +804,7 @@ void slow_hash_allocate_state(void)
|
||||||
*@brief frees the state allocated by slow_hash_allocate_state
|
*@brief frees the state allocated by 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;
|
||||||
|
@ -892,7 +892,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();
|
||||||
|
|
||||||
// locals to avoid constant TLS dereferencing
|
// locals to avoid constant TLS dereferencing
|
||||||
uint8_t *local_hp_state = hp_state;
|
uint8_t *local_hp_state = hp_state;
|
||||||
|
@ -1009,13 +1009,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;
|
||||||
|
@ -1582,13 +1582,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;
|
||||||
|
@ -1765,3 +1765,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();
|
||||||
|
}
|
||||||
|
|
|
@ -1218,21 +1218,6 @@ namespace cryptonote
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height)
|
|
||||||
{
|
|
||||||
// block 202612 bug workaround
|
|
||||||
if (height == 202612)
|
|
||||||
{
|
|
||||||
static const std::string longhash_202612 = "84f64766475d51837ac9efbef1926486e58563c95a19fef4aec3254f03000000";
|
|
||||||
string_tools::hex_to_pod(longhash_202612, res);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
blobdata bd = get_block_hashing_blob(b);
|
|
||||||
const int cn_variant = b.major_version >= 7 ? b.major_version - 6 : 0;
|
|
||||||
crypto::cn_slow_hash(bd.data(), bd.size(), res, cn_variant, height);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------
|
|
||||||
std::vector<uint64_t> relative_output_offsets_to_absolute(const std::vector<uint64_t>& off)
|
std::vector<uint64_t> relative_output_offsets_to_absolute(const std::vector<uint64_t>& off)
|
||||||
{
|
{
|
||||||
std::vector<uint64_t> res = off;
|
std::vector<uint64_t> res = off;
|
||||||
|
@ -1253,13 +1238,6 @@ namespace cryptonote
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
crypto::hash get_block_longhash(const block& b, uint64_t height)
|
|
||||||
{
|
|
||||||
crypto::hash p = null_hash;
|
|
||||||
get_block_longhash(b, p, height);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------
|
|
||||||
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash *block_hash)
|
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash *block_hash)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
|
@ -117,8 +117,6 @@ namespace cryptonote
|
||||||
bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata *blob = NULL);
|
bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata *blob = NULL);
|
||||||
bool get_block_hash(const block& b, crypto::hash& res);
|
bool get_block_hash(const block& b, crypto::hash& res);
|
||||||
crypto::hash get_block_hash(const block& b);
|
crypto::hash get_block_hash(const block& b);
|
||||||
bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height);
|
|
||||||
crypto::hash get_block_longhash(const block& b, uint64_t height);
|
|
||||||
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash *block_hash);
|
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash *block_hash);
|
||||||
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b);
|
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b);
|
||||||
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash &block_hash);
|
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash &block_hash);
|
||||||
|
|
|
@ -36,8 +36,10 @@
|
||||||
#include "syncobj.h"
|
#include "syncobj.h"
|
||||||
#include "cryptonote_basic_impl.h"
|
#include "cryptonote_basic_impl.h"
|
||||||
#include "cryptonote_format_utils.h"
|
#include "cryptonote_format_utils.h"
|
||||||
|
#include "cryptonote_core/cryptonote_tx_utils.h"
|
||||||
#include "file_io_utils.h"
|
#include "file_io_utils.h"
|
||||||
#include "common/command_line.h"
|
#include "common/command_line.h"
|
||||||
|
#include "common/util.h"
|
||||||
#include "string_coding.h"
|
#include "string_coding.h"
|
||||||
#include "string_tools.h"
|
#include "string_tools.h"
|
||||||
#include "storages/portable_storage_template_helper.h"
|
#include "storages/portable_storage_template_helper.h"
|
||||||
|
@ -98,12 +100,13 @@ namespace cryptonote
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
miner::miner(i_miner_handler* phandler):m_stop(1),
|
miner::miner(i_miner_handler* phandler, Blockchain* pbc):m_stop(1),
|
||||||
m_template{},
|
m_template{},
|
||||||
m_template_no(0),
|
m_template_no(0),
|
||||||
m_diffic(0),
|
m_diffic(0),
|
||||||
m_thread_index(0),
|
m_thread_index(0),
|
||||||
m_phandler(phandler),
|
m_phandler(phandler),
|
||||||
|
m_pbc(pbc),
|
||||||
m_height(0),
|
m_height(0),
|
||||||
m_threads_active(0),
|
m_threads_active(0),
|
||||||
m_pausers_count(0),
|
m_pausers_count(0),
|
||||||
|
@ -429,6 +432,7 @@ namespace cryptonote
|
||||||
{
|
{
|
||||||
boost::interprocess::ipcdetail::atomic_write32(&m_stop, 1);
|
boost::interprocess::ipcdetail::atomic_write32(&m_stop, 1);
|
||||||
}
|
}
|
||||||
|
extern "C" void rx_stop_mining(void);
|
||||||
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
||||||
bool miner::stop()
|
bool miner::stop()
|
||||||
{
|
{
|
||||||
|
@ -461,15 +465,16 @@ namespace cryptonote
|
||||||
MINFO("Mining has been stopped, " << m_threads.size() << " finished" );
|
MINFO("Mining has been stopped, " << m_threads.size() << " finished" );
|
||||||
m_threads.clear();
|
m_threads.clear();
|
||||||
m_threads_autodetect.clear();
|
m_threads_autodetect.clear();
|
||||||
|
rx_stop_mining();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
||||||
bool miner::find_nonce_for_given_block(block& bl, const difficulty_type& diffic, uint64_t height)
|
bool miner::find_nonce_for_given_block(const Blockchain *pbc, block& bl, const difficulty_type& diffic, uint64_t height)
|
||||||
{
|
{
|
||||||
for(; bl.nonce != std::numeric_limits<uint32_t>::max(); bl.nonce++)
|
for(; bl.nonce != std::numeric_limits<uint32_t>::max(); bl.nonce++)
|
||||||
{
|
{
|
||||||
crypto::hash h;
|
crypto::hash h;
|
||||||
get_block_longhash(bl, h, height);
|
get_block_longhash(pbc, bl, h, height, tools::get_max_concurrency());
|
||||||
|
|
||||||
if(check_hash(h, diffic))
|
if(check_hash(h, diffic))
|
||||||
{
|
{
|
||||||
|
@ -565,7 +570,7 @@ namespace cryptonote
|
||||||
|
|
||||||
b.nonce = nonce;
|
b.nonce = nonce;
|
||||||
crypto::hash h;
|
crypto::hash h;
|
||||||
get_block_longhash(b, h, height);
|
get_block_longhash(m_pbc, b, h, height, tools::get_max_concurrency());
|
||||||
|
|
||||||
if(check_hash(h, local_diff))
|
if(check_hash(h, local_diff))
|
||||||
{
|
{
|
||||||
|
|
|
@ -52,13 +52,15 @@ namespace cryptonote
|
||||||
~i_miner_handler(){};
|
~i_miner_handler(){};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Blockchain;
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
class miner
|
class miner
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
miner(i_miner_handler* phandler);
|
miner(i_miner_handler* phandler, Blockchain* pbc);
|
||||||
~miner();
|
~miner();
|
||||||
bool init(const boost::program_options::variables_map& vm, network_type nettype);
|
bool init(const boost::program_options::variables_map& vm, network_type nettype);
|
||||||
static void init_options(boost::program_options::options_description& desc);
|
static void init_options(boost::program_options::options_description& desc);
|
||||||
|
@ -74,7 +76,7 @@ namespace cryptonote
|
||||||
bool on_idle();
|
bool on_idle();
|
||||||
void on_synchronized();
|
void on_synchronized();
|
||||||
//synchronous analog (for fast calls)
|
//synchronous analog (for fast calls)
|
||||||
static bool find_nonce_for_given_block(block& bl, const difficulty_type& diffic, uint64_t height);
|
static bool find_nonce_for_given_block(const Blockchain *pbc, block& bl, const difficulty_type& diffic, uint64_t height);
|
||||||
void pause();
|
void pause();
|
||||||
void resume();
|
void resume();
|
||||||
void do_print_hashrate(bool do_hr);
|
void do_print_hashrate(bool do_hr);
|
||||||
|
@ -133,6 +135,7 @@ namespace cryptonote
|
||||||
std::list<boost::thread> m_threads;
|
std::list<boost::thread> m_threads;
|
||||||
epee::critical_section m_threads_lock;
|
epee::critical_section m_threads_lock;
|
||||||
i_miner_handler* m_phandler;
|
i_miner_handler* m_phandler;
|
||||||
|
Blockchain* m_pbc;
|
||||||
account_public_address m_mine_address;
|
account_public_address m_mine_address;
|
||||||
epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval;
|
epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval;
|
||||||
epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval;
|
epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval;
|
||||||
|
|
|
@ -96,6 +96,7 @@
|
||||||
#define BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT 10000 //by default, blocks ids count in synchronizing
|
#define BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT 10000 //by default, blocks ids count in synchronizing
|
||||||
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT_PRE_V4 100 //by default, blocks count in blocks downloading
|
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT_PRE_V4 100 //by default, blocks count in blocks downloading
|
||||||
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT 20 //by default, blocks count in blocks downloading
|
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT 20 //by default, blocks count in blocks downloading
|
||||||
|
#define BLOCKS_SYNCHRONIZING_MAX_COUNT 2048 //must be a power of 2, greater than 128, equal to SEEDHASH_EPOCH_BLOCKS
|
||||||
|
|
||||||
#define CRYPTONOTE_MEMPOOL_TX_LIVETIME (86400*3) //seconds, three days
|
#define CRYPTONOTE_MEMPOOL_TX_LIVETIME (86400*3) //seconds, three days
|
||||||
#define CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME 604800 //seconds, one week
|
#define CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME 604800 //seconds, one week
|
||||||
|
|
|
@ -95,7 +95,8 @@ Blockchain::Blockchain(tx_memory_pool& tx_pool) :
|
||||||
m_difficulty_for_next_block_top_hash(crypto::null_hash),
|
m_difficulty_for_next_block_top_hash(crypto::null_hash),
|
||||||
m_difficulty_for_next_block(1),
|
m_difficulty_for_next_block(1),
|
||||||
m_btc_valid(false),
|
m_btc_valid(false),
|
||||||
m_batch_success(true)
|
m_batch_success(true),
|
||||||
|
m_prepare_height(0)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||||
}
|
}
|
||||||
|
@ -754,6 +755,13 @@ crypto::hash Blockchain::get_block_id_by_height(uint64_t height) const
|
||||||
return null_hash;
|
return null_hash;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
crypto::hash Blockchain::get_pending_block_id_by_height(uint64_t height) const
|
||||||
|
{
|
||||||
|
if (m_prepare_height && height >= m_prepare_height && height - m_prepare_height < m_prepare_nblocks)
|
||||||
|
return (*m_prepare_blocks)[height - m_prepare_height].hash;
|
||||||
|
return get_block_id_by_height(height);
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------
|
||||||
bool Blockchain::get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan) const
|
bool Blockchain::get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan) const
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||||
|
@ -1029,6 +1037,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
|
||||||
}
|
}
|
||||||
|
|
||||||
m_hardfork->reorganize_from_chain_height(split_height);
|
m_hardfork->reorganize_from_chain_height(split_height);
|
||||||
|
get_block_longhash_reorg(split_height);
|
||||||
|
|
||||||
std::shared_ptr<tools::Notify> reorg_notify = m_reorg_notify;
|
std::shared_ptr<tools::Notify> reorg_notify = m_reorg_notify;
|
||||||
if (reorg_notify)
|
if (reorg_notify)
|
||||||
|
@ -1684,7 +1693,30 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
|
||||||
difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei);
|
difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei);
|
||||||
CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!");
|
CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!");
|
||||||
crypto::hash proof_of_work = null_hash;
|
crypto::hash proof_of_work = null_hash;
|
||||||
get_block_longhash(bei.bl, proof_of_work, bei.height);
|
if (b.major_version >= RX_BLOCK_VERSION)
|
||||||
|
{
|
||||||
|
crypto::hash seedhash = null_hash;
|
||||||
|
uint64_t seedheight = rx_seedheight(bei.height);
|
||||||
|
// seedblock is on the alt chain somewhere
|
||||||
|
if (alt_chain.size() && alt_chain.front().height <= seedheight)
|
||||||
|
{
|
||||||
|
for (auto it=alt_chain.begin(); it != alt_chain.end(); it++)
|
||||||
|
{
|
||||||
|
if (it->height == seedheight+1)
|
||||||
|
{
|
||||||
|
seedhash = it->bl.prev_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
seedhash = get_block_id_by_height(seedheight);
|
||||||
|
}
|
||||||
|
get_altblock_longhash(bei.bl, proof_of_work, get_current_blockchain_height(), bei.height, seedheight, seedhash);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
get_block_longhash(this, bei.bl, proof_of_work, bei.height, 0);
|
||||||
|
}
|
||||||
if(!check_hash(proof_of_work, current_diff))
|
if(!check_hash(proof_of_work, current_diff))
|
||||||
{
|
{
|
||||||
MERROR_VER("Block with id: " << id << std::endl << " for alternative chain, does not have enough proof of work: " << proof_of_work << std::endl << " expected difficulty: " << current_diff);
|
MERROR_VER("Block with id: " << id << std::endl << " for alternative chain, does not have enough proof of work: " << proof_of_work << std::endl << " expected difficulty: " << current_diff);
|
||||||
|
@ -3613,7 +3645,7 @@ leave:
|
||||||
proof_of_work = it->second;
|
proof_of_work = it->second;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
proof_of_work = get_block_longhash(bl, blockchain_height);
|
proof_of_work = get_block_longhash(this, bl, blockchain_height, 0);
|
||||||
|
|
||||||
// validate proof_of_work versus difficulty target
|
// validate proof_of_work versus difficulty target
|
||||||
if(!check_hash(proof_of_work, current_diffic))
|
if(!check_hash(proof_of_work, current_diffic))
|
||||||
|
@ -4114,7 +4146,7 @@ void Blockchain::block_longhash_worker(uint64_t height, const epee::span<const b
|
||||||
if (m_cancel)
|
if (m_cancel)
|
||||||
break;
|
break;
|
||||||
crypto::hash id = get_block_hash(block);
|
crypto::hash id = get_block_hash(block);
|
||||||
crypto::hash pow = get_block_longhash(block, height++);
|
crypto::hash pow = get_block_longhash(this, block, height++, 0);
|
||||||
map.emplace(id, pow);
|
map.emplace(id, pow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4430,6 +4462,9 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
|
||||||
m_blocks_longhash_table.clear();
|
m_blocks_longhash_table.clear();
|
||||||
uint64_t thread_height = height;
|
uint64_t thread_height = height;
|
||||||
tools::threadpool::waiter waiter;
|
tools::threadpool::waiter waiter;
|
||||||
|
m_prepare_height = height;
|
||||||
|
m_prepare_nblocks = blocks_entry.size();
|
||||||
|
m_prepare_blocks = &blocks;
|
||||||
for (unsigned int i = 0; i < threads; i++)
|
for (unsigned int i = 0; i < threads; i++)
|
||||||
{
|
{
|
||||||
unsigned nblocks = batches;
|
unsigned nblocks = batches;
|
||||||
|
@ -4440,6 +4475,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
|
||||||
}
|
}
|
||||||
|
|
||||||
waiter.wait(&tpool);
|
waiter.wait(&tpool);
|
||||||
|
m_prepare_height = 0;
|
||||||
|
|
||||||
if (m_cancel)
|
if (m_cancel)
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -205,6 +205,18 @@ namespace cryptonote
|
||||||
*/
|
*/
|
||||||
crypto::hash get_block_id_by_height(uint64_t height) const;
|
crypto::hash get_block_id_by_height(uint64_t height) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief gets a block's hash given a height
|
||||||
|
*
|
||||||
|
* Used only by prepare_handle_incoming_blocks. Will look in the list of incoming blocks
|
||||||
|
* if the height is contained there.
|
||||||
|
*
|
||||||
|
* @param height the height of the block
|
||||||
|
*
|
||||||
|
* @return the hash of the block at the requested height, or a zeroed hash if there is no such block
|
||||||
|
*/
|
||||||
|
crypto::hash get_pending_block_id_by_height(uint64_t height) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief gets the block with a given hash
|
* @brief gets the block with a given hash
|
||||||
*
|
*
|
||||||
|
@ -1077,6 +1089,11 @@ namespace cryptonote
|
||||||
std::shared_ptr<tools::Notify> m_block_notify;
|
std::shared_ptr<tools::Notify> m_block_notify;
|
||||||
std::shared_ptr<tools::Notify> m_reorg_notify;
|
std::shared_ptr<tools::Notify> m_reorg_notify;
|
||||||
|
|
||||||
|
// for prepare_handle_incoming_blocks
|
||||||
|
uint64_t m_prepare_height;
|
||||||
|
uint64_t m_prepare_nblocks;
|
||||||
|
std::vector<block> *m_prepare_blocks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief collects the keys for all outputs being "spent" as an input
|
* @brief collects the keys for all outputs being "spent" as an input
|
||||||
*
|
*
|
||||||
|
|
|
@ -219,7 +219,7 @@ namespace cryptonote
|
||||||
core::core(i_cryptonote_protocol* pprotocol):
|
core::core(i_cryptonote_protocol* pprotocol):
|
||||||
m_mempool(m_blockchain_storage),
|
m_mempool(m_blockchain_storage),
|
||||||
m_blockchain_storage(m_mempool),
|
m_blockchain_storage(m_mempool),
|
||||||
m_miner(this),
|
m_miner(this, &m_blockchain_storage),
|
||||||
m_starter_message_showed(false),
|
m_starter_message_showed(false),
|
||||||
m_target_blockchain_height(0),
|
m_target_blockchain_height(0),
|
||||||
m_checkpoints_path(""),
|
m_checkpoints_path(""),
|
||||||
|
@ -655,6 +655,8 @@ namespace cryptonote
|
||||||
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage");
|
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage");
|
||||||
|
|
||||||
block_sync_size = command_line::get_arg(vm, arg_block_sync_size);
|
block_sync_size = command_line::get_arg(vm, arg_block_sync_size);
|
||||||
|
if (block_sync_size > BLOCKS_SYNCHRONIZING_MAX_COUNT)
|
||||||
|
MERROR("Error --block-sync-size cannot be greater than " << BLOCKS_SYNCHRONIZING_MAX_COUNT);
|
||||||
|
|
||||||
MGINFO("Loading checkpoints");
|
MGINFO("Loading checkpoints");
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ using namespace epee;
|
||||||
#include "common/apply_permutation.h"
|
#include "common/apply_permutation.h"
|
||||||
#include "cryptonote_tx_utils.h"
|
#include "cryptonote_tx_utils.h"
|
||||||
#include "cryptonote_config.h"
|
#include "cryptonote_config.h"
|
||||||
|
#include "blockchain.h"
|
||||||
#include "cryptonote_basic/miner.h"
|
#include "cryptonote_basic/miner.h"
|
||||||
#include "cryptonote_basic/tx_extra.h"
|
#include "cryptonote_basic/tx_extra.h"
|
||||||
#include "crypto/crypto.h"
|
#include "crypto/crypto.h"
|
||||||
|
@ -658,9 +659,59 @@ namespace cryptonote
|
||||||
bl.minor_version = CURRENT_BLOCK_MINOR_VERSION;
|
bl.minor_version = CURRENT_BLOCK_MINOR_VERSION;
|
||||||
bl.timestamp = 0;
|
bl.timestamp = 0;
|
||||||
bl.nonce = nonce;
|
bl.nonce = nonce;
|
||||||
miner::find_nonce_for_given_block(bl, 1, 0);
|
miner::find_nonce_for_given_block(NULL, bl, 1, 0);
|
||||||
bl.invalidate_hashes();
|
bl.invalidate_hashes();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
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_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)
|
||||||
|
{
|
||||||
|
// block 202612 bug workaround
|
||||||
|
if (height == 202612)
|
||||||
|
{
|
||||||
|
static const std::string longhash_202612 = "84f64766475d51837ac9efbef1926486e58563c95a19fef4aec3254f03000000";
|
||||||
|
epee::string_tools::hex_to_pod(longhash_202612, res);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
blobdata bd = get_block_hashing_blob(b);
|
||||||
|
if (b.major_version >= RX_BLOCK_VERSION)
|
||||||
|
{
|
||||||
|
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(main_height, seed_height, hash.data, bd.data(), bd.size(), res.data, miners, 0);
|
||||||
|
} else {
|
||||||
|
const int pow_variant = b.major_version >= 7 ? b.major_version - 6 : 0;
|
||||||
|
crypto::cn_slow_hash(bd.data(), bd.size(), res, pow_variant, height);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto::hash get_block_longhash(const Blockchain *pbc, const block& b, const uint64_t height, const int miners)
|
||||||
|
{
|
||||||
|
crypto::hash p = crypto::null_hash;
|
||||||
|
get_block_longhash(pbc, b, p, height, miners);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_block_longhash_reorg(const uint64_t split_height)
|
||||||
|
{
|
||||||
|
rx_reorg(split_height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,6 +132,13 @@ namespace cryptonote
|
||||||
, uint32_t nonce
|
, uint32_t nonce
|
||||||
);
|
);
|
||||||
|
|
||||||
|
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);
|
||||||
|
void get_block_longhash_reorg(const uint64_t split_height);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_CLASS_VERSION(cryptonote::tx_source_entry, 1)
|
BOOST_CLASS_VERSION(cryptonote::tx_source_entry, 1)
|
||||||
|
|
|
@ -86,6 +86,7 @@ const hardfork_t testnet_hard_forks[] = {
|
||||||
{ 9, 1057778, 0, 1533297600 },
|
{ 9, 1057778, 0, 1533297600 },
|
||||||
{ 10, 1154318, 0, 1550153694 },
|
{ 10, 1154318, 0, 1550153694 },
|
||||||
{ 11, 1155038, 0, 1550225678 },
|
{ 11, 1155038, 0, 1550225678 },
|
||||||
|
{ 12, 1308737, 0, 1569582000 },
|
||||||
};
|
};
|
||||||
const size_t num_testnet_hard_forks = sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]);
|
const size_t num_testnet_hard_forks = sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]);
|
||||||
const uint64_t testnet_hard_fork_version_1_till = 624633;
|
const uint64_t testnet_hard_fork_version_1_till = 624633;
|
||||||
|
|
|
@ -1060,6 +1060,7 @@ namespace cryptonote
|
||||||
case 1: res.pow_algorithm = "CNv1 (Cryptonight variant 1)"; break;
|
case 1: res.pow_algorithm = "CNv1 (Cryptonight variant 1)"; break;
|
||||||
case 2: case 3: res.pow_algorithm = "CNv2 (Cryptonight variant 2)"; break;
|
case 2: case 3: res.pow_algorithm = "CNv2 (Cryptonight variant 2)"; break;
|
||||||
case 4: case 5: res.pow_algorithm = "CNv4 (Cryptonight variant 4)"; break;
|
case 4: case 5: res.pow_algorithm = "CNv4 (Cryptonight variant 4)"; break;
|
||||||
|
case 6: res.pow_algorithm = "RandomX"; break;
|
||||||
default: res.pow_algorithm = "I'm not sure actually"; break;
|
default: res.pow_algorithm = "I'm not sure actually"; break;
|
||||||
}
|
}
|
||||||
if (res.is_background_mining_enabled)
|
if (res.is_background_mining_enabled)
|
||||||
|
@ -1440,6 +1441,18 @@ namespace cryptonote
|
||||||
LOG_ERROR("Failed to create block template");
|
LOG_ERROR("Failed to create block template");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (b.major_version >= RX_BLOCK_VERSION)
|
||||||
|
{
|
||||||
|
uint64_t seed_height, next_height;
|
||||||
|
crypto::hash seed_hash;
|
||||||
|
crypto::rx_seedheights(res.height, &seed_height, &next_height);
|
||||||
|
seed_hash = m_core.get_block_id_by_height(seed_height);
|
||||||
|
res.seed_hash = string_tools::pod_to_hex(seed_hash);
|
||||||
|
if (next_height != seed_height) {
|
||||||
|
seed_hash = m_core.get_block_id_by_height(next_height);
|
||||||
|
res.next_seed_hash = string_tools::pod_to_hex(seed_hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
store_difficulty(wdiff, res.difficulty, res.wide_difficulty, res.difficulty_top64);
|
store_difficulty(wdiff, res.difficulty, res.wide_difficulty, res.difficulty_top64);
|
||||||
blobdata block_blob = t_serializable_object_to_blob(b);
|
blobdata block_blob = t_serializable_object_to_blob(b);
|
||||||
crypto::public_key tx_pub_key = cryptonote::get_tx_pub_key_from_extra(b.miner_tx);
|
crypto::public_key tx_pub_key = cryptonote::get_tx_pub_key_from_extra(b.miner_tx);
|
||||||
|
@ -1582,7 +1595,7 @@ namespace cryptonote
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
b.nonce = req.starting_nonce;
|
b.nonce = req.starting_nonce;
|
||||||
miner::find_nonce_for_given_block(b, template_res.difficulty, template_res.height);
|
miner::find_nonce_for_given_block(&(m_core.get_blockchain_storage()), b, template_res.difficulty, template_res.height);
|
||||||
|
|
||||||
submit_req.front() = string_tools::buff_to_hex_nodelimer(block_to_blob(b));
|
submit_req.front() = string_tools::buff_to_hex_nodelimer(block_to_blob(b));
|
||||||
r = on_submitblock(submit_req, submit_res, error_resp, ctx);
|
r = on_submitblock(submit_req, submit_res, error_resp, ctx);
|
||||||
|
@ -1627,7 +1640,7 @@ namespace cryptonote
|
||||||
response.reward = get_block_reward(blk);
|
response.reward = get_block_reward(blk);
|
||||||
response.block_size = response.block_weight = m_core.get_blockchain_storage().get_db().get_block_weight(height);
|
response.block_size = response.block_weight = m_core.get_blockchain_storage().get_db().get_block_weight(height);
|
||||||
response.num_txes = blk.tx_hashes.size();
|
response.num_txes = blk.tx_hashes.size();
|
||||||
response.pow_hash = fill_pow_hash ? string_tools::pod_to_hex(get_block_longhash(blk, height)) : "";
|
response.pow_hash = fill_pow_hash ? string_tools::pod_to_hex(get_block_longhash(&(m_core.get_blockchain_storage()), blk, height, 0)) : "";
|
||||||
response.long_term_weight = m_core.get_blockchain_storage().get_db().get_block_long_term_weight(height);
|
response.long_term_weight = m_core.get_blockchain_storage().get_db().get_block_long_term_weight(height);
|
||||||
response.miner_tx_hash = string_tools::pod_to_hex(cryptonote::get_transaction_hash(blk.miner_tx));
|
response.miner_tx_hash = string_tools::pod_to_hex(cryptonote::get_transaction_hash(blk.miner_tx));
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -894,6 +894,8 @@ namespace cryptonote
|
||||||
uint64_t reserved_offset;
|
uint64_t reserved_offset;
|
||||||
uint64_t expected_reward;
|
uint64_t expected_reward;
|
||||||
std::string prev_hash;
|
std::string prev_hash;
|
||||||
|
std::string seed_hash;
|
||||||
|
std::string next_seed_hash;
|
||||||
blobdata blocktemplate_blob;
|
blobdata blocktemplate_blob;
|
||||||
blobdata blockhashing_blob;
|
blobdata blockhashing_blob;
|
||||||
std::string status;
|
std::string status;
|
||||||
|
@ -911,6 +913,8 @@ namespace cryptonote
|
||||||
KV_SERIALIZE(blockhashing_blob)
|
KV_SERIALIZE(blockhashing_blob)
|
||||||
KV_SERIALIZE(status)
|
KV_SERIALIZE(status)
|
||||||
KV_SERIALIZE(untrusted)
|
KV_SERIALIZE(untrusted)
|
||||||
|
KV_SERIALIZE(seed_hash)
|
||||||
|
KV_SERIALIZE(next_seed_hash)
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
typedef epee::misc_utils::struct_init<response_t> response;
|
typedef epee::misc_utils::struct_init<response_t> response;
|
||||||
|
|
|
@ -209,7 +209,7 @@ bool tests::proxy_core::handle_incoming_block(const cryptonote::blobdata& block_
|
||||||
crypto::hash lh;
|
crypto::hash lh;
|
||||||
cout << "BLOCK" << endl << endl;
|
cout << "BLOCK" << endl << endl;
|
||||||
cout << (h = get_block_hash(b)) << endl;
|
cout << (h = get_block_hash(b)) << endl;
|
||||||
cout << (lh = get_block_longhash(b, 0)) << endl;
|
cout << (lh = get_block_longhash(NULL, b, 0, 0)) << endl;
|
||||||
cout << get_transaction_hash(b.miner_tx) << endl;
|
cout << get_transaction_hash(b.miner_tx) << endl;
|
||||||
cout << ::get_object_blobsize(b.miner_tx) << endl;
|
cout << ::get_object_blobsize(b.miner_tx) << endl;
|
||||||
//cout << string_tools::buff_to_hex_nodelimer(block_blob) << endl;
|
//cout << string_tools::buff_to_hex_nodelimer(block_blob) << endl;
|
||||||
|
@ -236,7 +236,7 @@ void tests::proxy_core::get_blockchain_top(uint64_t& height, crypto::hash& top_i
|
||||||
bool tests::proxy_core::init(const boost::program_options::variables_map& /*vm*/) {
|
bool tests::proxy_core::init(const boost::program_options::variables_map& /*vm*/) {
|
||||||
generate_genesis_block(m_genesis, config::GENESIS_TX, config::GENESIS_NONCE);
|
generate_genesis_block(m_genesis, config::GENESIS_TX, config::GENESIS_NONCE);
|
||||||
crypto::hash h = get_block_hash(m_genesis);
|
crypto::hash h = get_block_hash(m_genesis);
|
||||||
add_block(h, get_block_longhash(m_genesis, 0), m_genesis, block_to_blob(m_genesis));
|
add_block(h, get_block_longhash(NULL, m_genesis, 0, 0), m_genesis, block_to_blob(m_genesis));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,7 +186,7 @@ bool test_generator::construct_block(cryptonote::block& blk, uint64_t height, co
|
||||||
|
|
||||||
// Nonce search...
|
// Nonce search...
|
||||||
blk.nonce = 0;
|
blk.nonce = 0;
|
||||||
while (!miner::find_nonce_for_given_block(blk, get_test_difficulty(hf_ver), height))
|
while (!miner::find_nonce_for_given_block(NULL, blk, get_test_difficulty(hf_ver), height))
|
||||||
blk.timestamp++;
|
blk.timestamp++;
|
||||||
|
|
||||||
add_block(blk, txs_weight, block_weights, already_generated_coins, hf_ver ? hf_ver.get() : 1);
|
add_block(blk, txs_weight, block_weights, already_generated_coins, hf_ver ? hf_ver.get() : 1);
|
||||||
|
@ -797,7 +797,7 @@ void fill_tx_sources_and_destinations(const std::vector<test_event_entry>& event
|
||||||
void fill_nonce(cryptonote::block& blk, const difficulty_type& diffic, uint64_t height)
|
void fill_nonce(cryptonote::block& blk, const difficulty_type& diffic, uint64_t height)
|
||||||
{
|
{
|
||||||
blk.nonce = 0;
|
blk.nonce = 0;
|
||||||
while (!miner::find_nonce_for_given_block(blk, diffic, height))
|
while (!miner::find_nonce_for_given_block(NULL, blk, diffic, height))
|
||||||
blk.timestamp++;
|
blk.timestamp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue