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

please add cryptonight-asc #17

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
90 changes: 90 additions & 0 deletions multihashing.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,31 @@ NAN_METHOD(cryptonight_heavy) {
info.GetReturnValue().Set(returnValue);
}

NAN_METHOD(cryptonight_asc) {
if (info.Length() < 1) return THROW_ERROR_EXCEPTION("You must provide one argument.");

Local<Object> target = info[0]->ToObject();
if (!Buffer::HasInstance(target)) return THROW_ERROR_EXCEPTION("Argument 1 should be a buffer object.");

int variant = 0;

if (info.Length() >= 2) {
if (!info[1]->IsNumber()) return THROW_ERROR_EXCEPTION("Argument 2 should be a number");
variant = Nan::To<int>(info[1]).FromMaybe(0);
}

char output[32];
init_ctx();
switch (variant) {
case 0: cryptonight_single_hash_asc<xmrig::CRYPTONIGHT_ASC, SOFT_AES, xmrig::VARIANT_0 >(reinterpret_cast<const uint8_t*>(Buffer::Data(target)), Buffer::Length(target), reinterpret_cast<uint8_t*>(output), &ctx);
break;
default: cryptonight_single_hash_asc<xmrig::CRYPTONIGHT_ASC, SOFT_AES, xmrig::VARIANT_0 >(reinterpret_cast<const uint8_t*>(Buffer::Data(target)), Buffer::Length(target), reinterpret_cast<uint8_t*>(output), &ctx);
}

v8::Local<v8::Value> returnValue = Nan::CopyBuffer(output, 32).ToLocalChecked();
info.GetReturnValue().Set(returnValue);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class CCryptonightAsync : public Nan::AsyncWorker {
Expand Down Expand Up @@ -360,6 +385,69 @@ NAN_METHOD(cryptonight_heavy_async) {
Nan::AsyncQueueWorker(new CCryptonightHeavyAsync(callback, Buffer::Data(target), Buffer::Length(target), variant));
}

class CCryptonightAscAsync : public Nan::AsyncWorker {

private:

struct cryptonight_ctx* m_ctx;
const char* const m_input;
const uint32_t m_input_len;
const int m_variant;
char m_output[32];

public:

CCryptonightAscAsync(Nan::Callback* const callback, const char* const input, const uint32_t input_len, const int variant)
: Nan::AsyncWorker(callback), m_ctx(static_cast<cryptonight_ctx *>(_mm_malloc(sizeof(cryptonight_ctx), 16))),
m_input(input), m_input_len(input_len), m_variant(variant) {
m_ctx->memory = static_cast<uint8_t *>(_mm_malloc(xmrig::CRYPTONIGHT_ASC_MEMORY, 4096));
}

~CCryptonightAscAsync() {
_mm_free(m_ctx->memory);
_mm_free(m_ctx);
}

void Execute () {
switch (m_variant) {
case 0: cryptonight_single_hash_asc<xmrig::CRYPTONIGHT_ASC, SOFT_AES, xmrig::VARIANT_0 >(reinterpret_cast<const uint8_t*>(m_input), m_input_len, reinterpret_cast<uint8_t*>(m_output), &m_ctx);
break;
default: cryptonight_single_hash_asc<xmrig::CRYPTONIGHT_ASC, SOFT_AES, xmrig::VARIANT_0 >(reinterpret_cast<const uint8_t*>(m_input), m_input_len, reinterpret_cast<uint8_t*>(m_output), &m_ctx);
}
}

void HandleOKCallback () {
Nan::HandleScope scope;

v8::Local<v8::Value> argv[] = {
Nan::Null(),
v8::Local<v8::Value>(Nan::CopyBuffer(m_output, 32).ToLocalChecked())
};
callback->Call(2, argv, async_resource);
}
};

NAN_METHOD(cryptonight_Asc_async) {
if (info.Length() < 2) return THROW_ERROR_EXCEPTION("You must provide at least two arguments.");

Local<Object> target = info[0]->ToObject();
if (!Buffer::HasInstance(target)) return THROW_ERROR_EXCEPTION("Argument should be a buffer object.");

int variant = 0;

int callback_arg_num;
if (info.Length() >= 3) {
if (!info[1]->IsNumber()) return THROW_ERROR_EXCEPTION("Argument 2 should be a number");
variant = Nan::To<int>(info[1]).FromMaybe(0);
callback_arg_num = 2;
} else {
callback_arg_num = 1;
}

Callback *callback = new Nan::Callback(info[callback_arg_num].As<v8::Function>());
Nan::AsyncQueueWorker(new CCryptonightAscAsync(callback, Buffer::Data(target), Buffer::Length(target), variant));
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Expand All @@ -370,6 +458,8 @@ NAN_MODULE_INIT(init) {
Nan::Set(target, Nan::New("cryptonight_light_async").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(cryptonight_light_async)).ToLocalChecked());
Nan::Set(target, Nan::New("cryptonight_heavy").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(cryptonight_heavy)).ToLocalChecked());
Nan::Set(target, Nan::New("cryptonight_heavy_async").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(cryptonight_heavy_async)).ToLocalChecked());
Nan::Set(target, Nan::New("cryptonight_asc").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(cryptonight_asc)).ToLocalChecked());
Nan::Set(target, Nan::New("cryptonight_asc_async").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(cryptonight_asc_async)).ToLocalChecked());
}

NODE_MODULE(cryptonight, init)
5 changes: 3 additions & 2 deletions xmrig/common/xmrig.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ enum Algo {
INVALID_ALGO = -1,
CRYPTONIGHT, /* CryptoNight (Monero) */
CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */
CRYPTONIGHT_HEAVY /* CryptoNight-Heavy (RYO) */
CRYPTONIGHT_HEAVY, /* CryptoNight-Heavy (RYO) */
CRYPTONIGHT_ASC /* CryptoNight-ASC (TAX) */
};


Expand All @@ -59,7 +60,7 @@ enum AlgoVariant {

enum Variant {
VARIANT_AUTO = -1, // Autodetect
VARIANT_0 = 0, // Original CryptoNight or CryptoNight-Heavy
VARIANT_0 = 0, // Original CryptoNight or CryptoNight-Heavy or CryptoNight-ASC
VARIANT_1 = 1, // CryptoNight variant 1 also known as Monero7 and CryptoNightV7
VARIANT_TUBE = 2, // Modified CryptoNight-Heavy (TUBE only)
VARIANT_XTL = 3, // Modified CryptoNight variant 1 (Stellite only)
Expand Down
58 changes: 37 additions & 21 deletions xmrig/crypto/CryptoNight_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,16 @@ constexpr const size_t CRYPTONIGHT_HEAVY_MEMORY = 4 * 1024 * 1024;
constexpr const uint32_t CRYPTONIGHT_HEAVY_MASK = 0x3FFFF0;
constexpr const uint32_t CRYPTONIGHT_HEAVY_ITER = 0x40000;

constexpr const size_t CRYPTONIGHT_ASC_MEMORY = 2 * 1024 * 1024;
constexpr const uint32_t CRYPTONIGHT_ASC_MASK = 0x1FFFF0;
constexpr const uint32_t CRYPTONIGHT_ASC_ITER = 0x4000;

template<Algo ALGO> inline constexpr size_t cn_select_memory() { return 0; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT>() { return CRYPTONIGHT_MEMORY; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT_LITE>() { return CRYPTONIGHT_LITE_MEMORY; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT_HEAVY>() { return CRYPTONIGHT_HEAVY_MEMORY; }

template<Algo ALGO> inline constexpr size_t cn_select_memory() { return 0; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT>() { return CRYPTONIGHT_MEMORY; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT_LITE>() { return CRYPTONIGHT_LITE_MEMORY; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT_HEAVY>() { return CRYPTONIGHT_HEAVY_MEMORY; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT_ASC>() { return CRYPTONIGHT_ASC_MEMORY; }


inline size_t cn_select_memory(Algo algorithm)
Expand All @@ -69,6 +74,9 @@ inline size_t cn_select_memory(Algo algorithm)
case CRYPTONIGHT_HEAVY:
return CRYPTONIGHT_HEAVY_MEMORY;

case CRYPTONIGHT_ASC:
return CRYPTONIGHT_ASC_MEMORY;

default:
break;
}
Expand All @@ -77,10 +85,11 @@ inline size_t cn_select_memory(Algo algorithm)
}


template<Algo ALGO> inline constexpr uint32_t cn_select_mask() { return 0; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT>() { return CRYPTONIGHT_MASK; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT_LITE>() { return CRYPTONIGHT_LITE_MASK; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT_HEAVY>() { return CRYPTONIGHT_HEAVY_MASK; }
template<Algo ALGO> inline constexpr uint32_t cn_select_mask() { return 0; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT>() { return CRYPTONIGHT_MASK; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT_LITE>() { return CRYPTONIGHT_LITE_MASK; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT_HEAVY>() { return CRYPTONIGHT_HEAVY_MASK; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT_ASC>() { return CRYPTONIGHT_ASC_MASK; }


inline uint32_t cn_select_mask(Algo algorithm)
Expand All @@ -96,6 +105,9 @@ inline uint32_t cn_select_mask(Algo algorithm)
case CRYPTONIGHT_HEAVY:
return CRYPTONIGHT_HEAVY_MASK;

case CRYPTONIGHT_ASC:
return CRYPTONIGHT_ASC_MASK;

default:
break;
}
Expand All @@ -104,19 +116,20 @@ inline uint32_t cn_select_mask(Algo algorithm)
}


template<Algo ALGO, Variant variant> inline constexpr uint32_t cn_select_iter() { return 0; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_0>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_1>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_2>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_XTL>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_MSR>() { return CRYPTONIGHT_MSR_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_XAO>() { return CRYPTONIGHT_XAO_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_RTO>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_LITE, VARIANT_0>() { return CRYPTONIGHT_LITE_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_LITE, VARIANT_1>() { return CRYPTONIGHT_LITE_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_HEAVY, VARIANT_0>() { return CRYPTONIGHT_HEAVY_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_HEAVY, VARIANT_XHV>() { return CRYPTONIGHT_HEAVY_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_HEAVY, VARIANT_TUBE>() { return CRYPTONIGHT_HEAVY_ITER; }
template<Algo ALGO, Variant variant> inline constexpr uint32_t cn_select_iter() { return 0; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_0>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_1>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_2>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_XTL>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_MSR>() { return CRYPTONIGHT_MSR_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_XAO>() { return CRYPTONIGHT_XAO_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_RTO>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_LITE, VARIANT_0>() { return CRYPTONIGHT_LITE_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_LITE, VARIANT_1>() { return CRYPTONIGHT_LITE_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_HEAVY, VARIANT_0>() { return CRYPTONIGHT_HEAVY_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_HEAVY, VARIANT_XHV>() { return CRYPTONIGHT_HEAVY_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_HEAVY, VARIANT_TUBE>() { return CRYPTONIGHT_HEAVY_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_ASC, VARIANT_0>() { return CRYPTONIGHT_ASC_ITER; }


inline uint32_t cn_select_iter(Algo algorithm, Variant variant)
Expand All @@ -143,6 +156,9 @@ inline uint32_t cn_select_iter(Algo algorithm, Variant variant)
case CRYPTONIGHT_HEAVY:
return CRYPTONIGHT_HEAVY_ITER;

case CRYPTONIGHT_ASC:
return CRYPTONIGHT_ASC_ITER;

default:
break;
}
Expand Down
81 changes: 77 additions & 4 deletions xmrig/crypto/CryptoNight_x86.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
xin6 = _mm_load_si128(input + 10);
xin7 = _mm_load_si128(input + 11);

if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
if (ALGO == xmrig::CRYPTONIGHT_HEAVY || ALGO == xmrig::CRYPTONIGHT_ASC) {
for (size_t i = 0; i < 16; i++) {
aes_round<SOFT_AES>(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
Expand Down Expand Up @@ -328,12 +328,12 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);

if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
if (ALGO == xmrig::CRYPTONIGHT_HEAVY || ALGO == xmrig::CRYPTONIGHT_ASC) {
mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7);
}
}

if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
if (ALGO == xmrig::CRYPTONIGHT_HEAVY || ALGO == xmrig::CRYPTONIGHT_ASC) {
for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) {
xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
Expand Down Expand Up @@ -449,6 +449,78 @@ static inline void cryptonight_monero_tweak(uint64_t* mem_out, const uint8_t* l,
}
}

template<xmrig::Algo ALGO, bool SOFT_AES, xmrig::Variant VARIANT>
inline void cryptonight_single_hash_asc(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
{
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO, VARIANT>();
constexpr size_t MEM = xmrig::cn_select_memory<ALGO>();
constexpr bool IS_V1 = xmrig::cn_base_variant<VARIANT>() == xmrig::VARIANT_1;

if (IS_V1 && size < 43) {
memset(output, 0, 32);
return;
}
if (VARIANT == xmrig::VARIANT_ASC) {

hash_process(&ctx->state.hs, (const uint8_t*) input, len);
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
memcpy(ctx->aes_key, ctx->state.hs.b, FD_SETSIZE);
ctx->aes_ctx = (oaes_ctx*) oaes_alloc();
size_t i, j;

VARIANT1_INIT();

oaes_key_import_data(ctx->aes_ctx, ctx->aes_key, AES_KEY_SIZE);
for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
aesb_pseudo_round(&ctx->text[AES_BLOCK_SIZE * j],
&ctx->text[AES_BLOCK_SIZE * j],
ctx->aes_ctx->key->exp_data);
}
memcpy(&ctx->long_state[i * INIT_SIZE_BYTE], ctx->text, INIT_SIZE_BYTE);
}

for (i = 0; i < 16; i++) {
ctx->a[i] = ctx->state.k[i] ^ ctx->state.k[32 + i];
ctx->b[i] = ctx->state.k[16 + i] ^ ctx->state.k[48 + i];
}

for (i = 0; i < ITER / 2; i++) {
/* Dependency chain: address -> read value ------+
* written value <-+ hard function (AES or MUL) <+
* next address <-+
*/
/* Iteration 1 */
j = e2i(ctx->a);
aesb_single_round(&ctx->long_state[j * AES_BLOCK_SIZE], ctx->c, ctx->a);
xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j * AES_BLOCK_SIZE]);
VARIANT1_1((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]);
/* Iteration 2 */
mul_sum_xor_dst(ctx->c, ctx->a,
&ctx->long_state[e2i(ctx->c) * AES_BLOCK_SIZE]);
copy_block(ctx->b, ctx->c);

}

memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
oaes_key_import_data(ctx->aes_ctx, &ctx->state.hs.b[32], AES_KEY_SIZE);
for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
xor_blocks(&ctx->text[j * AES_BLOCK_SIZE],
&ctx->long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
aesb_pseudo_round(&ctx->text[j * AES_BLOCK_SIZE],
&ctx->text[j * AES_BLOCK_SIZE],
ctx->aes_ctx->key->exp_data);
}
}
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
hash_permutation(&ctx->state.hs);
/*memcpy(hash, &state, 32);*/
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
oaes_free((OAES_CTX **) &ctx->aes_ctx);
}


template<xmrig::Algo ALGO, bool SOFT_AES, xmrig::Variant VARIANT>
inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
Expand Down Expand Up @@ -553,7 +625,8 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
}
bx0 = cx;
}



cn_implode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx[0]->memory, (__m128i*) ctx[0]->state);

xmrig::keccakf(h0, 24);
Expand Down