Browse Source

RX/0 now worked.

rx
Just Wonder 4 years ago
parent
commit
85c262741b
  1. 156
      src/cn_utils/crypto/rx-slow-hash.c
  2. 81
      src/cn_utils/randomx/aes_hash.cpp
  3. 3
      src/cn_utils/randomx/aes_hash.hpp
  4. 2
      src/cn_utils/randomx/allocator.cpp
  5. 9
      src/cn_utils/randomx/dataset.hpp
  6. 7
      src/cn_utils/randomx/intrin_portable.h
  7. 2
      src/cn_utils/randomx/jit_compiler_a64.hpp
  8. 94
      src/cn_utils/randomx/jit_compiler_a64_static.S
  9. 2
      src/cn_utils/randomx/jit_compiler_fallback.hpp
  10. 2
      src/cn_utils/randomx/jit_compiler_x86.hpp
  11. 27
      src/cn_utils/randomx/randomx.cpp
  12. 20
      src/cn_utils/randomx/randomx.h
  13. 2
      src/cn_utils/randomx/tests/affinity.cpp
  14. 17
      src/cn_utils/randomx/tests/benchmark.cpp
  15. 25
      src/cn_utils/randomx/tests/tests.cpp
  16. 6
      src/cn_utils/randomx/virtual_machine.cpp
  17. 3
      src/cn_utils/randomx/virtual_machine.hpp
  18. 18
      src/primitives/block.cpp

156
src/cn_utils/crypto/rx-slow-hash.c

@ -34,6 +34,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <limits.h>
#include "randomx.h" #include "randomx.h"
#include "c_threads.h" #include "c_threads.h"
@ -50,7 +51,7 @@
typedef struct rx_state { typedef struct rx_state {
CTHR_MUTEX_TYPE rs_mutex; CTHR_MUTEX_TYPE rs_mutex;
char rs_hash[32]; char rs_hash[HASH_SIZE];
uint64_t rs_height; uint64_t rs_height;
randomx_cache *rs_cache; randomx_cache *rs_cache;
} rx_state; } rx_state;
@ -63,7 +64,6 @@ static rx_state rx_s[2] = {{CTHR_MUTEX_INIT,{0},0,0},{CTHR_MUTEX_INIT,{0},0,0}};
static randomx_dataset *rx_dataset; static randomx_dataset *rx_dataset;
static uint64_t rx_dataset_height; static uint64_t rx_dataset_height;
static THREADV randomx_vm *rx_vm = NULL; static THREADV randomx_vm *rx_vm = NULL;
static THREADV int rx_toggle;
static void local_abort(const char *msg) static void local_abort(const char *msg)
{ {
@ -75,84 +75,41 @@ static void local_abort(const char *msg)
#endif #endif
} }
/** static inline int disabled_flags(void) {
* @brief uses cpuid to determine if the CPU supports the AES instructions static int flags = -1;
* @return true if the CPU supports AES, false otherwise
*/
static inline int force_software_aes(void) if (flags != -1) {
{ return flags;
static int use = -1; }
if (use != -1)
return use;
const char *env = getenv("MONERO_USE_SOFTWARE_AES"); const char *env = getenv("MONERO_RANDOMX_UMASK");
if (!env) { if (!env) {
use = 0; flags = 0;
}
else if (!strcmp(env, "0") || !strcmp(env, "no")) {
use = 0;
} }
else { else {
use = 1; char* endptr;
long int value = strtol(env, &endptr, 0);
if (endptr != env && value >= 0 && value < INT_MAX) {
flags = value;
}
else {
flags = 0;
}
} }
return use;
}
static void cpuid(int CPUInfo[4], int InfoType) return flags;
{
#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 enabled_flags(void) {
static int flags = -1;
static inline int use_rx_jit(void) if (flags != -1) {
{ return flags;
#if defined(__x86_64__) }
if (use_rx_jit_flag != -1) flags = randomx_get_flags();
return use_rx_jit_flag;
const char *env = getenv("MONERO_USE_RX_JIT"); return flags;
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_BLOCKS 2048 /* Must be same as BLOCKS_SYNCHRONIZING_MAX_COUNT in cryptonote_config.h */
@ -162,8 +119,11 @@ void rx_reorg(const uint64_t split_height) {
int i; int i;
CTHR_MUTEX_LOCK(rx_mutex); CTHR_MUTEX_LOCK(rx_mutex);
for (i=0; i<2; i++) { for (i=0; i<2; i++) {
if (split_height < rx_s[i].rs_height) if (split_height <= rx_s[i].rs_height) {
if (rx_s[i].rs_height == rx_dataset_height)
rx_dataset_height = 1;
rx_s[i].rs_height = 1; /* set to an invalid seed height */ rx_s[i].rs_height = 1; /* set to an invalid seed height */
}
} }
CTHR_MUTEX_UNLOCK(rx_mutex); CTHR_MUTEX_UNLOCK(rx_mutex);
} }
@ -233,27 +193,27 @@ static void rx_initdata(randomx_cache *rs_cache, const int miners, const uint64_
void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const char *seedhash, const void *data, size_t length, 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) { char *hash, int miners, int is_alt) {
uint64_t s_height = rx_seedheight(mainheight); uint64_t s_height = rx_seedheight(mainheight);
int changed = 0; int toggle = (s_height & SEEDHASH_EPOCH_BLOCKS) != 0;
int toggle = is_alt ? s_height : seedheight; randomx_flags flags = enabled_flags() & ~disabled_flags();
randomx_flags flags = RANDOMX_FLAG_DEFAULT;
rx_state *rx_sp; rx_state *rx_sp;
randomx_cache *cache; randomx_cache *cache;
toggle = (toggle & SEEDHASH_EPOCH_BLOCKS) != 0;
CTHR_MUTEX_LOCK(rx_mutex); CTHR_MUTEX_LOCK(rx_mutex);
/* if alt block but with same seed as mainchain, no need for alt cache */ /* 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))) if (is_alt) {
is_alt = 0; if (s_height == seedheight && !memcmp(rx_s[toggle].rs_hash, seedhash, HASH_SIZE))
is_alt = 0;
} else {
/* RPC could request an earlier block on mainchain */ /* RPC could request an earlier block on mainchain */
if (!is_alt && s_height > seedheight) if (s_height > seedheight)
is_alt = 1; is_alt = 1;
/* miner can be ahead of mainchain */
else if (s_height < seedheight)
toggle ^= 1;
}
toggle ^= (is_alt != 0); toggle ^= (is_alt != 0);
if (toggle != rx_toggle)
changed = 1;
rx_toggle = toggle;
rx_sp = &rx_s[toggle]; rx_sp = &rx_s[toggle];
CTHR_MUTEX_LOCK(rx_sp->rs_mutex); CTHR_MUTEX_LOCK(rx_sp->rs_mutex);
@ -261,40 +221,35 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
cache = rx_sp->rs_cache; cache = rx_sp->rs_cache;
if (cache == NULL) { if (cache == NULL) {
if (use_rx_jit())
flags |= RANDOMX_FLAG_JIT;
if (cache == NULL) { if (cache == NULL) {
cache = randomx_alloc_cache(flags | RANDOMX_FLAG_LARGE_PAGES); cache = randomx_alloc_cache(flags | RANDOMX_FLAG_LARGE_PAGES);
if (cache == NULL) { if (cache == NULL) {
printf("Couldn't use largePages for RandomX cache\n"); //printf("Couldn't use largePages for RandomX cache\n");
cache = randomx_alloc_cache(flags); cache = randomx_alloc_cache(flags);
} }
if (cache == NULL) if (cache == NULL)
local_abort("Couldn't allocate RandomX cache\n"); 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))) { if (rx_sp->rs_height != seedheight || rx_sp->rs_cache == NULL || memcmp(seedhash, rx_sp->rs_hash, HASH_SIZE)) {
randomx_init_cache(cache, seedhash, 32); randomx_init_cache(cache, seedhash, HASH_SIZE);
rx_sp->rs_cache = cache; rx_sp->rs_cache = cache;
rx_sp->rs_height = seedheight; rx_sp->rs_height = seedheight;
memcpy(rx_sp->rs_hash, seedhash, sizeof(rx_sp->rs_hash)); memcpy(rx_sp->rs_hash, seedhash, HASH_SIZE);
changed = 1;
} }
if (rx_vm == NULL) { if (rx_vm == NULL) {
randomx_flags flags = RANDOMX_FLAG_DEFAULT; if ((flags & RANDOMX_FLAG_JIT) && !miners) {
if (use_rx_jit()) { flags |= RANDOMX_FLAG_SECURE & ~disabled_flags();
flags |= RANDOMX_FLAG_JIT; }
if (!miners) if (miners && (disabled_flags() & RANDOMX_FLAG_FULL_MEM)) {
flags |= RANDOMX_FLAG_SECURE; miners = 0;
} }
if(!force_software_aes() && check_aes_hw())
flags |= RANDOMX_FLAG_HARD_AES;
if (miners) { if (miners) {
CTHR_MUTEX_LOCK(rx_dataset_mutex); CTHR_MUTEX_LOCK(rx_dataset_mutex);
if (rx_dataset == NULL) { if (rx_dataset == NULL) {
rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES); rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES);
if (rx_dataset == NULL) { if (rx_dataset == NULL) {
printf("Couldn't use largePages for RandomX dataset\n"); //printf("Couldn't use largePages for RandomX dataset\n");
rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT); rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT);
} }
if (rx_dataset != NULL) if (rx_dataset != NULL)
@ -304,13 +259,13 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
flags |= RANDOMX_FLAG_FULL_MEM; flags |= RANDOMX_FLAG_FULL_MEM;
else { else {
miners = 0; miners = 0;
printf("Couldn't allocate RandomX dataset for miner\n"); //printf("Couldn't allocate RandomX dataset for miner\n");
} }
CTHR_MUTEX_UNLOCK(rx_dataset_mutex); CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
} }
rx_vm = randomx_create_vm(flags | RANDOMX_FLAG_LARGE_PAGES, rx_sp->rs_cache, rx_dataset); 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
printf("Couldn't use largePages for RandomX VM\n"); //printf("Couldn't use largePages for RandomX VM\n");
rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, rx_dataset); rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, rx_dataset);
} }
if(rx_vm == NULL) {//fallback if everything fails if(rx_vm == NULL) {//fallback if everything fails
@ -324,7 +279,8 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
if (rx_dataset != NULL && rx_dataset_height != seedheight) if (rx_dataset != NULL && rx_dataset_height != seedheight)
rx_initdata(cache, miners, seedheight); rx_initdata(cache, miners, seedheight);
CTHR_MUTEX_UNLOCK(rx_dataset_mutex); CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
} else if (changed) { } else {
/* this is a no-op if the cache hasn't changed */
randomx_vm_set_cache(rx_vm, rx_sp->rs_cache); randomx_vm_set_cache(rx_vm, rx_sp->rs_cache);
} }
/* mainchain users can run in parallel */ /* mainchain users can run in parallel */

81
src/cn_utils/randomx/aes_hash.cpp

