Electroneum
Classes | Macros | Functions | Variables
slow-hash.c File Reference
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include "int-util.h"
#include "hash-ops.h"
#include "oaes_lib.h"
#include "variant2_int_sqrt.h"
#include "variant4_random_math.h"
#include "CryptonightR_JIT.h"
#include <errno.h>
Include dependency graph for slow-hash.c:

Classes

union  cn_slow_hash_state
 

Macros

#define MEMORY   (1 << 21)
 
#define ITER   (1 << 20)
 
#define AES_BLOCK_SIZE   16
 
#define AES_KEY_SIZE   32
 
#define INIT_SIZE_BLK   8
 
#define INIT_SIZE_BYTE   (INIT_SIZE_BLK * AES_BLOCK_SIZE)
 
#define VARIANT1_1(p)
 
#define VARIANT1_2(p)
 
#define VARIANT1_CHECK()
 
#define NONCE_POINTER   (((const uint8_t*)data)+35)
 
#define VARIANT1_PORTABLE_INIT()
 
#define VARIANT1_INIT64()
 
#define VARIANT2_INIT64()
 
#define VARIANT2_PORTABLE_INIT()
 
#define VARIANT2_SHUFFLE_ADD_SSE2(base_ptr, offset)
 
#define VARIANT2_SHUFFLE_ADD_NEON(base_ptr, offset)
 
#define VARIANT2_PORTABLE_SHUFFLE_ADD(out, a_, base_ptr, offset)
 
#define VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr)
 
#define VARIANT2_INTEGER_MATH_SSE2(b, ptr)
 
#define VARIANT2_PORTABLE_INTEGER_MATH(b, ptr)
 
#define VARIANT2_2_PORTABLE()
 
#define VARIANT2_2()
 
#define V4_REG_LOAD(dst, src)
 
#define VARIANT4_RANDOM_MATH_INIT()
 
#define VARIANT4_RANDOM_MATH(a, b, r, _b, _b1)
 
#define hp_jitfunc   ((v4_random_math_JIT_func)NULL)
 
#define U64(x)   ((uint64_t *) (x))
 

Functions

void aesb_single_round (const uint8_t *in, uint8_t *out, const uint8_t *expandedKey)
 
void aesb_pseudo_round (const uint8_t *in, uint8_t *out, const uint8_t *expandedKey)
 
static void local_abort (const char *msg)
 
static int use_v4_jit (void)
 
void slow_hash_allocate_state (void)
 
void slow_hash_free_state (void)
 
static size_t e2i (const uint8_t *a, size_t count)
 
static void mul (const uint8_t *a, const uint8_t *b, uint8_t *res)
 
static void sum_half_blocks (uint8_t *a, const uint8_t *b)
 
static void copy_block (uint8_t *dst, const uint8_t *src)
 
static void swap_blocks (uint8_t *a, uint8_t *b)
 
static void xor_blocks (uint8_t *a, const uint8_t *b)
 
static void xor64 (uint8_t *left, const uint8_t *right)
 
void cn_slow_hash (const void *data, size_t length, char *hash, int variant, int prehashed, uint64_t height)
 

Variables

volatile int use_v4_jit_flag = -1
 
static void(*const extra_hashes [4])(const void *, size_t, char *)
 

Macro Definition Documentation

◆ AES_BLOCK_SIZE

#define AES_BLOCK_SIZE   16

◆ AES_KEY_SIZE

#define AES_KEY_SIZE   32

◆ hp_jitfunc

#define hp_jitfunc   ((v4_random_math_JIT_func)NULL)

◆ INIT_SIZE_BLK

#define INIT_SIZE_BLK   8

◆ INIT_SIZE_BYTE

#define INIT_SIZE_BYTE   (INIT_SIZE_BLK * AES_BLOCK_SIZE)

◆ ITER

#define ITER   (1 << 20)

◆ MEMORY

#define MEMORY   (1 << 21)

◆ NONCE_POINTER

#define NONCE_POINTER   (((const uint8_t*)data)+35)

◆ U64

#define U64 (   x)    ((uint64_t *) (x))

◆ V4_REG_LOAD

