Skip to content

Commit

Permalink
Merge pull request #2 from vtnerd/monerov7
Browse files Browse the repository at this point in the history
Monero cryptonight variant, version 1
  • Loading branch information
hyc committed Mar 4, 2018
2 parents efa6fed + 14e831d commit 5d422c6
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 23 deletions.
34 changes: 26 additions & 8 deletions cpu-miner.c
Expand Up @@ -120,6 +120,7 @@ enum mining_algo {
ALGO_BLAKE, /* Blake */
ALGO_X11, /* X11 */
ALGO_CRYPTONIGHT, /* CryptoNight */
ALGO_CRYPTONIGHT_MONERO, /* CryptoNight with Monero tweaks */
};

static const char *algo_names[] = {
Expand All @@ -133,6 +134,7 @@ static const char *algo_names[] = {
[ALGO_BLAKE] = "blake",
[ALGO_X11] = "x11",
[ALGO_CRYPTONIGHT] = "cryptonight",
[ALGO_CRYPTONIGHT_MONERO] = "cryptonight-monero",
};

bool opt_debug = false;
Expand All @@ -155,7 +157,7 @@ int opt_timeout = 0;
static int opt_scantime = 5;
static json_t *opt_config;
static const bool opt_time = true;
static enum mining_algo opt_algo = ALGO_CRYPTONIGHT;
static enum mining_algo opt_algo = ALGO_CRYPTONIGHT_MONERO;
static int opt_n_threads;
static int num_processors;
static char *rpc_url;
Expand Down Expand Up @@ -545,6 +547,7 @@ static void share_result(int result, struct work *work, const char *reason) {

switch (opt_algo) {
case ALGO_CRYPTONIGHT:
case ALGO_CRYPTONIGHT_MONERO:
applog(LOG_INFO, "accepted: %lu/%lu (%.2f%%), %.2f H/s at diff %g %s",
accepted_count, accepted_count + rejected_count,
100. * accepted_count / (accepted_count + rejected_count), hashrate,
Expand All @@ -571,6 +574,7 @@ static bool submit_upstream_work(CURL *curl, struct work *work) {
char s[BIG_BUF_LEN];
int i;
bool rc = false;
bool is_monero = opt_algo == ALGO_CRYPTONIGHT_MONERO;

/* pass if the previous hash is not the current previous hash */
if (!submit_old && memcmp(work->data + 1, g_work.data + 1, 32)) {
Expand All @@ -582,14 +586,20 @@ static bool submit_upstream_work(CURL *curl, struct work *work) {
if (have_stratum) {
uint32_t ntime, nonce;
char *ntimestr, *noncestr, *xnonce2str;
int variant;

if (jsonrpc_2) {
variant = is_monero && ((const unsigned char*)work->data)[0] >= 7 ? ((const unsigned char*)work->data)[0] - 6 : 0;
noncestr = bin2hex(((const unsigned char*)work->data) + 39, 4);
char hash[32];
switch(opt_algo) {
case ALGO_CRYPTONIGHT:
case ALGO_CRYPTONIGHT_MONERO:
default:
cryptonight_hash(hash, work->data, work->dlen);
if (!cryptonight_hash(hash, work->data, work->dlen, variant)) {
applog(LOG_ERR, "submit_upstream_work cryptonight_hash failed");
goto out;
}
}
char *hashhex = bin2hex(hash, 32);
snprintf(s, JSON_BUF_LEN,
Expand All @@ -615,6 +625,7 @@ static bool submit_upstream_work(CURL *curl, struct work *work) {
goto out;
}
} else if (have_daemon) {
int variant = is_monero && ((const unsigned char*)work->data)[0] >= 7 ? ((const unsigned char*)work->data)[0] - 6 : 0;
char *noncestr;
time_t work_time;
pthread_mutex_lock(&g_work_lock);
Expand Down Expand Up @@ -654,12 +665,17 @@ static bool submit_upstream_work(CURL *curl, struct work *work) {
} else {
/* build JSON-RPC request */
if(jsonrpc_2) {
int variant = is_monero && ((const unsigned char*)work->data)[0] >= 7 ? ((const unsigned char*)work->data)[0] - 6 : 0;
char *noncestr = bin2hex(((const unsigned char*)work->data) + 39, 4);
char hash[32];
switch(opt_algo) {
case ALGO_CRYPTONIGHT:
case ALGO_CRYPTONIGHT_MONERO:
default:
cryptonight_hash(hash, work->data, work->dlen);
if (!cryptonight_hash(hash, work->data, work->dlen, variant)) {
applog(LOG_ERR, "submit_upstream_work cryptonight_hash failed");
goto out;
}
}
char *hashhex = bin2hex(hash, 32);
snprintf(s, JSON_BUF_LEN,
Expand Down Expand Up @@ -1090,7 +1106,7 @@ static void *miner_thread(void *userdata) {
}*/

persistentctx = persistentctxs[thr_id];
if(!persistentctx && opt_algo == ALGO_CRYPTONIGHT)
if(!persistentctx && (opt_algo == ALGO_CRYPTONIGHT || opt_algo == ALGO_CRYPTONIGHT_MONERO))
{
#if defined __unix__ && (!defined __APPLE__) && (!defined DISABLE_LINUX_HUGEPAGES)
persistentctx = (struct cryptonight_ctx *)mmap(0, sizeof(struct cryptonight_ctx), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0);
Expand Down Expand Up @@ -1167,7 +1183,7 @@ static void *miner_thread(void *userdata) {
max64 = 0xfffLL;
break;
case ALGO_CRYPTONIGHT:

case ALGO_CRYPTONIGHT_MONERO:
max64 = 0x40LL;
break;
default:
Expand Down Expand Up @@ -1199,6 +1215,7 @@ static void *miner_thread(void *userdata) {
/*if (!opt_quiet) {
switch(opt_algo) {
case ALGO_CRYPTONIGHT:
case ALGO_CRYPTONIGHT_MONERO:
applog(LOG_INFO, "thread %d: %lu hashes, %.2f H/s", thr_id,
hashes_done, thr_hashrates[thr_id]);
break;
Expand All @@ -1217,6 +1234,7 @@ static void *miner_thread(void *userdata) {
if (i == opt_n_threads) {
switch(opt_algo) {
case ALGO_CRYPTONIGHT:
case ALGO_CRYPTONIGHT_MONERO:
applog(LOG_INFO, "Total: %s H/s", hashrate);
break;
default:
Expand Down Expand Up @@ -1887,15 +1905,15 @@ static void signal_handler(int sig) {
case SIGINT:
applog(LOG_INFO, "SIGINT received, exiting");
#if defined __unix__ && (!defined __APPLE__)
if(opt_algo == ALGO_CRYPTONIGHT)
if(opt_algo == ALGO_CRYPTONIGHT || opt_algo == ALGO_CRYPTONIGHT_MONERO)
for(i = 0; i < opt_n_threads; i++) munmap(persistentctxs[i], sizeof(struct cryptonight_ctx));
#endif
exit(0);
break;
case SIGTERM:
applog(LOG_INFO, "SIGTERM received, exiting");
#if defined __unix__ && (!defined __APPLE__)
if(opt_algo == ALGO_CRYPTONIGHT)
if(opt_algo == ALGO_CRYPTONIGHT || opt_algo == ALGO_CRYPTONIGHT_MONERO)
for(i = 0; i < opt_n_threads; i++) munmap(persistentctxs[i], sizeof(struct cryptonight_ctx));
#endif
exit(0);
Expand Down Expand Up @@ -2115,7 +2133,7 @@ int main(int argc, char *argv[]) {

applog(LOG_INFO, "workio thread dead, exiting.");
#if defined __unix__ && (!defined __APPLE__)
if(opt_algo == ALGO_CRYPTONIGHT)
if(opt_algo == ALGO_CRYPTONIGHT || opt_algo == ALGO_CRYPTONIGHT_MONERO)
for(i = 0; i < opt_n_threads; i++) munmap(persistentctxs[i], sizeof(struct cryptonight_ctx));
#endif
return 0;
Expand Down
18 changes: 17 additions & 1 deletion cryptonight.h
Expand Up @@ -60,9 +60,25 @@ void do_groestl_hash(const void* input, size_t len, char* output);
void do_jh_hash(const void* input, size_t len, char* output);
void do_skein_hash(const void* input, size_t len, char* output);
void xor_blocks_dst(const uint8_t *restrict a, const uint8_t *restrict b, uint8_t *restrict dst);
void cryptonight_hash_ctx(void* output, const void* input, int inlen, struct cryptonight_ctx* ctx);
int cryptonight_hash_ctx(void* output, const void* input, int inlen, struct cryptonight_ctx* ctx, int variant);
void keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen);
void keccakf(uint64_t st[25], int rounds);
extern void (* const extra_hashes[4])(const void *, size_t, char *);

#define VARIANT1_1(p) \
do if (variant > 0) \
{ \
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)

#define VARIANT1_INIT() \
if (variant > 0 && inlen < 43) \
{ \
return 0; \
} \
const uint64_t tweak1_2 = variant > 0 ? *((const uint64_t*) (((const uint8_t*)input) + 35)) ^ ctx->state.hs.w[24] : 0

#endif
9 changes: 7 additions & 2 deletions cryptonight_aesni.c
Expand Up @@ -85,12 +85,14 @@ static inline void ExpandAESKey256(char *keybuf)
keys[14] = tmp1;
}

void cryptonight_hash_ctx(void *restrict output, const void *restrict input, int inlen, struct cryptonight_ctx *restrict ctx)
int cryptonight_hash_ctx(void *restrict output, const void *restrict input, int inlen, struct cryptonight_ctx *restrict ctx, int variant)
{
keccak((const uint8_t *)input, inlen, &ctx->state.hs, 200);
uint8_t ExpandedKey[256];
size_t i, j;

VARIANT1_INIT();

memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE);
ExpandAESKey256(ExpandedKey);
Expand Down Expand Up @@ -150,6 +152,8 @@ void cryptonight_hash_ctx(void *restrict output, const void *restrict input, int
b_x = _mm_xor_si128(b_x, c_x);
_mm_store_si128((__m128i *)&ctx->long_state[a[0] & 0x1FFFF0], b_x);

VARIANT1_1(&ctx->long_state[a[0] & 0x1FFFF0]);

uint64_t *nextblock = (uint64_t *)&ctx->long_state[c[0] & 0x1FFFF0];
uint64_t b[2];
b[0] = nextblock[0];
Expand All @@ -171,7 +175,7 @@ void cryptonight_hash_ctx(void *restrict output, const void *restrict input, int
}
uint64_t *dst = &ctx->long_state[c[0] & 0x1FFFF0];
dst[0] = a[0];
dst[1] = a[1];
dst[1] = variant > 0 ? a[1] ^ tweak1_2 : a[1];

a[0] ^= b[0];
a[1] ^= b[1];
Expand Down Expand Up @@ -214,4 +218,5 @@ void cryptonight_hash_ctx(void *restrict output, const void *restrict input, int
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
keccakf(&ctx->state.hs, 24);
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
return 1;
}
15 changes: 9 additions & 6 deletions cryptonight_common.c
Expand Up @@ -41,25 +41,28 @@ void xor_blocks_dst(const uint8_t *restrict a, const uint8_t *restrict b, uint8_

void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};

void cryptonight_hash(void* output, const void* input, size_t len) {
int cryptonight_hash(void* output, const void* input, size_t len, int variant) {
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx));
cryptonight_hash_ctx(output, input, len, ctx);
int rc = cryptonight_hash_ctx(output, input, len, ctx, variant);
free(ctx);
return rc;
}

int scanhash_cryptonight(int thr_id, uint32_t *restrict pdata, int dlen, const uint32_t *restrict ptarget, uint32_t max_nonce, unsigned long *restrict hashes_done, struct cryptonight_ctx *persistentctx) {
uint32_t *nonceptr = (uint32_t*) (((char*)pdata) + 39);
int variant = ((const unsigned char*)pdata)[0] >= 7 ? ((const unsigned char*)pdata)[0] - 6 : 0;
uint32_t n = *nonceptr - 1;
const uint32_t first_nonce = n + 1;
const uint64_t Htarg = ((const uint64_t *)ptarget)[3];
uint64_t hash[32 / 8] __attribute__((aligned(64)));

do {
*nonceptr = ++n;
cryptonight_hash_ctx(hash, pdata, dlen, persistentctx);
if (unlikely(hash[3] < Htarg)) {
*hashes_done = n - first_nonce + 1;
return true;
if (cryptonight_hash_ctx(hash, pdata, dlen, persistentctx, variant)) {
if (unlikely(hash[3] < Htarg)) {
*hashes_done = n - first_nonce + 1;
return true;
}
}
} while (likely((n <= max_nonce && !work_restart[thr_id].restart)));

Expand Down
15 changes: 10 additions & 5 deletions cryptonight_lobotomized.c
Expand Up @@ -189,29 +189,31 @@ static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64
return product_lo;
}

static inline void mul_sum_xor_dst(const uint8_t *a, uint8_t *c, uint8_t *dst)
static inline void mul_sum_xor_dst(const uint8_t *a, uint8_t *c, uint8_t *dst, int variant, const uint64_t tweak1_2)
{
uint64_t hi, lo = mul128(((uint64_t *)a)[0], ((uint64_t *)dst)[0], &hi) + ((uint64_t *)c)[1];
hi += ((uint64_t *)c)[0];

((uint64_t *)c)[0] = ((uint64_t*) dst)[0] ^ hi;
((uint64_t *)c)[1] = ((uint64_t*) dst)[1] ^ lo;
((uint64_t *)dst)[0] = hi;
((uint64_t *)dst)[1] = lo;
((uint64_t *)dst)[1] = variant > 0 ? lo ^ tweak1_2 : lo;
}

static inline void xor_blocks(uint8_t *restrict a, const uint8_t *restrict b) {
((uint64_t*) a)[0] ^= ((uint64_t*) b)[0];
((uint64_t*) a)[1] ^= ((uint64_t*) b)[1];
}

void cryptonight_hash_ctx(void *restrict output, const void *restrict input, int inlen, struct cryptonight_ctx *restrict ctx) {
int cryptonight_hash_ctx(void *restrict output, const void *restrict input, int inlen, struct cryptonight_ctx *restrict ctx, int variant) {

ctx->aes_ctx = (oaes_ctx*) oaes_alloc();
size_t i, j;
//hash_process(&ctx->state.hs, (const uint8_t*) input, 76);
keccak((const uint8_t *)input, inlen, &ctx->state.hs, 200);
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);

VARIANT1_INIT();

oaes_key_import_data(ctx->aes_ctx, ctx->state.hs.b, AES_KEY_SIZE);

Expand Down Expand Up @@ -248,13 +250,15 @@ void cryptonight_hash_ctx(void *restrict output, const void *restrict input, int
// Iteration 1
SubAndShiftAndMixAddRound(ctx->c, &ctx->long_state[((uint64_t *)(ctx->a))[0] & 0x1FFFF0], ctx->a);
xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[((uint64_t *)(ctx->a))[0] & 0x1FFFF0]);
VARIANT1_1(&ctx->long_state[((uint64_t *)(ctx->a))[0] & 0x1FFFF0]);
// Iteration 2
mul_sum_xor_dst(ctx->c, ctx->a, &ctx->long_state[((uint64_t *)(ctx->c))[0] & 0x1FFFF0]);
mul_sum_xor_dst(ctx->c, ctx->a, &ctx->long_state[((uint64_t *)(ctx->c))[0] & 0x1FFFF0], variant, tweak1_2);
// Iteration 3
SubAndShiftAndMixAddRound(ctx->b, &ctx->long_state[((uint64_t *)(ctx->a))[0] & 0x1FFFF0], ctx->a);
xor_blocks_dst(ctx->b, ctx->c, &ctx->long_state[((uint64_t *)(ctx->a))[0] & 0x1FFFF0]);
VARIANT1_1(&ctx->long_state[((uint64_t *)(ctx->a))[0] & 0x1FFFF0]);
// Iteration 4
mul_sum_xor_dst(ctx->b, ctx->a, &ctx->long_state[((uint64_t *)(ctx->b))[0] & 0x1FFFF0]);
mul_sum_xor_dst(ctx->b, ctx->a, &ctx->long_state[((uint64_t *)(ctx->b))[0] & 0x1FFFF0], variant, tweak1_2);
}

memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
Expand Down Expand Up @@ -290,4 +294,5 @@ void cryptonight_hash_ctx(void *restrict output, const void *restrict input, int
/*memcpy(hash, &state, 32);*/
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
oaes_free((OAES_CTX **) &ctx->aes_ctx);
return 1;
}
2 changes: 1 addition & 1 deletion miner.h
Expand Up @@ -182,7 +182,7 @@ extern int scanhash_blake(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
extern int scanhash_x11(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
uint32_t max_nonce, unsigned long *hashes_done);

extern void cryptonight_hash(void* output, const void* input, size_t input_len);
extern int cryptonight_hash(void* output, const void* input, size_t input_len, int variant);

extern int scanhash_cryptonight(int thr_id, uint32_t *pdata, int dlen, const uint32_t *ptarget,
uint32_t max_nonce, unsigned long *hashes_done, struct cryptonight_ctx *persistentctx);
Expand Down

0 comments on commit 5d422c6

Please sign in to comment.