@ -239,84 +239,3 @@ void fillAes4Rx4(void *state, size_t outputSize, void *buffer) {
template void fillAes4Rx4<true>(void *state, size_t outputSize, void *buffer); template void fillAes4Rx4<true>(void *state, size_t outputSize, void *buffer);
template void fillAes4Rx4<false>(void *state, size_t outputSize, void *buffer); template void fillAes4Rx4<false>(void *state, size_t outputSize, void *buffer);
template<bool softAes>
void hashAndFillAes1Rx4(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state) {
uint8_t* scratchpadPtr = (uint8_t*)scratchpad;
const uint8_t* scratchpadEnd = scratchpadPtr + scratchpadSize;
// initial state
rx_vec_i128 hash_state0 = rx_set_int_vec_i128(AES_HASH_1R_STATE0);
rx_vec_i128 hash_state1 = rx_set_int_vec_i128(AES_HASH_1R_STATE1);
rx_vec_i128 hash_state2 = rx_set_int_vec_i128(AES_HASH_1R_STATE2);
rx_vec_i128 hash_state3 = rx_set_int_vec_i128(AES_HASH_1R_STATE3);
const rx_vec_i128 key0 = rx_set_int_vec_i128(AES_GEN_1R_KEY0);
const rx_vec_i128 key1 = rx_set_int_vec_i128(AES_GEN_1R_KEY1);
const rx_vec_i128 key2 = rx_set_int_vec_i128(AES_GEN_1R_KEY2);
const rx_vec_i128 key3 = rx_set_int_vec_i128(AES_GEN_1R_KEY3);
rx_vec_i128 fill_state0 = rx_load_vec_i128((rx_vec_i128*)fill_state + 0);
rx_vec_i128 fill_state1 = rx_load_vec_i128((rx_vec_i128*)fill_state + 1);
rx_vec_i128 fill_state2 = rx_load_vec_i128((rx_vec_i128*)fill_state + 2);
rx_vec_i128 fill_state3 = rx_load_vec_i128((rx_vec_i128*)fill_state + 3);
constexpr int PREFETCH_DISTANCE = 4096;
const char* prefetchPtr = ((const char*)scratchpad) + PREFETCH_DISTANCE;
scratchpadEnd -= PREFETCH_DISTANCE;
for (int i = 0; i < 2; ++i) {
//process 64 bytes at a time in 4 lanes
while (scratchpadPtr < scratchpadEnd) {
hash_state0 = aesenc<softAes>(hash_state0, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 0));
hash_state1 = aesdec<softAes>(hash_state1, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 1));
hash_state2 = aesenc<softAes>(hash_state2, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 2));
hash_state3 = aesdec<softAes>(hash_state3, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 3));
fill_state0 = aesdec<softAes>(fill_state0, key0);
fill_state1 = aesenc<softAes>(fill_state1, key1);
fill_state2 = aesdec<softAes>(fill_state2, key2);
fill_state3 = aesenc<softAes>(fill_state3, key3);
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 0, fill_state0);
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 1, fill_state1);
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 2, fill_state2);
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 3, fill_state3);
rx_prefetch_t0(prefetchPtr);
scratchpadPtr += 64;
prefetchPtr += 64;
}
prefetchPtr = (const char*) scratchpad;
scratchpadEnd += PREFETCH_DISTANCE;
}
rx_store_vec_i128((rx_vec_i128*)fill_state + 0, fill_state0);
rx_store_vec_i128((rx_vec_i128*)fill_state + 1, fill_state1);
rx_store_vec_i128((rx_vec_i128*)fill_state + 2, fill_state2);
rx_store_vec_i128((rx_vec_i128*)fill_state + 3, fill_state3);
//two extra rounds to achieve full diffusion
rx_vec_i128 xkey0 = rx_set_int_vec_i128(AES_HASH_1R_XKEY0);
rx_vec_i128 xkey1 = rx_set_int_vec_i128(AES_HASH_1R_XKEY1);
hash_state0 = aesenc<softAes>(hash_state0, xkey0);
hash_state1 = aesdec<softAes>(hash_state1, xkey0);
hash_state2 = aesenc<softAes>(hash_state2, xkey0);
hash_state3 = aesdec<softAes>(hash_state3, xkey0);
hash_state0 = aesenc<softAes>(hash_state0, xkey1);
hash_state1 = aesdec<softAes>(hash_state1, xkey1);
hash_state2 = aesenc<softAes>(hash_state2, xkey1);
hash_state3 = aesdec<softAes>(hash_state3, xkey1);
//output hash
rx_store_vec_i128((rx_vec_i128*)hash + 0, hash_state0);
rx_store_vec_i128((rx_vec_i128*)hash + 1, hash_state1);
rx_store_vec_i128((rx_vec_i128*)hash + 2, hash_state2);
rx_store_vec_i128((rx_vec_i128*)hash + 3, hash_state3);
}
template void hashAndFillAes1Rx4<false>(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state);
template void hashAndFillAes1Rx4<true>(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state);

3
src/cn_utils/randomx/aes_hash.hpp

@ -38,6 +38,3 @@ void fillAes1Rx4(void *state, size_t outputSize, void *buffer);
template<bool softAes> template<bool softAes>
void fillAes4Rx4(void *state, size_t outputSize, void *buffer); void fillAes4Rx4(void *state, size_t outputSize, void *buffer);
template<bool softAes>
void hashAndFillAes1Rx4(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state);

2
src/cn_utils/randomx/allocator.cpp