#define V4_REG_LOAD (   dst,
  src 
)
Value:
do { \
memcpy((dst), (src), sizeof(v4_reg)); \
if (sizeof(v4_reg) == sizeof(uint32_t)) \
*(dst) = SWAP32LE(*(dst)); \
else \
*(dst) = SWAP64LE(*(dst)); \
} while (0)
uint32_t v4_reg
Definition: variant4_random_math.h:5

◆ VARIANT1_1

#define VARIANT1_1 (   p)
Value:
do if (variant == 1) \
{ \
const uint8_t tmp = ((const uint8_t*)(p))[11]; \
static const uint32_t table = 0x75310; \
const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \
((uint8_t*)(p))[11] = tmp ^ ((table >> index) & 0x30); \
} while(0)

◆ VARIANT1_2

#define VARIANT1_2 (   p)
Value:
do if (variant == 1) \
{ \
xor64(p, tweak1_2); \
} while(0)

◆ VARIANT1_CHECK

#define VARIANT1_CHECK ( )
Value:
do if (length < 43) \
{ \
fprintf(stderr, "Cryptonight variant 1 needs at least 43 bytes of data"); \
_exit(1); \
} while(0)

◆ VARIANT1_INIT64

#define VARIANT1_INIT64 ( )
Value:
if (variant == 1) \
{ \
VARIANT1_CHECK(); \
} \
const uint64_t tweak1_2 = (variant == 1) ? (state.hs.w[24] ^ (*((const uint64_t*)NONCE_POINTER))) : 0
#define NONCE_POINTER
Definition: slow-hash.c:116
Definition: blake256.h:37

◆ VARIANT1_PORTABLE_INIT

#define VARIANT1_PORTABLE_INIT ( )
Value:
uint8_t tweak1_2[8]; \
do if (variant == 1) \
{ \
VARIANT1_CHECK(); \
memcpy(&tweak1_2, &state.hs.b[192], sizeof(tweak1_2)); \
xor64(tweak1_2, NONCE_POINTER); \
} while(0)

◆ VARIANT2_2

#define VARIANT2_2 ( )
Value:
do if (variant == 2 || variant == 3) \
{ \
*U64(local_hp_state + (j ^ 0x10)) ^= SWAP64LE(hi); \
*(U64(local_hp_state + (j ^ 0x10)) + 1) ^= SWAP64LE(lo); \
hi ^= SWAP64LE(*U64(local_hp_state + (j ^ 0x20))); \
lo ^= SWAP64LE(*(U64(local_hp_state + (j ^ 0x20)) + 1)); \
} while (0)
#define U64(x)
Definition: slow-hash.c:1631

◆ VARIANT2_2_PORTABLE

#define VARIANT2_2_PORTABLE ( )
Value:
if (variant == 2 || variant == 3) { \
xor_blocks(long_state + (j ^ 0x10), d); \
xor_blocks(d, long_state + (j ^ 0x20)); \
}
Definition: d.py:1

◆ VARIANT2_INIT64

#define VARIANT2_INIT64 ( )
Value:
uint64_t division_result = 0; \
uint64_t sqrt_result = 0; \
do if (variant >= 2) \
{ \
U64(b)[2] = state.hs.w[8] ^ state.hs.w[10]; \
U64(b)[3] = state.hs.w[9] ^ state.hs.w[11]; \
division_result = state.hs.w[12]; \
sqrt_result = state.hs.w[13]; \
} while (0)
int b
Definition: base.py:1

◆ VARIANT2_INTEGER_MATH_DIVISION_STEP

#define VARIANT2_INTEGER_MATH_DIVISION_STEP (   b,
  ptr 
)
Value:
uint64_t tmpx = division_result ^ (sqrt_result << 32); \
((uint64_t*)(b))[0] ^= SWAP64LE(tmpx); \
{ \
const uint64_t dividend = SWAP64LE(((uint64_t*)(ptr))[1]); \
const uint32_t divisor = (SWAP64LE(((uint64_t*)(ptr))[0]) + (uint32_t)(sqrt_result << 1)) | 0x80000001UL; \
division_result = ((uint32_t)(dividend / divisor)) + \
(((uint64_t)(dividend % divisor)) << 32); \
} \
const uint64_t sqrt_input = SWAP64LE(((uint64_t*)(ptr))[0]) + division_result

