diff --git a/src/Miningcore/Crypto/Hashing/Algorithms/MegaBTX.cs b/src/Miningcore/Crypto/Hashing/Algorithms/MegaBTX.cs new file mode 100644 index 000000000..f6fdce53f --- /dev/null +++ b/src/Miningcore/Crypto/Hashing/Algorithms/MegaBTX.cs @@ -0,0 +1,21 @@ +using Miningcore.Contracts; +using Miningcore.Native; + +namespace Miningcore.Crypto.Hashing.Algorithms; + +[Identifier("megabtx")] +public unsafe class MegaBTX : IHashAlgorithm +{ + public void Digest(ReadOnlySpan data, Span result, params object[] extra) + { + Contract.Requires(result.Length >= 32); + + fixed (byte* input = data) + { + fixed (byte* output = result) + { + Multihash.megabtx(input, output, (uint) data.Length); + } + } + } +} diff --git a/src/Miningcore/Native/Multihash.cs b/src/Miningcore/Native/Multihash.cs index c84326c5d..9384d1a65 100644 --- a/src/Miningcore/Native/Multihash.cs +++ b/src/Miningcore/Native/Multihash.cs @@ -196,6 +196,9 @@ public static unsafe class Multihash [DllImport("libmultihash", EntryPoint = "aurum_export", CallingConvention = CallingConvention.Cdecl)] public static extern void aurum(byte* input, void* output, uint inputLength); + [DllImport("libmultihash", EntryPoint = "megabtx_export", CallingConvention = CallingConvention.Cdecl)] + public static extern void megabtx(byte* input, void* output, uint inputLength); + [DllImport("libmultihash", EntryPoint = "cpupower_export", CallingConvention = CallingConvention.Cdecl)] public static extern void cpupower(byte* input, void* output, uint inputLength); diff --git a/src/Native/libmultihash/Makefile b/src/Native/libmultihash/Makefile index bc906f97c..25ce168fc 100644 --- a/src/Native/libmultihash/Makefile +++ b/src/Native/libmultihash/Makefile @@ -4,7 +4,7 @@ LDFLAGS = -shared LDLIBS = -lsodium TARGET = libmultihash.so -OBJECTS = allium.o aurum.o bcrypt.o blake.o c11.o dcrypt.o fresh.o lane.o memehash.o \ +OBJECTS = allium.o aurum.o bcrypt.o blake.o c11.o dcrypt.o fresh.o lane.o megabtx.o memehash.o \ fugue.o groestl.o hefty1.o jh.o keccak.o neoscrypt.o exports.o nist5.o quark.o qubit.o s3.o scryptn.o \ sha256csm.o hmq17.o phi.o \ sha3/aes_helper.o sha3/hamsi.o sha3/hamsi_helper.o sha3/sph_blake.o sha3/sph_bmw.o sha3/sph_cubehash.o \ diff --git a/src/Native/libmultihash/exports.cpp b/src/Native/libmultihash/exports.cpp index b864fa20b..b258398dd 100644 --- a/src/Native/libmultihash/exports.cpp +++ b/src/Native/libmultihash/exports.cpp @@ -66,6 +66,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "shake/cshake.h" #include "shake/shake.h" #include "memehash.h" +#include "megabtx.h" #ifdef _WIN32 #include "blake2/ref/blake2.h" @@ -451,3 +452,8 @@ extern "C" MODULE_API void memehash_export(const char *input, char *output, uint meme_hash(input, output, input_len); } +extern "C" MODULE_API void megabtx_export(const char *input, char *output, uint32_t input_len) +{ + megabtx_hash(input, output, input_len); +} + diff --git a/src/Native/libmultihash/libmultihash.vcxproj b/src/Native/libmultihash/libmultihash.vcxproj index 952eb86f6..577578c0e 100644 --- a/src/Native/libmultihash/libmultihash.vcxproj +++ b/src/Native/libmultihash/libmultihash.vcxproj @@ -211,6 +211,7 @@ + @@ -336,6 +337,7 @@ + diff --git a/src/Native/libmultihash/megabtx.c b/src/Native/libmultihash/megabtx.c new file mode 100644 index 000000000..3c56f796a --- /dev/null +++ b/src/Native/libmultihash/megabtx.c @@ -0,0 +1,374 @@ +#include +#include +#include + +#define HASH_FUNC_BASE_TIMESTAMP_1 1492973331 // Bitcore Genesis +#define HASH_FUNC_COUNT_1 8 +#define HASH_FUNC_COUNT_2 8 +#define HASH_FUNC_COUNT_3 7 +#define HASH_FUNC_VAR_1 3333 +#define HASH_FUNC_VAR_2 2100 +#define HASH_FUNC_COUNT_PERMUTATIONS_7 5040 +#define HASH_FUNC_COUNT_PERMUTATIONS 40320 + +#include "sha3/sph_blake.h" +#include "sha3/sph_bmw.h" +#include "sha3/sph_groestl.h" +#include "sha3/sph_jh.h" +#include "sha3/sph_keccak.h" +#include "sha3/sph_skein.h" +#include "sha3/sph_luffa.h" +#include "sha3/sph_cubehash.h" +#include "sha3/sph_shavite.h" +#include "sha3/sph_simd.h" +#include "sha3/sph_echo.h" +#include "sha3/sph_hamsi.h" +#include "sha3/sph_fugue.h" +#include "sha3/sph_shabal.h" +#include "sha3/sph_whirlpool.h" +#include "sha3/gost_streebog.h" +#include "sha3/sph_haval.h" +#include "sha3/sph_sha2.h" + + +#define _ALIGN(x) __attribute__ ((aligned(x))) + +// helpers +inline void swap(int *a, int *b) { + int c = *a; + *a = *b; + *b = c; +} + +static void reverse(int *pbegin, int *pend) { + while ( (pbegin != pend) && (pbegin != --pend) ) + swap(pbegin++, pend); +} + +static void next_permutation(int *pbegin, int *pend) { + if (pbegin == pend) + return; + + int *i = pbegin; + ++i; + if (i == pend) + return; + + i = pend; + --i; + + while (1) { + int *j = i; + --i; + + if (*i < *j) { + int *k = pend; + + while (!(*i < *--k)) + /* pass */; + + swap(i, k); + reverse(j, pend); + return; // true + } + + if (i == pbegin) { + reverse(pbegin, pend); + return; // false + } + } +} + +void megabtx_hash(const char* input, char* output, uint32_t len) +{ + uint32_t _ALIGN(64) hash[23]; + uint32_t *work_data = (uint32_t *)input; + const uint32_t timestamp = work_data[17]; + + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_skein512_context ctx_skein; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_hamsi512_context ctx_hamsi; + sph_fugue512_context ctx_fugue; + sph_shabal512_context ctx_shabal; + sph_whirlpool_context ctx_whirlpool; + sph_sha512_context ctx_sha512; + sph_gost512_context ctx_gost; + sph_haval256_5_context ctx_haval; + + uint32_t permutation_1[HASH_FUNC_COUNT_1]; + uint32_t permutation_2[HASH_FUNC_COUNT_2 + HASH_FUNC_COUNT_1]; + uint32_t permutation_3[HASH_FUNC_COUNT_3 + HASH_FUNC_COUNT_2 + HASH_FUNC_COUNT_1]; + + //Init1 + for (uint32_t i = 1; i < HASH_FUNC_COUNT_1; i++) { + permutation_1[i] = i; + } + + //Init2 + for (uint32_t i = HASH_FUNC_COUNT_1; i < HASH_FUNC_COUNT_2 + HASH_FUNC_COUNT_1; i++) { + permutation_2[i] = i; + } + + //Init3 + for (uint32_t i = HASH_FUNC_COUNT_1 + HASH_FUNC_COUNT_2; i < HASH_FUNC_COUNT_3 + HASH_FUNC_COUNT_2 + HASH_FUNC_COUNT_1; i++) { + permutation_3[i] = i; + } + + uint32_t steps_1 = (timestamp - HASH_FUNC_BASE_TIMESTAMP_1) % HASH_FUNC_COUNT_PERMUTATIONS_7; + for (uint32_t i = 0; i < steps_1; i++) { + next_permutation(permutation_1, permutation_1 + HASH_FUNC_COUNT_1); + } + + uint32_t steps_2 = (timestamp+ HASH_FUNC_VAR_1 - HASH_FUNC_BASE_TIMESTAMP_1) % HASH_FUNC_COUNT_PERMUTATIONS; + for (uint32_t i = 0; i < steps_2; i++) { + next_permutation(permutation_2 + HASH_FUNC_COUNT_1, permutation_2 + HASH_FUNC_COUNT_1 + HASH_FUNC_COUNT_2); + } + + uint32_t steps_3 = (timestamp+ HASH_FUNC_VAR_2 - HASH_FUNC_BASE_TIMESTAMP_1) % HASH_FUNC_COUNT_PERMUTATIONS_7; + for (uint32_t i = 0; i < steps_3; i++) { + next_permutation(permutation_3 + HASH_FUNC_COUNT_1 + HASH_FUNC_COUNT_2, permutation_3 + HASH_FUNC_COUNT_1 + HASH_FUNC_COUNT_2 + HASH_FUNC_COUNT_3); + } + + int lenToHash = 64; + + sph_blake512_init(&ctx_blake); + sph_blake512 (&ctx_blake, input, len); + sph_blake512_close(&ctx_blake, hash); + + for (int i = 1; i < HASH_FUNC_COUNT_1; i++) { + switch (permutation_1[i]) { + case 1: + // 3000 + 700 + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, hash, lenToHash ); + sph_echo512_close(&ctx_echo, hash); + + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, hash, 64); + sph_blake512_close(&ctx_blake, hash); + break; + case 2: + // 700 +3500 + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, hash, lenToHash); + sph_simd512_close(&ctx_simd, hash); + + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, hash, 64); + sph_bmw512_close(&ctx_bmw, hash); + break; + case 3: + // 4000 + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, hash, lenToHash); + sph_groestl512_close(&ctx_groestl, hash); + break; + case 4: + // 2000 + 2100 + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, hash, lenToHash); + sph_whirlpool_close(&ctx_whirlpool, hash); + + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, hash, 64); + sph_jh512_close(&ctx_jh, hash); + break; + case 5: + // 1000 + 700 + sph_gost512_init(&ctx_gost); + sph_gost512 (&ctx_gost, hash, lenToHash);; + sph_gost512_close(&ctx_gost, hash); + + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + break; + case 6: + // 1000 + 4000 + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, hash, lenToHash); + sph_fugue512_close(&ctx_fugue, hash); + + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, hash, 64); + sph_skein512_close(&ctx_skein, hash); + break; + case 7: + // 1800 + 2000 + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, hash, lenToHash); + sph_shavite512_close(&ctx_shavite, hash); + + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close(&ctx_luffa, hash); + break; + } + } + for (int i = HASH_FUNC_COUNT_1; i < HASH_FUNC_COUNT_1 + HASH_FUNC_COUNT_2; i++) { + switch (permutation_2[i]) { + case 8: + // 2100 +2000 + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, hash, lenToHash); + sph_whirlpool_close(&ctx_whirlpool, hash); + + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, hash, 64); + sph_cubehash512_close(&ctx_cubehash, hash); + break; + case 9: + // 1800 + 2100 + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, hash, lenToHash); + sph_jh512_close(&ctx_jh, hash); + + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, hash, 64); + sph_shavite512_close(&ctx_shavite, hash); + break; + case 10: + // 3500 + 700 + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, hash, lenToHash); + sph_blake512_close(&ctx_blake, hash); + + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, hash, 64); + sph_simd512_close(&ctx_simd, hash); + break; + case 11: + // 3000 + 1000 + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, hash, lenToHash); + sph_shabal512_close(&ctx_shabal, hash); + + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, hash, 64); + sph_echo512_close(&ctx_echo, hash); + break; + case 12: + // 5000 + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, hash, lenToHash); + sph_hamsi512_close(&ctx_hamsi, hash); + break; + case 13: + // 4000 + 700 + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, hash, lenToHash); + sph_bmw512_close(&ctx_bmw, hash); + + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, hash, 64); + sph_fugue512_close(&ctx_fugue, hash); + break; + case 14: + // 1000 +1000 + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, hash, lenToHash);; + sph_keccak512_close(&ctx_keccak, hash); + + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, hash, 64); + sph_shabal512_close(&ctx_shabal, hash); + break; + case 15: + // 2000 + 2000 + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, hash, lenToHash); + sph_luffa512_close(&ctx_luffa, hash); + + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, hash, 64); + sph_whirlpool_close(&ctx_whirlpool, hash); + break; + } + } + for (int i = HASH_FUNC_COUNT_2; i < HASH_FUNC_COUNT_1 + HASH_FUNC_COUNT_2 + HASH_FUNC_COUNT_3; i++) { + switch (permutation_3[i]) { + case 16: + // 700 + 2000 + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512, hash, lenToHash); + sph_sha512_close(&ctx_sha512, hash); + + sph_haval256_5_init(&ctx_haval); + sph_haval256_5 (&ctx_haval, hash, 64); + sph_haval256_5_close(&ctx_haval, hash); + break; + case 17: + // 4000 + 700 + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, hash, lenToHash); + sph_skein512_close(&ctx_skein, hash); + + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, hash, 64); + sph_groestl512_close(&ctx_groestl, hash); + break; + case 18: + // 700 + 5000 + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, hash, lenToHash); + sph_simd512_close(&ctx_simd, hash); + + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, hash, 64); + sph_hamsi512_close(&ctx_hamsi, hash); + break; + case 19: + // 1000 + 2000 + sph_gost512_init(&ctx_gost); + sph_gost512 (&ctx_gost, hash, lenToHash);; + sph_gost512_close(&ctx_gost, hash); + + sph_haval256_5_init(&ctx_haval); + sph_haval256_5 (&ctx_haval, hash, 64); + sph_haval256_5_close(&ctx_haval, hash); + break; + case 20: + // 2100 + 700 + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, hash, lenToHash); + sph_cubehash512_close(&ctx_cubehash, hash); + + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512, hash, 64); + sph_sha512_close(&ctx_sha512, hash); + break; + case 21: + // 1800 + 3000 + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, hash, lenToHash); + sph_echo512_close(&ctx_echo, hash); + + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, hash, 64); + sph_shavite512_close(&ctx_shavite, hash); + break; + case 22: + // 2000 + 1000 + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, hash, lenToHash); + sph_luffa512_close(&ctx_luffa, hash); + + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, hash, 64); + sph_shabal512_close(&ctx_shabal, hash);; + break; + } + + } + + memcpy(output, hash, 32); +} diff --git a/src/Native/libmultihash/megabtx.h b/src/Native/libmultihash/megabtx.h new file mode 100644 index 000000000..b33772e01 --- /dev/null +++ b/src/Native/libmultihash/megabtx.h @@ -0,0 +1,16 @@ +#ifndef MEGABTX_H +#define MEGABTX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void megabtx_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif