Prechádzať zdrojové kódy

introduce RandomX v2 with double-hashing

tevador 3 rokov pred
rodič
commit
db273f2671

+ 11 - 0
src/randomx.cpp

@@ -400,4 +400,15 @@ extern "C" {
 		machine->run(machine->tempHash);
 		machine->getFinalResult(output, RANDOMX_HASH_SIZE);
 	}
+
+	void randomx_calculate_hash_v2(const void* input, size_t inputSize, const void* v1_in, void* v2_out) {
+		assert(inputSize == 0 || input != nullptr);
+		assert(v1_in != nullptr);
+		assert(v2_out != nullptr);
+		blake2b_state state;
+		blake2b_init(&state, RANDOMX_HASH_SIZE);
+		blake2b_update(&state, input, inputSize);
+		blake2b_update(&state, v1_in, RANDOMX_HASH_SIZE);
+		blake2b_final(&state, v2_out, RANDOMX_HASH_SIZE);
+	}
 }

+ 11 - 0
src/randomx.h

@@ -260,6 +260,17 @@ RANDOMX_EXPORT void randomx_calculate_hash_first(randomx_vm* machine, const void
 RANDOMX_EXPORT void randomx_calculate_hash_next(randomx_vm* machine, const void* nextInput, size_t nextInputSize, void* output);
 RANDOMX_EXPORT void randomx_calculate_hash_last(randomx_vm* machine, void* output);
 
+/**
+ * Calculate V2 hash from the V1 hash and its input.
+ *
+ * @param input is a pointer to memory that was hashed by V1. Must not be NULL.
+ * @param inputSize is the number of bytes in the input.
+ * @param v1_in is the V1 hash (RANDOMX_HASH_SIZE bytes).
+ * @param output is a pointer to memory where the V2 hash will be stored. Must not
+ *        be NULL and at least RANDOMX_HASH_SIZE bytes must be available for writing.
+*/
+RANDOMX_EXPORT void randomx_calculate_hash_v2(const void* input, size_t inputSize, const void* v1_in, void* v2_out);
+
 #if defined(__cplusplus)
 }
 #endif

+ 25 - 7
src/tests/benchmark.cpp