◆ VARIANT2_INTEGER_MATH_SSE2

#define VARIANT2_INTEGER_MATH_SSE2 (   b,
  ptr 
)
Value:
do if ((variant == 2) || (variant == 3)) \
{ \
VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr); \
VARIANT2_INTEGER_MATH_SQRT_STEP_SSE2(); \
VARIANT2_INTEGER_MATH_SQRT_FIXUP(sqrt_result); \
} while(0)

◆ VARIANT2_PORTABLE_INIT

#define VARIANT2_PORTABLE_INIT ( )
Value:
uint64_t division_result = 0; \
uint64_t sqrt_result = 0; \
do if (variant >= 2) \
{ \
memcpy(b + AES_BLOCK_SIZE, state.hs.b + 64, AES_BLOCK_SIZE); \
xor64(b + AES_BLOCK_SIZE, state.hs.b + 80); \
xor64(b + AES_BLOCK_SIZE + 8, state.hs.b + 88); \
division_result = SWAP64LE(state.hs.w[12]); \
sqrt_result = SWAP64LE(state.hs.w[13]); \
} while (0)
#define AES_BLOCK_SIZE
Definition: slow-hash.c:51

◆ VARIANT2_PORTABLE_INTEGER_MATH

#define VARIANT2_PORTABLE_INTEGER_MATH (   b,
  ptr 
)
Value:
do if ((variant == 2) || (variant == 3)) \
{ \
VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr); \
VARIANT2_INTEGER_MATH_SQRT_STEP_REF(); \
} while (0)

◆ VARIANT2_PORTABLE_SHUFFLE_ADD

#define VARIANT2_PORTABLE_SHUFFLE_ADD (   out,
  a_,
  base_ptr,
  offset 
)

◆ VARIANT2_SHUFFLE_ADD_NEON

#define VARIANT2_SHUFFLE_ADD_NEON (   base_ptr,
  offset 
)
Value:
do if (variant >= 2) \
{ \
uint64x2_t chunk1 = vld1q_u64(U64((base_ptr) + ((offset) ^ 0x10))); \
const uint64x2_t chunk2 = vld1q_u64(U64((base_ptr) + ((offset) ^ 0x20))); \
const uint64x2_t chunk3 = vld1q_u64(U64((base_ptr) + ((offset) ^ 0x30))); \
vst1q_u64(U64((base_ptr) + ((offset) ^ 0x10)), vaddq_u64(chunk3, vreinterpretq_u64_u8(_b1))); \
vst1q_u64(U64((base_ptr) + ((offset) ^ 0x20)), vaddq_u64(chunk1, vreinterpretq_u64_u8(_b))); \
vst1q_u64(U64((base_ptr) + ((offset) ^ 0x30)), vaddq_u64(chunk2, vreinterpretq_u64_u8(_a))); \
if (variant >= 4) \
{ \
chunk1 = veorq_u64(chunk1, chunk2); \
_c = vreinterpretq_u8_u64(veorq_u64(vreinterpretq_u64_u8(_c), chunk3)); \
_c = vreinterpretq_u8_u64(veorq_u64(vreinterpretq_u64_u8(_c), chunk1)); \
} \
} while (0)

◆ VARIANT2_SHUFFLE_ADD_SSE2

#define VARIANT2_SHUFFLE_ADD_SSE2 (   base_ptr,
  offset 
)
Value:
do if (variant >= 2) \
{ \
__m128i chunk1 = _mm_load_si128((__m128i *)((base_ptr) + ((offset) ^ 0x10))); \
const __m128i chunk2 = _mm_load_si128((__m128i *)((base_ptr) + ((offset) ^ 0x20))); \
const __m128i chunk3 = _mm_load_si128((__m128i *)((base_ptr) + ((offset) ^ 0x30))); \
_mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x10)), _mm_add_epi64(chunk3, _b1)); \
_mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x20)), _mm_add_epi64(chunk1, _b)); \
_mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x30)), _mm_add_epi64(chunk2, _a)); \
if (variant >= 4) \
{ \
chunk1 = _mm_xor_si128(chunk1, chunk2); \
_c = _mm_xor_si128(_c, chunk3); \
_c = _mm_xor_si128(_c, chunk1); \
} \
} while (0)