@ -47,7 +47,7 @@ namespace randomx {
rx_aligned_free(ptr); rx_aligned_free(ptr);
} }
template struct AlignedAllocator<CacheLineSize>; template class AlignedAllocator<CacheLineSize>;
void* LargePageAllocator::allocMemory(size_t count) { void* LargePageAllocator::allocMemory(size_t count) {
return allocLargePagesMemory(count); return allocLargePagesMemory(count);

9
src/cn_utils/randomx/dataset.hpp

@ -61,17 +61,8 @@ struct randomx_cache {
//A pointer to a standard-layout struct object points to its initial member //A pointer to a standard-layout struct object points to its initial member
static_assert(std::is_standard_layout<randomx_dataset>(), "randomx_dataset must be a standard-layout struct"); static_assert(std::is_standard_layout<randomx_dataset>(), "randomx_dataset must be a standard-layout struct");
//the following assert fails when compiling Debug in Visual Studio (JIT mode will crash in Debug) //the following assert fails when compiling Debug in Visual Studio (JIT mode will crash in Debug)
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_DEBUG)
#define TO_STR(x) #x
#define STR(x) TO_STR(x)
#pragma message ( __FILE__ "(" STR(__LINE__) ") warning: check std::is_standard_layout<randomx_cache>() is disabled for Debug configuration. JIT mode will crash." )
#undef STR
#undef TO_STR
#else
static_assert(std::is_standard_layout<randomx_cache>(), "randomx_cache must be a standard-layout struct"); static_assert(std::is_standard_layout<randomx_cache>(), "randomx_cache must be a standard-layout struct");
#endif
namespace randomx { namespace randomx {

7
src/cn_utils/randomx/intrin_portable.h

@ -102,7 +102,6 @@ typedef __m128d rx_vec_f128;
#define rx_aligned_alloc(a, b) _mm_malloc(a,b) #define rx_aligned_alloc(a, b) _mm_malloc(a,b)
#define rx_aligned_free(a) _mm_free(a) #define rx_aligned_free(a) _mm_free(a)
#define rx_prefetch_nta(x) _mm_prefetch((const char *)(x), _MM_HINT_NTA) #define rx_prefetch_nta(x) _mm_prefetch((const char *)(x), _MM_HINT_NTA)
#define rx_prefetch_t0(x) _mm_prefetch((const char *)(x), _MM_HINT_T0)
#define rx_load_vec_f128 _mm_load_pd #define rx_load_vec_f128 _mm_load_pd
#define rx_store_vec_f128 _mm_store_pd #define rx_store_vec_f128 _mm_store_pd
@ -202,7 +201,6 @@ typedef union{
#define rx_aligned_alloc(a, b) malloc(a) #define rx_aligned_alloc(a, b) malloc(a)
#define rx_aligned_free(a) free(a) #define rx_aligned_free(a) free(a)
#define rx_prefetch_nta(x) #define rx_prefetch_nta(x)
#define rx_prefetch_t0(x)
/* Splat 64-bit long long to 2 64-bit long longs */ /* Splat 64-bit long long to 2 64-bit long longs */
FORCE_INLINE __m128i vec_splat2sd (int64_t scalar) FORCE_INLINE __m128i vec_splat2sd (int64_t scalar)
@ -401,10 +399,6 @@ inline void rx_prefetch_nta(void* ptr) {
asm volatile ("prfm pldl1strm, [%0]\n" : : "r" (ptr)); asm volatile ("prfm pldl1strm, [%0]\n" : : "r" (ptr));
} }
inline void rx_prefetch_t0(const void* ptr) {
asm volatile ("prfm pldl1strm, [%0]\n" : : "r" (ptr));
}
FORCE_INLINE rx_vec_f128 rx_load_vec_f128(const double* pd) { FORCE_INLINE rx_vec_f128 rx_load_vec_f128(const double* pd) {
return vld1q_f64((const float64_t*)pd); return vld1q_f64((const float64_t*)pd);
} }
@ -538,7 +532,6 @@ typedef union {
#define rx_aligned_alloc(a, b) malloc(a) #define rx_aligned_alloc(a, b) malloc(a)
#define rx_aligned_free(a) free(a) #define rx_aligned_free(a) free(a)
#define rx_prefetch_nta(x) #define rx_prefetch_nta(x)
#define rx_prefetch_t0(x)
FORCE_INLINE rx_vec_f128 rx_load_vec_f128(const double* pd) { FORCE_INLINE rx_vec_f128 rx_load_vec_f128(const double* pd) {
rx_vec_f128 x; rx_vec_f128 x;

2
src/cn_utils/randomx/jit_compiler_a64.hpp

@ -38,7 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace randomx { namespace randomx {
class Program; class Program;
struct ProgramConfiguration; class ProgramConfiguration;
class SuperscalarProgram; class SuperscalarProgram;
class Instruction; class Instruction;

94
src/cn_utils/randomx/jit_compiler_a64_static.S

@ -25,32 +25,26 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # 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. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#if defined(__APPLE__)
#define DECL(x) _##x
#else
#define DECL(x) x
#endif
.arch armv8-a .arch armv8-a
.text .text
.global DECL(randomx_program_aarch64) .global randomx_program_aarch64
.global DECL(randomx_program_aarch64_main_loop) .global randomx_program_aarch64_main_loop
.global DECL(randomx_program_aarch64_vm_instructions) .global randomx_program_aarch64_vm_instructions
.global DECL(randomx_program_aarch64_imul_rcp_literals_end) .global randomx_program_aarch64_imul_rcp_literals_end
.global DECL(randomx_program_aarch64_vm_instructions_end) .global randomx_program_aarch64_vm_instructions_end
.global DECL(randomx_program_aarch64_cacheline_align_mask1) .global randomx_program_aarch64_cacheline_align_mask1
.global DECL(randomx_program_aarch64_cacheline_align_mask2) .global randomx_program_aarch64_cacheline_align_mask2
.global DECL(randomx_program_aarch64_update_spMix1) .global randomx_program_aarch64_update_spMix1
.global DECL(randomx_program_aarch64_vm_instructions_end_light) .global randomx_program_aarch64_vm_instructions_end_light
.global DECL(randomx_program_aarch64_light_cacheline_align_mask) .global randomx_program_aarch64_light_cacheline_align_mask
.global DECL(randomx_program_aarch64_light_dataset_offset) .global randomx_program_aarch64_light_dataset_offset
.global DECL(randomx_init_dataset_aarch64) .global randomx_init_dataset_aarch64
.global DECL(randomx_init_dataset_aarch64_end) .global randomx_init_dataset_aarch64_end
.global DECL(randomx_calc_dataset_item_aarch64) .global randomx_calc_dataset_item_aarch64
.global DECL(randomx_calc_dataset_item_aarch64_prefetch) .global randomx_calc_dataset_item_aarch64_prefetch
.global DECL(randomx_calc_dataset_item_aarch64_mix) .global randomx_calc_dataset_item_aarch64_mix
.global DECL(randomx_calc_dataset_item_aarch64_store_result) .global randomx_calc_dataset_item_aarch64_store_result
.global DECL(randomx_calc_dataset_item_aarch64_end) .global randomx_calc_dataset_item_aarch64_end
#include "configuration.h" #include "configuration.h"
@ -107,7 +101,7 @@
# v31 -> scale mask = 0x81f000000000000081f0000000000000 # v31 -> scale mask = 0x81f000000000000081f0000000000000
.balign 4 .balign 4
DECL(randomx_program_aarch64): randomx_program_aarch64:
# Save callee-saved registers # Save callee-saved registers
sub sp, sp, 192 sub sp, sp, 192
stp x16, x17, [sp] stp x16, x17, [sp]
@ -195,7 +189,7 @@ DECL(randomx_program_aarch64):
ldr q14, literal_v14 ldr q14, literal_v14
ldr q15, literal_v15 ldr q15, literal_v15
DECL(randomx_program_aarch64_main_loop): randomx_program_aarch64_main_loop:
# spAddr0 = spMix1 & ScratchpadL3Mask64; # spAddr0 = spMix1 & ScratchpadL3Mask64;
# spAddr1 = (spMix1 >> 32) & ScratchpadL3Mask64; # spAddr1 = (spMix1 >> 32) & ScratchpadL3Mask64;
lsr x18, x10, 32 lsr x18, x10, 32
@ -268,7 +262,7 @@ DECL(randomx_program_aarch64_main_loop):
orr v23.16b, v23.16b, v30.16b orr v23.16b, v23.16b, v30.16b
# Execute VM instructions # Execute VM instructions
DECL(randomx_program_aarch64_vm_instructions): randomx_program_aarch64_vm_instructions:
# buffer for generated instructions # buffer for generated instructions
# FDIV_M is the largest instruction taking up to 12 ARMv8 instructions # FDIV_M is the largest instruction taking up to 12 ARMv8 instructions
@ -287,7 +281,7 @@ literal_x27: .fill 1,8,0
literal_x28: .fill 1,8,0 literal_x28: .fill 1,8,0
literal_x29: .fill 1,8,0 literal_x29: .fill 1,8,0
literal_x30: .fill 1,8,0 literal_x30: .fill 1,8,0
DECL(randomx_program_aarch64_imul_rcp_literals_end): randomx_program_aarch64_imul_rcp_literals_end:
literal_v0: .fill 2,8,0 literal_v0: .fill 2,8,0
literal_v1: .fill 2,8,0 literal_v1: .fill 2,8,0
@ -306,14 +300,14 @@ literal_v13: .fill 2,8,0
literal_v14: .fill 2,8,0 literal_v14: .fill 2,8,0
literal_v15: .fill 2,8,0 literal_v15: .fill 2,8,0
DECL(randomx_program_aarch64_vm_instructions_end): randomx_program_aarch64_vm_instructions_end:
# mx ^= r[readReg2] ^ r[readReg3]; # mx ^= r[readReg2] ^ r[readReg3];
eor x9, x9, x18 eor x9, x9, x18
# Calculate dataset pointer for dataset prefetch # Calculate dataset pointer for dataset prefetch
mov w18, w9 mov w18, w9
DECL(randomx_program_aarch64_cacheline_align_mask1): randomx_program_aarch64_cacheline_align_mask1:
# Actual mask will be inserted by JIT compiler # Actual mask will be inserted by JIT compiler
and x18, x18, 1 and x18, x18, 1
add x18, x18, x1 add x18, x18, x1
@ -326,12 +320,12 @@ DECL(randomx_program_aarch64_cacheline_align_mask1):
# Calculate dataset pointer for dataset read # Calculate dataset pointer for dataset read
mov w10, w9 mov w10, w9
DECL(randomx_program_aarch64_cacheline_align_mask2): randomx_program_aarch64_cacheline_align_mask2:
# Actual mask will be inserted by JIT compiler # Actual mask will be inserted by JIT compiler
and x10, x10, 1 and x10, x10, 1
add x10, x10, x1 add x10, x10, x1
DECL(randomx_program_aarch64_xor_with_dataset_line): randomx_program_aarch64_xor_with_dataset_line:
# xor integer registers with dataset data # xor integer registers with dataset data
ldp x18, x19, [x10] ldp x18, x19, [x10]
eor x4, x4, x18 eor x4, x4, x18
@ -346,7 +340,7 @@ DECL(randomx_program_aarch64_xor_with_dataset_line):
eor x14, x14, x18 eor x14, x14, x18
eor x15, x15, x19 eor x15, x15, x19
DECL(randomx_program_aarch64_update_spMix1): randomx_program_aarch64_update_spMix1:
# JIT compiler will replace it with "eor x10, config.readReg0, config.readReg1" # JIT compiler will replace it with "eor x10, config.readReg0, config.readReg1"
eor x10, x0, x0 eor x10, x0, x0
@ -367,7 +361,7 @@ DECL(randomx_program_aarch64_update_spMix1):
stp q18, q19, [x16, 32] stp q18, q19, [x16, 32]
subs x3, x3, 1 subs x3, x3, 1
bne DECL(randomx_program_aarch64_main_loop) bne randomx_program_aarch64_main_loop
# Restore x0 # Restore x0
ldr x0, [sp], 16 ldr x0, [sp], 16
@ -401,7 +395,7 @@ DECL(randomx_program_aarch64_update_spMix1):
ret ret
DECL(randomx_program_aarch64_vm_instructions_end_light): randomx_program_aarch64_vm_instructions_end_light:
sub sp, sp, 96 sub sp, sp, 96
stp x0, x1, [sp, 64] stp x0, x1, [sp, 64]
stp x2, x30, [sp, 80] stp x2, x30, [sp, 80]
@ -418,26 +412,26 @@ DECL(randomx_program_aarch64_vm_instructions_end_light):
# x1 -> pointer to output # x1 -> pointer to output
mov x1, sp mov x1, sp
DECL(randomx_program_aarch64_light_cacheline_align_mask): randomx_program_aarch64_light_cacheline_align_mask:
# Actual mask will be inserted by JIT compiler # Actual mask will be inserted by JIT compiler
and w2, w9, 1 and w2, w9, 1
# x2 -> item number # x2 -> item number
lsr x2, x2, 6 lsr x2, x2, 6
DECL(randomx_program_aarch64_light_dataset_offset): randomx_program_aarch64_light_dataset_offset:
# Apply dataset offset (filled in by JIT compiler) # Apply dataset offset (filled in by JIT compiler)
add x2, x2, 0 add x2, x2, 0
add x2, x2, 0 add x2, x2, 0
bl DECL(randomx_calc_dataset_item_aarch64) bl randomx_calc_dataset_item_aarch64
mov x10, sp mov x10, sp
ldp x0, x1, [sp, 64] ldp x0, x1, [sp, 64]
ldp x2, x30, [sp, 80] ldp x2, x30, [sp, 80]
add sp, sp, 96 add sp, sp, 96
b DECL(randomx_program_aarch64_xor_with_dataset_line) b randomx_program_aarch64_xor_with_dataset_line
@ -448,26 +442,26 @@ DECL(randomx_program_aarch64_light_dataset_offset):
# x2 -> start item # x2 -> start item
# x3 -> end item # x3 -> end item
DECL(randomx_init_dataset_aarch64): randomx_init_dataset_aarch64:
# Save x30 (return address) # Save x30 (return address)
str x30, [sp, -16]! str x30, [sp, -16]!
# Load pointer to cache memory # Load pointer to cache memory
ldr x0, [x0] ldr x0, [x0]
DECL(randomx_init_dataset_aarch64_main_loop): randomx_init_dataset_aarch64_main_loop:
bl DECL(randomx_calc_dataset_item_aarch64) bl randomx_calc_dataset_item_aarch64
add x1, x1, 64 add x1, x1, 64
add x2, x2, 1 add x2, x2, 1
cmp x2, x3 cmp x2, x3
bne DECL(randomx_init_dataset_aarch64_main_loop) bne randomx_init_dataset_aarch64_main_loop
# Restore x30 (return address) # Restore x30 (return address)
ldr x30, [sp], 16 ldr x30, [sp], 16
ret ret
DECL(randomx_init_dataset_aarch64_end): randomx_init_dataset_aarch64_end:
# Input parameters # Input parameters
# #
@ -485,7 +479,7 @@ DECL(randomx_init_dataset_aarch64_end):
# x12 -> temporary # x12 -> temporary
# x13 -> temporary # x13 -> temporary
DECL(randomx_calc_dataset_item_aarch64): randomx_calc_dataset_item_aarch64:
sub sp, sp, 112 sub sp, sp, 112
stp x0, x1, [sp] stp x0, x1, [sp]
stp x2, x3, [sp, 16] stp x2, x3, [sp, 16]
@ -532,7 +526,7 @@ DECL(randomx_calc_dataset_item_aarch64):
ldr x12, superscalarAdd7 ldr x12, superscalarAdd7
eor x7, x0, x12 eor x7, x0, x12
b DECL(randomx_calc_dataset_item_aarch64_prefetch) b randomx_calc_dataset_item_aarch64_prefetch
superscalarMul0: .quad 6364136223846793005 superscalarMul0: .quad 6364136223846793005
superscalarAdd1: .quad 9298411001130361340 superscalarAdd1: .quad 9298411001130361340
@ -545,7 +539,7 @@ superscalarAdd7: .quad 9549104520008361294
# Prefetch -> SuperScalar hash -> Mix will be repeated N times # Prefetch -> SuperScalar hash -> Mix will be repeated N times
DECL(randomx_calc_dataset_item_aarch64_prefetch): randomx_calc_dataset_item_aarch64_prefetch:
# Actual mask will be inserted by JIT compiler # Actual mask will be inserted by JIT compiler
and x11, x10, 1 and x11, x10, 1
add x11, x8, x11, lsl 6 add x11, x8, x11, lsl 6
@ -553,7 +547,7 @@ DECL(randomx_calc_dataset_item_aarch64_prefetch):
# Generated SuperScalar hash program goes here # Generated SuperScalar hash program goes here
DECL(randomx_calc_dataset_item_aarch64_mix): randomx_calc_dataset_item_aarch64_mix:
ldp x12, x13, [x11] ldp x12, x13, [x11]
eor x0, x0, x12 eor x0, x0, x12
eor x1, x1, x13 eor x1, x1, x13
@ -567,7 +561,7 @@ DECL(randomx_calc_dataset_item_aarch64_mix):
eor x6, x6, x12 eor x6, x6, x12
eor x7, x7, x13 eor x7, x7, x13
DECL(randomx_calc_dataset_item_aarch64_store_result): randomx_calc_dataset_item_aarch64_store_result:
stp x0, x1, [x9] stp x0, x1, [x9]
stp x2, x3, [x9, 16] stp x2, x3, [x9, 16]
stp x4, x5, [x9, 32] stp x4, x5, [x9, 32]
@ -584,4 +578,4 @@ DECL(randomx_calc_dataset_item_aarch64_store_result):
ret ret
DECL(randomx_calc_dataset_item_aarch64_end): randomx_calc_dataset_item_aarch64_end:

2
src/cn_utils/randomx/jit_compiler_fallback.hpp

@ -36,7 +36,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace randomx { namespace randomx {
class Program; class Program;
struct ProgramConfiguration; class ProgramConfiguration;
class SuperscalarProgram; class SuperscalarProgram;
class JitCompilerFallback { class JitCompilerFallback {

2
src/cn_utils/randomx/jit_compiler_x86.hpp

@ -36,7 +36,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace randomx { namespace randomx {
class Program; class Program;
struct ProgramConfiguration; class ProgramConfiguration;
class SuperscalarProgram; class SuperscalarProgram;
class JitCompilerX86; class JitCompilerX86;
class Instruction; class Instruction;

27
src/cn_utils/randomx/randomx.cpp

@ -363,31 +363,4 @@ extern "C" {
machine->getFinalResult(output, RANDOMX_HASH_SIZE); machine->getFinalResult(output, RANDOMX_HASH_SIZE);
} }
void randomx_calculate_hash_first(randomx_vm* machine, const void* input, size_t inputSize) {
blake2b(machine->tempHash, sizeof(machine->tempHash), input, inputSize, nullptr, 0);
machine->initScratchpad(machine->tempHash);
}
void randomx_calculate_hash_next(randomx_vm* machine, const void* nextInput, size_t nextInputSize, void* output) {
machine->resetRoundingMode();
for (uint32_t chain = 0; chain < RANDOMX_PROGRAM_COUNT - 1; ++chain) {
machine->run(machine->tempHash);
blake2b(machine->tempHash, sizeof(machine->tempHash), machine->getRegisterFile(), sizeof(randomx::RegisterFile), nullptr, 0);
}
machine->run(machine->tempHash);
// Finish current hash and fill the scratchpad for the next hash at the same time
blake2b(machine->tempHash, sizeof(machine->tempHash), nextInput, nextInputSize, nullptr, 0);
machine->hashAndFill(output, RANDOMX_HASH_SIZE, machine->tempHash);
}
void randomx_calculate_hash_last(randomx_vm* machine, void* output) {
machine->resetRoundingMode();
for (int chain = 0; chain < RANDOMX_PROGRAM_COUNT - 1; ++chain) {
machine->run(machine->tempHash);
blake2b(machine->tempHash, sizeof(machine->tempHash), machine->getRegisterFile(), sizeof(randomx::RegisterFile), nullptr, 0);
}
machine->run(machine->tempHash);
machine->getFinalResult(output, RANDOMX_HASH_SIZE);
}
} }

20
src/cn_utils/randomx/randomx.h

@ -30,7 +30,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define RANDOMX_H #define RANDOMX_H
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
#define RANDOMX_HASH_SIZE 32 #define RANDOMX_HASH_SIZE 32
#define RANDOMX_DATASET_ITEM_SIZE 64 #define RANDOMX_DATASET_ITEM_SIZE 64
@ -239,25 +238,6 @@ RANDOMX_EXPORT void randomx_destroy_vm(randomx_vm *machine);
*/ */
RANDOMX_EXPORT void randomx_calculate_hash(randomx_vm *machine, const void *input, size_t inputSize, void *output); RANDOMX_EXPORT void randomx_calculate_hash(randomx_vm *machine, const void *input, size_t inputSize, void *output);
/**
* Set of functions used to calculate multiple RandomX hashes more efficiently.
* randomx_calculate_hash_first will begin a hash calculation.
* randomx_calculate_hash_next will output the hash value of the previous input
* and begin the calculation of the next hash.
* randomx_calculate_hash_last will output the hash value of the previous input.
*
* @param machine is a pointer to a randomx_vm structure. Must not be NULL.
* @param input is a pointer to memory to be hashed. Must not be NULL.
* @param inputSize is the number of bytes to be hashed.
* @param nextInput is a pointer to memory to be hashed for the next hash. Must not be NULL.
* @param nextInputSize is the number of bytes to be hashed for the next hash.
* @param output is a pointer to memory where the hash will be stored. Must not
* be NULL and at least RANDOMX_HASH_SIZE bytes must be available for writing.
*/
RANDOMX_EXPORT void randomx_calculate_hash_first(randomx_vm* machine, const void* input, size_t inputSize);
RANDOMX_EXPORT void randomx_calculate_hash_next(randomx_vm* machine, const void* nextInput, size_t nextInputSize, void* output);
RANDOMX_EXPORT void randomx_calculate_hash_last(randomx_vm* machine, void* output);
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif

2
src/cn_utils/randomx/tests/affinity.cpp

@ -65,7 +65,7 @@ set_thread_affinity(std::thread::native_handle_type thread,
(thread_policy_t)&policy, 1); (thread_policy_t)&policy, 1);
#elif defined(_WIN32) || defined(__CYGWIN__) #elif defined(_WIN32) || defined(__CYGWIN__)
rc = SetThreadAffinityMask(reinterpret_cast<HANDLE>(thread), 1ULL << cpuid) == 0 ? -2 : 0; rc = SetThreadAffinityMask(reinterpret_cast<HANDLE>(thread), 1ULL << cpuid) == 0 ? -2 : 0;
#elif !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__ANDROID__) #elif !defined(__OpenBSD__)
cpu_set_t cs; cpu_set_t cs;
CPU_ZERO(&cs); CPU_ZERO(&cs);
CPU_SET(cpuid, &cs); CPU_SET(cpuid, &cs);

17
src/cn_utils/randomx/tests/benchmark.cpp

@ -122,14 +122,11 @@ void mine(randomx_vm* vm, std::atomic<uint32_t>& atomicNonce, AtomicHash& result
void* noncePtr = blockTemplate + 39; void* noncePtr = blockTemplate + 39;
auto nonce = atomicNonce.fetch_add(1); auto nonce = atomicNonce.fetch_add(1);
store32(noncePtr, nonce);
randomx_calculate_hash_first(vm, blockTemplate, sizeof(blockTemplate));
while (nonce < noncesCount) { while (nonce < noncesCount) {
nonce = atomicNonce.fetch_add(1);
store32(noncePtr, nonce); store32(noncePtr, nonce);
randomx_calculate_hash_next(vm, blockTemplate, sizeof(blockTemplate), &hash); randomx_calculate_hash(vm, blockTemplate, sizeof(blockTemplate), &hash);
result.xorWith(hash); result.xorWith(hash);
nonce = atomicNonce.fetch_add(1);
} }
} }
@ -161,19 +158,13 @@ int main(int argc, char** argv) {
store32(&seed, seedValue); store32(&seed, seedValue);
std::cout << "RandomX benchmark v1.1.7" << std::endl; std::cout << "RandomX benchmark v1.1.5" << std::endl;
if (help) { if (help || (!miningMode && !verificationMode)) {
printUsage(argv[0]); printUsage(argv[0]);
return 0; return 0;
} }
if (!miningMode && !verificationMode) {
std::cout << "Please select either the fast mode (--mine) or the slow mode (--verify)" << std::endl;
std::cout << "Run '" << argv[0] << " --help' to see all supported options" << std::endl;
return 0;
}
std::atomic<uint32_t> atomicNonce(0); std::atomic<uint32_t> atomicNonce(0);
AtomicHash result; AtomicHash result;
std::vector<randomx_vm*> vms; std::vector<randomx_vm*> vms;

25
src/cn_utils/randomx/tests/tests.cpp

@ -1026,6 +1026,9 @@ int main() {
runTest("Hash test 2e (compiler)", RANDOMX_HAVE_COMPILER && stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), test_e); runTest("Hash test 2e (compiler)", RANDOMX_HAVE_COMPILER && stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), test_e);
randomx_destroy_vm(vm);
vm = nullptr;
auto flags = randomx_get_flags(); auto flags = randomx_get_flags();
randomx_release_cache(cache); randomx_release_cache(cache);
@ -1051,28 +1054,6 @@ int main() {
assert(cacheMemory[33554431] == 0x1f47f056d05cd99b); assert(cacheMemory[33554431] == 0x1f47f056d05cd99b);
}); });
runTest("Hash batch test", RANDOMX_HAVE_COMPILER && stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), []() {
char hash1[RANDOMX_HASH_SIZE];
char hash2[RANDOMX_HASH_SIZE];
char hash3[RANDOMX_HASH_SIZE];
initCache("test key 000");
char input1[] = "This is a test";
char input2[] = "Lorem ipsum dolor sit amet";
char input3[] = "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua";
randomx_calculate_hash_first(vm, input1, sizeof(input1) - 1);
randomx_calculate_hash_next(vm, input2, sizeof(input2) - 1, &hash1);
randomx_calculate_hash_next(vm, input3, sizeof(input3) - 1, &hash2);
randomx_calculate_hash_last(vm, &hash3);
assert(equalsHex(hash1, "639183aae1bf4c9a35884cb46b09cad9175f04efd7684e7262a0ac1c2f0b4e3f"));
assert(equalsHex(hash2, "300a0adb47603dedb42228ccb2b211104f4da45af709cd7547cd049e9489c969"));
assert(equalsHex(hash3, "c36d4ed4191e617309867ed66a443be4075014e2b061bcdaf9ce7b721d2b77a8"));
});
randomx_destroy_vm(vm);
vm = nullptr;
if (cache != nullptr) if (cache != nullptr)
randomx_release_cache(cache); randomx_release_cache(cache);

6
src/cn_utils/randomx/virtual_machine.cpp

@ -120,12 +120,6 @@ namespace randomx {
blake2b(out, outSize, &reg, sizeof(RegisterFile), nullptr, 0); blake2b(out, outSize, &reg, sizeof(RegisterFile), nullptr, 0);
} }
template<class Allocator, bool softAes>
void VmBase<Allocator, softAes>::hashAndFill(void* out, size_t outSize, uint64_t *fill_state) {
hashAndFillAes1Rx4<softAes>((void*) getScratchpad(), ScratchpadSize, &reg.a, fill_state);
blake2b(out, outSize, &reg, sizeof(RegisterFile), nullptr, 0);
}
template<class Allocator, bool softAes> template<class Allocator, bool softAes>
void VmBase<Allocator, softAes>::initScratchpad(void* seed) { void VmBase<Allocator, softAes>::initScratchpad(void* seed) {
fillAes1Rx4<softAes>(seed, ScratchpadSize, scratchpad); fillAes1Rx4<softAes>(seed, ScratchpadSize, scratchpad);

3
src/cn_utils/randomx/virtual_machine.hpp

@ -38,7 +38,6 @@ public:
virtual ~randomx_vm() = 0; virtual ~randomx_vm() = 0;
virtual void allocate() = 0; virtual void allocate() = 0;
virtual void getFinalResult(void* out, size_t outSize) = 0; virtual void getFinalResult(void* out, size_t outSize) = 0;
virtual void hashAndFill(void* out, size_t outSize, uint64_t *fill_state) = 0;
virtual void setDataset(randomx_dataset* dataset) { } virtual void setDataset(randomx_dataset* dataset) { }
virtual void setCache(randomx_cache* cache) { } virtual void setCache(randomx_cache* cache) { }
virtual void initScratchpad(void* seed) = 0; virtual void initScratchpad(void* seed) = 0;
@ -68,7 +67,6 @@ protected:
uint64_t datasetOffset; uint64_t datasetOffset;
public: public:
std::string cacheKey; std::string cacheKey;
alignas(16) uint64_t tempHash[8]; //8 64-bit values used to store intermediate data
}; };
namespace randomx { namespace randomx {
@ -80,7 +78,6 @@ namespace randomx {
void allocate() override; void allocate() override;
void initScratchpad(void* seed) override; void initScratchpad(void* seed) override;
void getFinalResult(void* out, size_t outSize) override; void getFinalResult(void* out, size_t outSize) override;
void hashAndFill(void* out, size_t outSize, uint64_t *fill_state) override;
protected: protected:
void generateProgram(void* seed); void generateProgram(void* seed);
}; };

18
src/primitives/block.cpp

@ -40,6 +40,16 @@ unsigned get_max_concurrency()
return max_concurrency; return max_concurrency;
} }
static uint256 cn_get_block_hash_by_height(uint64_t seed_height, char cnHash[32])
{
CBlockIndex* pblockindex = chainActive[seed_height];
uint256 blockHash = pblockindex->GetBlockHash();
const unsigned char* pHash = blockHash.begin();
for (int j = 31; j >= 0; j--) {
cnHash[31 - j] = pHash[j];
}
}
uint256 CBlockHeader::GetOriginalBlockHash() const uint256 CBlockHeader::GetOriginalBlockHash() const
{ {
CHashWriter hashWriter(SER_GETHASH, PROTOCOL_VERSION); CHashWriter hashWriter(SER_GETHASH, PROTOCOL_VERSION);
@ -78,13 +88,13 @@ uint256 CBlockHeader::GetPoWHash() const
uint32_t height = nNonce; uint32_t height = nNonce;
if (cnHeader.major_version >= RX_BLOCK_VERSION) { if (cnHeader.major_version >= RX_BLOCK_VERSION) {
uint64_t seed_height; uint64_t seed_height;
char cnHash[32];
seed_height = crypto::rx_seedheight(height); seed_height = crypto::rx_seedheight(height);
CBlockIndex* pblockindex = chainActive[seed_height]; cn_get_block_hash_by_height(seed_height, cnHash);
crypto::rx_slow_hash(height, seed_height, (const char*)(pblockindex->GetBlockHash().begin()), crypto::rx_slow_hash(height, seed_height, cnHash, blob.data(), blob.size(), BEGIN(thash), get_max_concurrency(), 0);
blob.data(), blob.size(), BEGIN(thash), get_max_concurrency(), 0);
} else { } else {
cn_slow_hash(blob.data(), blob.size(), BEGIN(thash), cnHeader.major_version - 6, 0, height); cn_slow_hash(blob.data(), blob.size(), BEGIN(thash), cnHeader.major_version - 6, 0, height);
} }
return thash; return thash;
} }

Loading…
Cancel
Save