@@ -96,6 +96,7 @@ void printUsage(const char* executable) {
 	std::cout << "  --avx2        use optimized Argon2 for AVX2 CPUs" << std::endl;
 	std::cout << "  --auto        select the best options for the current CPU" << std::endl;
 	std::cout << "  --noBatch     calculate hashes one by one (default: batch)" << std::endl;
+	std::cout << "  --v2          calculate v2 hashes (default: v1)" << std::endl;
 }
 
 struct MemoryException : public std::exception {
@@ -113,7 +114,7 @@ struct DatasetAllocException : public MemoryException {
 
 using MineFunc = void(randomx_vm * vm, std::atomic<uint32_t> & atomicNonce, AtomicHash & result, uint32_t noncesCount, int thread, int cpuid);
 
-template<bool batch>
+template<bool batch, bool v2>
 void mine(randomx_vm* vm, std::atomic<uint32_t>& atomicNonce, AtomicHash& result, uint32_t noncesCount, int thread, int cpuid = -1) {
 	if (cpuid >= 0) {
 		int rc = set_thread_affinity(cpuid);
@@ -138,6 +139,9 @@ void mine(randomx_vm* vm, std::atomic<uint32_t>& atomicNonce, AtomicHash& result
 		}
 		store32(noncePtr, nonce);
 		(batch ? randomx_calculate_hash_next : randomx_calculate_hash)(vm, blockTemplate, sizeof(blockTemplate), &hash);
+		if (v2) {
+			randomx_calculate_hash_v2(blockTemplate, sizeof(blockTemplate), &hash, &hash);
+		}
 		result.xorWith(hash);
 		if (!batch) {
 			nonce = atomicNonce.fetch_add(1);
@@ -146,7 +150,7 @@ void mine(randomx_vm* vm, std::atomic<uint32_t>& atomicNonce, AtomicHash& result
 }
 
 int main(int argc, char** argv) {
-	bool softAes, miningMode, verificationMode, help, largePages, jit, secure;
+	bool softAes, miningMode, verificationMode, help, largePages, jit, secure, v2;
 	bool ssse3, avx2, autoFlags, noBatch;
 	int noncesCount, threadCount, initThreadCount;
 	uint64_t threadAffinity;
@@ -172,10 +176,11 @@ int main(int argc, char** argv) {
 	readOption("--avx2", argc, argv, avx2);
 	readOption("--auto", argc, argv, autoFlags);
 	readOption("--noBatch", argc, argv, noBatch);
+	readOption("--v2", argc, argv, v2);
 
 	store32(&seed, seedValue);
 
-	std::cout << "RandomX benchmark v1.1.11" << std::endl;
+	std::cout << "RandomX benchmark v1.1.12" << std::endl;
 
 	if (help) {
 		printUsage(argv[0]);
@@ -280,11 +285,24 @@ int main(int argc, char** argv) {
 	MineFunc* func;
 
 	if (noBatch) {
-		func = &mine<false>;
+		if (v2) {
+			std::cout << " - v2 hashes" << std::endl;
+			func = &mine<false, true>;
+		}
+		else {
+			func = &mine<false, false>;
+		}
 	}
 	else {
-		func = &mine<true>;
-		std::cout << " - batch mode" << std::endl;
+		if (v2) {
+			//TODO: support batch mode with v2
+			std::cout << " - v2 hashes" << std::endl;
+			func = &mine<false, true>;
+		}
+		else {
+			std::cout << " - batch mode" << std::endl;
+			func = &mine<true, false>;
+		}
 	}
 
 	std::cout << "Initializing";
@@ -376,7 +394,7 @@ int main(int argc, char** argv) {
 			randomx_release_cache(cache);
 		std::cout << "Calculated result: ";
 		result.print(std::cout);
-		if (noncesCount == 1000 && seedValue == 0)
+		if (noncesCount == 1000 && seedValue == 0 && !v2)
 			std::cout << "Reference result:  10b649a3f15c7c7f88277812f2e74b337a0f20ce909af09199cccb960771cfa1" << std::endl;
 		if (!miningMode) {
 			std::cout << "Performance: " << 1000 * elapsed / noncesCount << " ms per hash" << std::endl;

+ 24 - 0
src/tests/tests.cpp

@@ -34,6 +34,14 @@ void calcStringHash(const char(&key)[K], const char(&input)[H], void* output) {
 	randomx_calculate_hash(vm, input, H - 1, output);
 }
 
+template<size_t K, size_t H>
+void calcStringHashV2(const char(&key)[K], const char(&input)[H], void* output) {
+	initCache(key);
+	assert(vm != nullptr);
+	randomx_calculate_hash(vm, input, H - 1, output);
+	randomx_calculate_hash_v2(input, H - 1, output, output);
+}
+
 template<size_t K, size_t H>
 void calcHexHash(const char(&key)[K], const char(&hex)[H], void* output) {
 	initCache(key);
@@ -1082,6 +1090,22 @@ int main() {
 		assert(rx_get_rounding_mode() == RoundToNearest);
 	});
 
+	if (RANDOMX_HAVE_COMPILER) {
+		randomx_destroy_vm(vm);
+		vm = nullptr;
+#ifdef RANDOMX_FORCE_SECURE
+		vm = randomx_create_vm(RANDOMX_FLAG_DEFAULT | RANDOMX_FLAG_SECURE, cache, nullptr);
+#else
+		vm = randomx_create_vm(RANDOMX_FLAG_DEFAULT, cache, nullptr);
+#endif
+	}
+
+	runTest("RandomX v2 hash test", stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), []() {
+		char hash[RANDOMX_HASH_SIZE];
+		calcStringHashV2("test key 000", "This is a test", &hash);
+		assert(equalsHex(hash, "d53ccf348b75291b7be76f0a7ac8208bbced734b912f6fca60539ab6f86be919"));
+	});
+
 	randomx_destroy_vm(vm);
 	vm = nullptr;
 

+ 1 - 1
vcxproj/randomx.vcxproj

@@ -156,7 +156,7 @@ SET ERRORLEVEL = 0</Command>
     <ClCompile Include="..\src\reciprocal.c" />
     <ClCompile Include="..\src\soft_aes.cpp" />
     <ClCompile Include="..\src\virtual_machine.cpp" />
-    <ClCompile Include="..\src\virtual_memory.cpp" />
+    <ClCompile Include="..\src\virtual_memory.c" />
   </ItemGroup>
   <ItemGroup>
     <MASM Include="..\src\jit_compiler_x86_static.asm" />

+ 1 - 1
vcxproj/randomx.vcxproj.filters

@@ -72,7 +72,7 @@
     <ClCompile Include="..\src\vm_interpreted.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\src\virtual_memory.cpp">
+    <ClCompile Include="..\src\virtual_memory.c">
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="..\src\blake2_generator.cpp">