Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updates for the monero-v1 pow tweaks #88

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions cpu-miner.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ enum algos {
ALGO_X14, /* X14 */
ALGO_X15, /* X15 Whirlpool */
ALGO_CRYPTONIGHT, /* CryptoNight */
ALGO_CRYPTONIGHT_MONERO, /* CryptoNight with Monero tweaks */
};

static const char *algo_names[] = {
Expand All @@ -131,6 +132,7 @@ static const char *algo_names[] = {
[ALGO_X14] = "x14",
[ALGO_X15] = "x15",
[ALGO_CRYPTONIGHT] = "cryptonight",
[ALGO_CRYPTONIGHT_MONERO] = "cryptonight-monero",
};

bool opt_debug = false;
Expand Down Expand Up @@ -215,6 +217,7 @@ Options:\n\
x14 X14\n\
x15 X15\n\
cryptonight CryptoNight\n\
cryptonight-monero CryptoNight with Monero variants\n\
-o, --url=URL URL of mining server\n\
-O, --userpass=U:P username:password pair for mining server\n\
-u, --user=USERNAME username for mining server\n\
Expand Down Expand Up @@ -560,6 +563,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 @@ -585,6 +589,7 @@ static bool submit_upstream_work(CURL *curl, struct work *work) {
char s[JSON_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 @@ -596,14 +601,21 @@ static bool submit_upstream_work(CURL *curl, struct work *work) {
if (have_stratum) {
uint32_t ntime, nonce;
char *ntimestr, *noncestr, *xnonce2str;
bool is_monero = opt_algo == ALGO_CRYPTONIGHT_MONERO;
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, 76);
if (!cryptonight_hash(hash, work->data, 76, 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 @@ -631,12 +643,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, 76);
if (!cryptonight_hash(hash, work->data, 76, 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 @@ -1128,6 +1145,7 @@ static void *miner_thread(void *userdata) {
max64 = opt_scrypt_n < 16 ? 0x3ffff : 0x3fffff / opt_scrypt_n;
break;
case ALGO_CRYPTONIGHT:
case ALGO_CRYPTONIGHT_MONERO:
max64 = 0x40LL;
break;
case ALGO_FRESH:
Expand Down Expand Up @@ -1215,6 +1233,7 @@ static void *miner_thread(void *userdata) {
&hashes_done);
break;
case ALGO_CRYPTONIGHT:
case ALGO_CRYPTONIGHT_MONERO:
rc = scanhash_cryptonight(thr_id, work.data, work.target,
max_nonce, &hashes_done);
break;
Expand All @@ -1236,6 +1255,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 @@ -1254,6 +1274,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 @@ -1852,7 +1873,7 @@ int main(int argc, char *argv[]) {
init_quarkhash_contexts();
} else if (opt_algo == ALGO_BLAKE) {
init_blakehash_contexts();
} else if(opt_algo == ALGO_CRYPTONIGHT) {
} else if(opt_algo == ALGO_CRYPTONIGHT || opt_algo == ALGO_CRYPTONIGHT_MONERO) {
jsonrpc_2 = true;
aes_ni_supported = has_aes_ni();
applog(LOG_INFO, "Using JSON-RPC 2.0");
Expand Down
55 changes: 47 additions & 8 deletions cryptonight.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,29 @@ typedef __uint128_t uint128_t;
#define INIT_SIZE_BLK 8
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE)

#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_2(p) \
do if (variant > 0) \
{ \
((uint64_t*)p)[1] ^= tweak1_2; \
} while(0)

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


#pragma pack(push, 1)
union cn_slow_hash_state {
union hash_state hs;
Expand Down Expand Up @@ -112,12 +135,14 @@ struct cryptonight_ctx {
oaes_ctx* aes_ctx;
};

void cryptonight_hash_ctx(void* output, const void* input, size_t len, struct cryptonight_ctx* ctx) {
int cryptonight_hash_ctx(void* output, const void* input, size_t len, struct cryptonight_ctx* ctx, int variant) {
hash_process(&ctx->state.hs, (const uint8_t*) input, len);
ctx->aes_ctx = (oaes_ctx*) oaes_alloc();
size_t i, j;
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);
for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) {
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 0], ctx->aes_ctx->key->exp_data);
Expand All @@ -143,14 +168,18 @@ void cryptonight_hash_ctx(void* output, const void* input, size_t len, struct cr
j = e2i(ctx->a);
aesb_single_round(&ctx->long_state[j], ctx->c, ctx->a);
xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j]);
VARIANT1_1(&ctx->long_state[j]);
/* Iteration 2 */
mul_sum_xor_dst(ctx->c, ctx->a, &ctx->long_state[e2i(ctx->c)]);
VARIANT1_2(&ctx->long_state[e2i(ctx->c)]);
/* Iteration 3 */
j = e2i(ctx->a);
aesb_single_round(&ctx->long_state[j], ctx->b, ctx->a);
xor_blocks_dst(ctx->b, ctx->c, &ctx->long_state[j]);
VARIANT1_1(&ctx->long_state[j]);
/* Iteration 4 */
mul_sum_xor_dst(ctx->b, ctx->a, &ctx->long_state[e2i(ctx->b)]);
VARIANT1_2(&ctx->long_state[e2i(ctx->b)]);
}

memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
Expand Down Expand Up @@ -178,20 +207,24 @@ void cryptonight_hash_ctx(void* output, const void* input, size_t len, struct cr
/*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;
}

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);
const int rc = cryptonight_hash_ctx(output, input, len, ctx, variant);
free(ctx);
return rc;
}

void cryptonight_hash_ctx_aes_ni(void* output, const void* input, size_t len, struct cryptonight_ctx* ctx) {
int cryptonight_hash_ctx_aes_ni(void* output, const void* input, size_t len, struct cryptonight_ctx* ctx, int variant) {
hash_process(&ctx->state.hs, (const uint8_t*) input, len);
ctx->aes_ctx = (oaes_ctx*) oaes_alloc();
size_t i, j;
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);
for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) {
fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 0], ctx->aes_ctx->key->exp_data);
Expand All @@ -217,14 +250,18 @@ void cryptonight_hash_ctx_aes_ni(void* output, const void* input, size_t len, st
j = e2i(ctx->a);
fast_aesb_single_round(&ctx->long_state[j], ctx->c, ctx->a);
xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j]);
VARIANT1_1(&ctx->long_state[j]);
/* Iteration 2 */
mul_sum_xor_dst(ctx->c, ctx->a, &ctx->long_state[e2i(ctx->c)]);
VARIANT1_2(&ctx->long_state[j]);
/* Iteration 3 */
j = e2i(ctx->a);
fast_aesb_single_round(&ctx->long_state[j], ctx->b, ctx->a);
xor_blocks_dst(ctx->b, ctx->c, &ctx->long_state[j]);
VARIANT1_1(&ctx->long_state[j]);
/* Iteration 4 */
mul_sum_xor_dst(ctx->b, ctx->a, &ctx->long_state[e2i(ctx->b)]);
VARIANT1_2(&ctx->long_state[j]);
}

memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
Expand Down Expand Up @@ -252,12 +289,14 @@ void cryptonight_hash_ctx_aes_ni(void* output, const void* input, size_t len, st
/*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;
}

int scanhash_cryptonight(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
uint32_t max_nonce, uint64_t *hashes_done) {
uint32_t *nonceptr = (uint32_t*) (((char*)pdata) + 39);
uint32_t n = *nonceptr - 1;
int variant = ((const unsigned char*)pdata)[0] >= 7 ? ((const unsigned char*)pdata)[0] - 6 : 0;
const uint32_t first_nonce = n + 1;
const uint32_t Htarg = ptarget[7];
uint32_t hash[HASH_SIZE / 4] __attribute__((aligned(32)));
Expand All @@ -267,8 +306,8 @@ int scanhash_cryptonight(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
if (aes_ni_supported) {
do {
*nonceptr = ++n;
cryptonight_hash_ctx_aes_ni(hash, pdata, 76, ctx);
if (unlikely(hash[7] < ptarget[7])) {
const int rc = cryptonight_hash_ctx_aes_ni(hash, pdata, 76, ctx, variant);
if (likely(rc) && unlikely(hash[7] < ptarget[7])) {
*hashes_done = n - first_nonce + 1;
free(ctx);
return true;
Expand All @@ -277,8 +316,8 @@ int scanhash_cryptonight(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
} else {
do {
*nonceptr = ++n;
cryptonight_hash_ctx(hash, pdata, 76, ctx);
if (unlikely(hash[7] < ptarget[7])) {
const int rc = cryptonight_hash_ctx(hash, pdata, 76, ctx, variant);
if (likely(rc) && unlikely(hash[7] < ptarget[7])) {
*hashes_done = n - first_nonce + 1;
free(ctx);
return true;
Expand Down
2 changes: 1 addition & 1 deletion miner.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ extern int scanhash_x14(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
extern int scanhash_x15(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
uint32_t max_nonce, uint64_t *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, const uint32_t *ptarget,
uint32_t max_nonce, uint64_t *hashes_done);
Expand Down