◆ VARIANT4_RANDOM_MATH

#define VARIANT4_RANDOM_MATH (   a,
  b,
  r,
  _b,
  _b1 
)

◆ VARIANT4_RANDOM_MATH_INIT

#define VARIANT4_RANDOM_MATH_INIT ( )
Value:
v4_reg r[9]; \
int jit = use_v4_jit(); \
do if (variant >= 4) \
{ \
for (int i = 0; i < 4; ++i) \
V4_REG_LOAD(r + i, (uint8_t*)(state.hs.w + 12) + sizeof(v4_reg) * i); \
v4_random_math_init(code, height); \
if (jit) \
{ \
int ret = v4_generate_JIT_code(code, hp_jitfunc, 4096); \
if (ret < 0) \
local_abort("Error generating CryptonightR code"); \
} \
} while (0)
int v4_generate_JIT_code(const struct V4_Instruction *code, v4_random_math_JIT_func buf, const size_t buf_size)
Definition: CryptonightR_JIT.c:58
uint64_t height
Definition: blockchain.cpp:91
#define V4_REG_LOAD(dst, src)
Definition: slow-hash.c:284
#define hp_jitfunc
Definition: slow-hash.c:1588
static int use_v4_jit(void)
Definition: slow-hash.c:71
Definition: variant4_random_math.h:54
@ NUM_INSTRUCTIONS_MAX
Definition: variant4_random_math.h:16

Function Documentation

◆ aesb_pseudo_round()

void aesb_pseudo_round ( const uint8_t *  in,
uint8_t *  out,
const uint8_t *  expandedKey 
)

◆ aesb_single_round()

void aesb_single_round ( const uint8_t *  in,
uint8_t *  out,
const uint8_t *  expandedKey 
)

◆ cn_slow_hash()

void cn_slow_hash ( const void *  data,
size_t  length,
char *  hash,
int  variant,
int  prehashed,
uint64_t  height 
)

◆ copy_block()

static void copy_block ( uint8_t *  dst,
const uint8_t *  src 
)
static

◆ e2i()

static size_t e2i ( const uint8_t *  a,
size_t  count 
)
static

◆ local_abort()

static void local_abort ( const char *  msg)
static

◆ mul()

static void mul ( const uint8_t *  a,
const uint8_t *  b,
uint8_t *  res 
)
static

◆ slow_hash_allocate_state()

void slow_hash_allocate_state ( void  )

◆ slow_hash_free_state()

void slow_hash_free_state ( void  )

◆ sum_half_blocks()

static void sum_half_blocks ( uint8_t *  a,
const uint8_t *  b 
)
static

◆ swap_blocks()

static void swap_blocks ( uint8_t *  a,
uint8_t *  b 
)
static

◆ use_v4_jit()

static int use_v4_jit ( void  )
inlinestatic

◆ xor64()

static void xor64 ( uint8_t *  left,
const uint8_t *  right 
)
static

◆ xor_blocks()

static void xor_blocks ( uint8_t *  a,
const uint8_t *  b 
)
static

Variable Documentation

◆ extra_hashes

void(*const extra_hashes[4])(const void *, size_t, char *) ( const void *  ,
size_t  ,
char *   
)
static
Initial value:
= {
}
void hash_extra_blake(const void *data, size_t length, char *hash)
Definition: hash-extra-blake.c:37
void hash_extra_groestl(const void *data, size_t length, char *hash)
Definition: hash-extra-groestl.c:37
void hash_extra_jh(const void *data, size_t length, char *hash)
Definition: hash-extra-jh.c:40
void hash_extra_skein(const void *data, size_t length, char *hash)
Definition: hash-extra-skein.c:38

◆ use_v4_jit_flag

volatile int use_v4_jit_flag = -1