From a93f6c73e2a4d7c26daf1c36a7165f3c87ffb65e Mon Sep 17 00:00:00 2001 From: jon4hz Date: Mon, 30 Jan 2023 15:39:23 +0100 Subject: [PATCH 1/5] chore: idk what changed? --- src/Native/libetchash/libetchash.sln | 62 ++-- src/Native/libetchash/libetchash.vcxproj | 402 +++++++++++----------- src/Native/libubqhash/libubqhash.sln | 62 ++-- src/Native/libubqhash/libubqhash.vcxproj | 408 +++++++++++------------ 4 files changed, 467 insertions(+), 467 deletions(-) diff --git a/src/Native/libetchash/libetchash.sln b/src/Native/libetchash/libetchash.sln index 3490adb5fe..9264baf453 100644 --- a/src/Native/libetchash/libetchash.sln +++ b/src/Native/libetchash/libetchash.sln @@ -1,31 +1,31 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31229.75 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmultihash", "libetchash.vcxproj", "{2DE74E14-BF6D-4046-951B-8EBC8A1BA009}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x64.ActiveCfg = Debug|x64 - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x64.Build.0 = Debug|x64 - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x86.ActiveCfg = Debug|Win32 - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x86.Build.0 = Debug|Win32 - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x64.ActiveCfg = Release|x64 - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x64.Build.0 = Release|x64 - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x86.ActiveCfg = Release|Win32 - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {DDE0FE54-030A-4DFD-98A1-952779FB461F} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31229.75 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmultihash", "libetchash.vcxproj", "{2DE74E14-BF6D-4046-951B-8EBC8A1BA009}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x64.ActiveCfg = Debug|x64 + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x64.Build.0 = Debug|x64 + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x86.ActiveCfg = Debug|Win32 + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x86.Build.0 = Debug|Win32 + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x64.ActiveCfg = Release|x64 + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x64.Build.0 = Release|x64 + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x86.ActiveCfg = Release|Win32 + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {DDE0FE54-030A-4DFD-98A1-952779FB461F} + EndGlobalSection +EndGlobal diff --git a/src/Native/libetchash/libetchash.vcxproj b/src/Native/libetchash/libetchash.vcxproj index 160fd65676..22b28c95df 100644 --- a/src/Native/libetchash/libetchash.vcxproj +++ b/src/Native/libetchash/libetchash.vcxproj @@ -1,202 +1,202 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942} - Win32Proj - netmultihashnative - 10.0 - libetchash - - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) - $(SolutionDir)\..\..\..\..\boost_1_62_0\lib32-msvc-14.0;$(LibraryPath) - - - true - $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) - $(SolutionDir)\..\..\..\..\boost_1_62_0\lib64-msvc-14.0;$(ProjectDir)..\libethhash\windows\lib\x64;$(LibraryPath) - - - false - $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) - $(SolutionDir)\..\..\..\..\boost_1_62_0\lib32-msvc-14.0;$(LibraryPath) - - - false - $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) - $(SolutionDir)\..\..\..\..\boost_1_62_0\lib64-msvc-14.0;$(LibraryPath) - - - - - - Level3 - Disabled - SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 - true - MultiThreadedDebug - stdcpp14 - - - Windows - true - Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x86\libsodium.lib;%(AdditionalDependencies) - - - - - - - Level3 - Disabled - SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 - true - MultiThreadedDebug - stdcpp14 - - - Windows - true - Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x64\libsodium.lib;%(AdditionalDependencies) - - - - - - - Level3 - MaxSpeed - true - true - SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 - true - MultiThreaded - stdcpp14 - - - Windows - true - true - true - Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x86\libsodium.lib;%(AdditionalDependencies) - - - - - - - Level3 - MaxSpeed - true - true - SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 - true - MultiThreaded - stdcpp14 - - - Windows - true - true - true - Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x64\libsodium.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942} + Win32Proj + netmultihashnative + 10.0 + libetchash + + + + DynamicLibrary + true + v143 + Unicode + + + DynamicLibrary + false + v143 + true + Unicode + + + DynamicLibrary + true + v143 + Unicode + + + DynamicLibrary + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) + $(SolutionDir)\..\..\..\..\boost_1_62_0\lib32-msvc-14.0;$(LibraryPath) + + + true + $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) + $(SolutionDir)\..\..\..\..\boost_1_62_0\lib64-msvc-14.0;$(ProjectDir)..\libethhash\windows\lib\x64;$(LibraryPath) + + + false + $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) + $(SolutionDir)\..\..\..\..\boost_1_62_0\lib32-msvc-14.0;$(LibraryPath) + + + false + $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) + $(SolutionDir)\..\..\..\..\boost_1_62_0\lib64-msvc-14.0;$(LibraryPath) + + + + + + Level3 + Disabled + SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 + true + MultiThreadedDebug + stdcpp14 + + + Windows + true + Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x86\libsodium.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 + true + MultiThreadedDebug + stdcpp14 + + + Windows + true + Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x64\libsodium.lib;%(AdditionalDependencies) + + + + + + + Level3 + MaxSpeed + true + true + SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 + true + MultiThreaded + stdcpp14 + + + Windows + true + true + true + Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x86\libsodium.lib;%(AdditionalDependencies) + + + + + + + Level3 + MaxSpeed + true + true + SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 + true + MultiThreaded + stdcpp14 + + + Windows + true + true + true + Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x64\libsodium.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Native/libubqhash/libubqhash.sln b/src/Native/libubqhash/libubqhash.sln index 895257b66e..f8af08e076 100644 --- a/src/Native/libubqhash/libubqhash.sln +++ b/src/Native/libubqhash/libubqhash.sln @@ -1,31 +1,31 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31229.75 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmultihash", "libubqhash.vcxproj", "{2DE74E14-BF6D-4046-951B-8EBC8A1BA009}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x64.ActiveCfg = Debug|x64 - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x64.Build.0 = Debug|x64 - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x86.ActiveCfg = Debug|Win32 - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x86.Build.0 = Debug|Win32 - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x64.ActiveCfg = Release|x64 - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x64.Build.0 = Release|x64 - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x86.ActiveCfg = Release|Win32 - {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {DDE0FE54-030A-4DFD-98A1-952779FB461F} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31229.75 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmultihash", "libubqhash.vcxproj", "{2DE74E14-BF6D-4046-951B-8EBC8A1BA009}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x64.ActiveCfg = Debug|x64 + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x64.Build.0 = Debug|x64 + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x86.ActiveCfg = Debug|Win32 + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Debug|x86.Build.0 = Debug|Win32 + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x64.ActiveCfg = Release|x64 + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x64.Build.0 = Release|x64 + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x86.ActiveCfg = Release|Win32 + {2DE74E14-BF6D-4046-951B-8EBC8A1BA009}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {DDE0FE54-030A-4DFD-98A1-952779FB461F} + EndGlobalSection +EndGlobal diff --git a/src/Native/libubqhash/libubqhash.vcxproj b/src/Native/libubqhash/libubqhash.vcxproj index b8d6360b1d..c2d6950bf8 100644 --- a/src/Native/libubqhash/libubqhash.vcxproj +++ b/src/Native/libubqhash/libubqhash.vcxproj @@ -1,205 +1,205 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942} - Win32Proj - netmultihashnative - 10.0 - libubqhash - - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) - $(SolutionDir)\..\..\..\..\boost_1_62_0\lib32-msvc-14.0;$(LibraryPath) - - - true - $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) - $(SolutionDir)\..\..\..\..\boost_1_62_0\lib64-msvc-14.0;$(ProjectDir)windows\lib\x64;$(LibraryPath) - - - false - $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) - $(SolutionDir)\..\..\..\..\boost_1_62_0\lib32-msvc-14.0;$(LibraryPath) - - - false - $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) - $(SolutionDir)\..\..\..\..\boost_1_62_0\lib64-msvc-14.0;$(LibraryPath) - - - - - - Level3 - Disabled - SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 - true - MultiThreadedDebug - stdcpp14 - - - Windows - true - Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x86\libsodium.lib;%(AdditionalDependencies) - - - - - - - Level3 - Disabled - SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 - true - MultiThreadedDebug - stdcpp14 - - - Windows - true - Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x64\libsodium.lib;%(AdditionalDependencies) - - - - - - - Level3 - MaxSpeed - true - true - SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 - true - MultiThreaded - stdcpp14 - - - Windows - true - true - true - Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x86\libsodium.lib;%(AdditionalDependencies) - - - - - - - Level3 - MaxSpeed - true - true - SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 - true - MultiThreaded - stdcpp14 - - - Windows - true - true - true - Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x64\libsodium.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942} + Win32Proj + netmultihashnative + 10.0 + libubqhash + + + + DynamicLibrary + true + v143 + Unicode + + + DynamicLibrary + false + v143 + true + Unicode + + + DynamicLibrary + true + v143 + Unicode + + + DynamicLibrary + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) + $(SolutionDir)\..\..\..\..\boost_1_62_0\lib32-msvc-14.0;$(LibraryPath) + + + true + $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) + $(SolutionDir)\..\..\..\..\boost_1_62_0\lib64-msvc-14.0;$(ProjectDir)windows\lib\x64;$(LibraryPath) + + + false + $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) + $(SolutionDir)\..\..\..\..\boost_1_62_0\lib32-msvc-14.0;$(LibraryPath) + + + false + $(SolutionDir)\..\..\..\..\boost_1_62_0;$(ProjectDir)..\libethhash\windows\include\libsodium;$(ProjectDir)..\libethhash\windows\include\libsodium;$(IncludePath);$(ProjectDir) + $(SolutionDir)\..\..\..\..\boost_1_62_0\lib64-msvc-14.0;$(LibraryPath) + + + + + + Level3 + Disabled + SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 + true + MultiThreadedDebug + stdcpp14 + + + Windows + true + Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x86\libsodium.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 + true + MultiThreadedDebug + stdcpp14 + + + Windows + true + Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x64\libsodium.lib;%(AdditionalDependencies) + + + + + + + Level3 + MaxSpeed + true + true + SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 + true + MultiThreaded + stdcpp14 + + + Windows + true + true + true + Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x86\libsodium.lib;%(AdditionalDependencies) + + + + + + + Level3 + MaxSpeed + true + true + SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;HAVE_SSE2 + true + MultiThreaded + stdcpp14 + + + Windows + true + true + true + Ws2_32.lib;$(ProjectDir)..\libethhash\windows\lib\x64\libsodium.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 0b78ae990512d23b24f18ac49adc0de95e1a123b Mon Sep 17 00:00:00 2001 From: jon4hz Date: Mon, 30 Jan 2023 18:27:17 +0100 Subject: [PATCH 2/5] feat: abstract ethash algo --- src/Miningcore/AutofacModule.cs | 29 ++- .../Blockchain/Conceal/ConcealPool.cs | 4 +- .../Blockchain/Ethereum/EthereumJob.cs | 156 +-------------- .../Blockchain/Ethereum/EthereumJobManager.cs | 182 ++++-------------- src/Miningcore/Configuration/ClusterConfig.cs | 13 +- .../Configuration/ClusterConfigExtensions.cs | 35 ++-- .../Crypto/Hashing/Ethash/Abstractions.cs | 19 ++ .../DagEtchash.cs => Ethash/Etchash/Dag.cs} | 32 +-- .../{ => Ethash}/Etchash/EtchashFull.cs | 52 +++-- .../Crypto/Hashing/Ethash/{ => Ethash}/Dag.cs | 34 +--- .../Hashing/Ethash/{ => Ethash}/EthashFull.cs | 40 +++- .../Crypto/Hashing/Ethash/EthashFactory.cs | 25 +++ .../DagUbqhash.cs => Ethash/Ubqhash/Dag.cs} | 36 +--- .../{ => Ethash}/Ubqhash/UbqhashFull.cs | 50 +++-- src/Miningcore/Program.cs | 46 +++-- src/Miningcore/coins.json | 21 +- 16 files changed, 320 insertions(+), 454 deletions(-) create mode 100644 src/Miningcore/Crypto/Hashing/Ethash/Abstractions.cs rename src/Miningcore/Crypto/Hashing/{Etchash/DagEtchash.cs => Ethash/Etchash/Dag.cs} (81%) rename src/Miningcore/Crypto/Hashing/{ => Ethash}/Etchash/EtchashFull.cs (70%) rename src/Miningcore/Crypto/Hashing/Ethash/{ => Ethash}/Dag.cs (80%) rename src/Miningcore/Crypto/Hashing/Ethash/{ => Ethash}/EthashFull.cs (70%) create mode 100644 src/Miningcore/Crypto/Hashing/Ethash/EthashFactory.cs rename src/Miningcore/Crypto/Hashing/{Ubqhash/DagUbqhash.cs => Ethash/Ubqhash/Dag.cs} (79%) rename src/Miningcore/Crypto/Hashing/{ => Ethash}/Ubqhash/UbqhashFull.cs (65%) diff --git a/src/Miningcore/AutofacModule.cs b/src/Miningcore/AutofacModule.cs index ef2b595b9a..3302d19245 100644 --- a/src/Miningcore/AutofacModule.cs +++ b/src/Miningcore/AutofacModule.cs @@ -1,29 +1,30 @@ using System.Reflection; using Autofac; +using Microsoft.AspNetCore.Mvc; +using Microsoft.IO; using Miningcore.Api; using Miningcore.Banning; using Miningcore.Blockchain.Bitcoin; using Miningcore.Blockchain.Conceal; using Miningcore.Blockchain.Cryptonote; using Miningcore.Blockchain.Equihash; +using Miningcore.Blockchain.Ergo; using Miningcore.Blockchain.Ethereum; using Miningcore.Configuration; using Miningcore.Crypto; using Miningcore.Crypto.Hashing.Equihash; +using Miningcore.Crypto.Hashing.Ethash; using Miningcore.Messaging; using Miningcore.Mining; +using Miningcore.Nicehash; using Miningcore.Notifications; using Miningcore.Payments; using Miningcore.Payments.PaymentSchemes; +using Miningcore.Pushover; using Miningcore.Time; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using Module = Autofac.Module; -using Microsoft.AspNetCore.Mvc; -using Microsoft.IO; -using Miningcore.Blockchain.Ergo; -using Miningcore.Nicehash; -using Miningcore.Pushover; namespace Miningcore; @@ -78,7 +79,19 @@ protected override void Load(ContainerBuilder builder) builder.RegisterAssemblyTypes(ThisAssembly) .Where(t => t.GetCustomAttributes().Any() && t.GetInterfaces().Any(i => i.IsAssignableFrom(typeof(IHashAlgorithm)))) - .Named(t=> t.GetCustomAttributes().First().Name) + .Named(t => t.GetCustomAttributes().First().Name) + .PropertiesAutowired(); + + builder.RegisterAssemblyTypes(ThisAssembly) + .Where(t => t.GetCustomAttributes().Any() && + t.GetInterfaces().Any(i => i.IsAssignableFrom(typeof(IEthashFull)))) + .Named(t => t.GetCustomAttributes().First().Name) + .PropertiesAutowired(); + + builder.RegisterAssemblyTypes(ThisAssembly) + .Where(t => t.GetCustomAttributes().Any() && + t.GetInterfaces().Any(i => i.IsAssignableFrom(typeof(IEthashDag)))) + .Named(t => t.GetCustomAttributes().First().Name) .PropertiesAutowired(); builder.RegisterAssemblyTypes(ThisAssembly) @@ -148,12 +161,12 @@ protected override void Load(ContainerBuilder builder) // Bitcoin and family builder.RegisterType(); - + ////////////////////// // Conceal builder.RegisterType(); - + ////////////////////// // Cryptonote diff --git a/src/Miningcore/Blockchain/Conceal/ConcealPool.cs b/src/Miningcore/Blockchain/Conceal/ConcealPool.cs index 99806e9987..cbf5d6012c 100644 --- a/src/Miningcore/Blockchain/Conceal/ConcealPool.cs +++ b/src/Miningcore/Blockchain/Conceal/ConcealPool.cs @@ -314,7 +314,7 @@ protected override async Task SetupJobManager(CancellationToken ct) disposables.Add(manager.Blocks .Select(_ => Observable.FromAsync(() => Guard(OnNewJobAsync, - ex=> logger.Debug(() => $"{nameof(OnNewJobAsync)}: {ex.Message}")))) + ex => logger.Debug(() => $"{nameof(OnNewJobAsync)}: {ex.Message}")))) .Concat() .Subscribe(_ => { }, ex => { @@ -338,7 +338,7 @@ private string GetMinerAlgo() { case CryptonightHashType.CryptonightCCX: return $"cn-ccx"; - + case CryptonightHashType.CryptonightGPU: return $"cn-gpu"; } diff --git a/src/Miningcore/Blockchain/Ethereum/EthereumJob.cs b/src/Miningcore/Blockchain/Ethereum/EthereumJob.cs index a7a181e499..a432f8be5f 100644 --- a/src/Miningcore/Blockchain/Ethereum/EthereumJob.cs +++ b/src/Miningcore/Blockchain/Ethereum/EthereumJob.cs @@ -1,8 +1,6 @@ using System.Globalization; using System.Numerics; -using Miningcore.Crypto.Hashing.Etchash; using Miningcore.Crypto.Hashing.Ethash; -using Miningcore.Crypto.Hashing.Ubqhash; using Miningcore.Extensions; using Miningcore.Stratum; using NBitcoin; @@ -12,11 +10,12 @@ namespace Miningcore.Blockchain.Ethereum; public class EthereumJob { - public EthereumJob(string id, EthereumBlockTemplate blockTemplate, ILogger logger) + public EthereumJob(string id, EthereumBlockTemplate blockTemplate, ILogger logger, IEthashFull ethashFull) { Id = id; BlockTemplate = blockTemplate; this.logger = logger; + this.ethashFull = ethashFull; var target = blockTemplate.Target; if(target.StartsWith("0x")) @@ -31,6 +30,7 @@ public EthereumJob(string id, EthereumBlockTemplate blockTemplate, ILogger logge public EthereumBlockTemplate BlockTemplate { get; } private readonly uint256 blockTarget; private readonly ILogger logger; + private readonly IEthashFull ethashFull; public record SubmitResult(Share Share, string FullNonceHex = null, string HeaderHash = null, string MixHash = null); @@ -52,155 +52,9 @@ private void RegisterNonce(StratumConnection worker, string nonce) nonces.Add(nonceLower); } } - - public async Task ProcessShareEtcHashAsync(StratumConnection worker, - string workerName, string fullNonceHex, EtchashFull etchash, CancellationToken ct) - { - // dupe check - lock(workerNonces) - { - RegisterNonce(worker, fullNonceHex); - } - - var context = worker.ContextAs(); - - if(!ulong.TryParse(fullNonceHex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var fullNonce)) - throw new StratumException(StratumError.MinusOne, "bad nonce " + fullNonceHex); - - // get dag for block - var dag = await etchash.GetDagAsync(BlockTemplate.Height, logger, CancellationToken.None); - - // compute - if(!dag.Compute(logger, BlockTemplate.Header.HexToByteArray(), fullNonce, out var mixDigest, out var resultBytes)) - throw new StratumException(StratumError.MinusOne, "bad hash"); - - // test if share meets at least workers current difficulty - resultBytes.ReverseInPlace(); - var resultValue = new uint256(resultBytes); - var resultValueBig = resultBytes.AsSpan().ToBigInteger(); - var shareDiff = (double) BigInteger.Divide(EthereumConstants.BigMaxValue, resultValueBig) / EthereumConstants.Pow2x32; - var stratumDifficulty = context.Difficulty; - var ratio = shareDiff / stratumDifficulty; - var isBlockCandidate = resultValue <= blockTarget; - - if(!isBlockCandidate && ratio < 0.99) - { - // check if share matched the previous difficulty from before a vardiff retarget - if(context.VarDiff?.LastUpdate != null && context.PreviousDifficulty.HasValue) - { - ratio = shareDiff / context.PreviousDifficulty.Value; - - if(ratio < 0.99) - throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})"); - - // use previous difficulty - stratumDifficulty = context.PreviousDifficulty.Value; - } - - else - throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})"); - } - - var share = new Share - { - BlockHeight = (long) BlockTemplate.Height, - IpAddress = worker.RemoteEndpoint?.Address?.ToString(), - Miner = context.Miner, - Worker = workerName, - UserAgent = context.UserAgent, - IsBlockCandidate = isBlockCandidate, - Difficulty = stratumDifficulty * EthereumConstants.Pow2x32 - }; - - if(share.IsBlockCandidate) - { - fullNonceHex = "0x" + fullNonceHex; - var headerHash = BlockTemplate.Header; - var mixHash = mixDigest.ToHexString(true); - - share.TransactionConfirmationData = ""; - - return new SubmitResult(share, fullNonceHex, headerHash, mixHash); - } - - return new SubmitResult(share); - } public async Task ProcessShareAsync(StratumConnection worker, - string workerName, string fullNonceHex, EthashFull ethash, CancellationToken ct) - { - // dupe check - lock(workerNonces) - { - RegisterNonce(worker, fullNonceHex); - } - - var context = worker.ContextAs(); - - if(!ulong.TryParse(fullNonceHex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var fullNonce)) - throw new StratumException(StratumError.MinusOne, "bad nonce " + fullNonceHex); - - // get dag for block - var dag = await ethash.GetDagAsync(BlockTemplate.Height, logger, CancellationToken.None); - - // compute - if(!dag.Compute(logger, BlockTemplate.Header.HexToByteArray(), fullNonce, out var mixDigest, out var resultBytes)) - throw new StratumException(StratumError.MinusOne, "bad hash"); - - // test if share meets at least workers current difficulty - resultBytes.ReverseInPlace(); - var resultValue = new uint256(resultBytes); - var resultValueBig = resultBytes.AsSpan().ToBigInteger(); - var shareDiff = (double) BigInteger.Divide(EthereumConstants.BigMaxValue, resultValueBig) / EthereumConstants.Pow2x32; - var stratumDifficulty = context.Difficulty; - var ratio = shareDiff / stratumDifficulty; - var isBlockCandidate = resultValue <= blockTarget; - - if(!isBlockCandidate && ratio < 0.99) - { - // check if share matched the previous difficulty from before a vardiff retarget - if(context.VarDiff?.LastUpdate != null && context.PreviousDifficulty.HasValue) - { - ratio = shareDiff / context.PreviousDifficulty.Value; - - if(ratio < 0.99) - throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})"); - - // use previous difficulty - stratumDifficulty = context.PreviousDifficulty.Value; - } - - else - throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})"); - } - - var share = new Share - { - BlockHeight = (long) BlockTemplate.Height, - IpAddress = worker.RemoteEndpoint?.Address?.ToString(), - Miner = context.Miner, - Worker = workerName, - UserAgent = context.UserAgent, - IsBlockCandidate = isBlockCandidate, - Difficulty = stratumDifficulty * EthereumConstants.Pow2x32 - }; - - if(share.IsBlockCandidate) - { - fullNonceHex = "0x" + fullNonceHex; - var headerHash = BlockTemplate.Header; - var mixHash = mixDigest.ToHexString(true); - - share.TransactionConfirmationData = ""; - - return new SubmitResult(share, fullNonceHex, headerHash, mixHash); - } - - return new SubmitResult(share); - } - - public async Task ProcessShareUbqHashAsync(StratumConnection worker, - string workerName, string fullNonceHex, UbqhashFull ubqhash, CancellationToken ct) + string workerName, string fullNonceHex, CancellationToken ct) { // dupe check lock(workerNonces) @@ -214,7 +68,7 @@ public async Task ProcessShareUbqHashAsync(StratumConnection worke throw new StratumException(StratumError.MinusOne, "bad nonce " + fullNonceHex); // get dag for block - var dag = await ubqhash.GetDagAsync(BlockTemplate.Height, logger, CancellationToken.None); + var dag = await ethashFull.GetDagAsync(BlockTemplate.Height, logger, CancellationToken.None); // compute if(!dag.Compute(logger, BlockTemplate.Header.HexToByteArray(), fullNonce, out var mixDigest, out var resultBytes)) diff --git a/src/Miningcore/Blockchain/Ethereum/EthereumJobManager.cs b/src/Miningcore/Blockchain/Ethereum/EthereumJobManager.cs index e1a82b7696..d65c629974 100644 --- a/src/Miningcore/Blockchain/Ethereum/EthereumJobManager.cs +++ b/src/Miningcore/Blockchain/Ethereum/EthereumJobManager.cs @@ -1,5 +1,6 @@ using System.Globalization; using System.Numerics; +using System.Reactive; using System.Reactive.Linq; using System.Reactive.Threading.Tasks; using System.Text; @@ -8,25 +9,22 @@ using Miningcore.Blockchain.Ethereum.Configuration; using Miningcore.Blockchain.Ethereum.DaemonResponses; using Miningcore.Configuration; -using Miningcore.Crypto.Hashing.Etchash; -using Miningcore.Crypto.Hashing.Ethash; -using Miningcore.Crypto.Hashing.Ubqhash; using Miningcore.Extensions; using Miningcore.JsonRpc; using Miningcore.Messaging; +using Miningcore.Mining; using Miningcore.Notifications.Messages; +using Miningcore.Rpc; using Miningcore.Stratum; using Miningcore.Time; +using NBitcoin; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using NLog; +using static Miningcore.Util.ActionUtils; using Block = Miningcore.Blockchain.Ethereum.DaemonResponses.Block; using Contract = Miningcore.Contracts.Contract; using EC = Miningcore.Blockchain.Ethereum.EthCommands; -using static Miningcore.Util.ActionUtils; -using System.Reactive; -using Miningcore.Mining; -using Miningcore.Rpc; -using Newtonsoft.Json.Linq; namespace Miningcore.Blockchain.Ethereum; @@ -48,13 +46,11 @@ public EthereumJobManager( this.extraNonceProvider = extraNonceProvider; } + private EthereumCoinTemplate coin; private DaemonEndpointConfig[] daemonEndpoints; private RpcClient rpc; private EthereumNetworkType networkType; private GethChainType chainType; - private EtchashFull etchash; - private EthashFull ethash; - private UbqhashFull ubqhash; private readonly IMasterClock clock; private readonly IExtraNonceProvider extraNonceProvider; private const int MaxBlockBacklog = 6; @@ -106,7 +102,7 @@ protected bool UpdateJob(EthereumBlockTemplate blockTemplate, string via = null) var jobId = NextJobId("x8"); // update template - job = new EthereumJob(jobId, blockTemplate, logger); + job = new EthereumJob(jobId, blockTemplate, logger, coin.EthashFull); lock(jobLock) { @@ -339,6 +335,7 @@ public object[] GetWorkParamsForStratum(EthereumWorkerContext context) public override void Configure(PoolConfig pc, ClusterConfig cc) { extraPoolConfig = pc.Extra.SafeExtensionDataAs(); + coin = pc.Template.As(); // extract standard daemon endpoints daemonEndpoints = pc.Daemons @@ -350,49 +347,19 @@ public override void Configure(PoolConfig pc, ClusterConfig cc) if(pc.EnableInternalStratum == true) { var coin = pc.Template.As(); - + // ensure dag location is configured - string dagDir = null; - - if(!string.IsNullOrEmpty(extraPoolConfig?.DagDir)) - { - dagDir = Environment.ExpandEnvironmentVariables(extraPoolConfig.DagDir); - } - else - { - // Default DAG folder - switch(coin.Symbol) - { - case "ETC": - dagDir = DagEtchash.GetDefaultDagDirectory(); - break; - case "UBIQ": - dagDir = DagUbqhash.GetDefaultDagDirectory(); - break; - default: - dagDir = Dag.GetDefaultDagDirectory(); - break; - } - } + var dagDir = !string.IsNullOrEmpty(extraPoolConfig?.DagDir) ? + Environment.ExpandEnvironmentVariables(extraPoolConfig.DagDir) : + coin.EthashFull.GetDefaultDagDirectory(); // create it if necessary Directory.CreateDirectory(dagDir); - // setup ethash - switch(coin.Symbol) - { - case "ETC": - var hardForkBlock = extraPoolConfig?.ChainTypeOverride == "Classic" ? EthereumClassicConstants.HardForkBlockMainnet : EthereumClassicConstants.HardForkBlockMordor; - logger.Debug(() => $"Hard fork block on `{extraPoolConfig?.ChainTypeOverride}`: {hardForkBlock}"); - etchash = new EtchashFull(3, dagDir, hardForkBlock); - break; - case "UBIQ": - ubqhash = new UbqhashFull(3, dagDir); - break; - default: - ethash = new EthashFull(3, dagDir); - break; - } + logger.Info(() => $"Ethasher is: {coin.Ethasher}"); + + var hardForkBlock = extraPoolConfig?.ChainTypeOverride == "Classic" ? EthereumClassicConstants.HardForkBlockMainnet : EthereumClassicConstants.HardForkBlockMordor; + coin.EthashFull.Setup(3, dagDir, hardForkBlock); } } @@ -466,86 +433,31 @@ private async Task SubmitShareAsync(StratumConnection worker, EthereumWorkerContext context, string workerName, EthereumJob job, string nonce, CancellationToken ct) { var coin = poolConfig.Template.As(); - - // validate & process - switch(coin.Symbol) - { - case "ETC": - var (shareEtchash, fullNonceHexEtchash, headerHashEtchash, mixHashEtchash) = await job.ProcessShareEtcHashAsync(worker, workerName, nonce, etchash, ct); - - // enrich share with common data - shareEtchash.PoolId = poolConfig.Id; - shareEtchash.NetworkDifficulty = BlockchainStats.NetworkDifficulty; - shareEtchash.Source = clusterConfig.ClusterName; - shareEtchash.Created = clock.Now; - - // if block candidate, submit & check if accepted by network - if(shareEtchash.IsBlockCandidate) - { - logger.Info(() => $"Submitting block {shareEtchash.BlockHeight}"); - - shareEtchash.IsBlockCandidate = await SubmitBlockAsync(shareEtchash, fullNonceHexEtchash, headerHashEtchash, mixHashEtchash); - - if(shareEtchash.IsBlockCandidate) - { - logger.Info(() => $"Daemon accepted block {shareEtchash.BlockHeight} submitted by {context.Miner}"); - - OnBlockFound(); - } - } - - return shareEtchash; - case "UBIQ": - var (shareUbqhash, fullNonceHexUbqhash, headerHashUbqhash, mixHashUbqhash) = await job.ProcessShareUbqHashAsync(worker, workerName, nonce, ubqhash, ct); - - // enrich share with common data - shareUbqhash.PoolId = poolConfig.Id; - shareUbqhash.NetworkDifficulty = BlockchainStats.NetworkDifficulty; - shareUbqhash.Source = clusterConfig.ClusterName; - shareUbqhash.Created = clock.Now; - - // if block candidate, submit & check if accepted by network - if(shareUbqhash.IsBlockCandidate) - { - logger.Info(() => $"Submitting block {shareUbqhash.BlockHeight}"); - shareUbqhash.IsBlockCandidate = await SubmitBlockAsync(shareUbqhash, fullNonceHexUbqhash, headerHashUbqhash, mixHashUbqhash); + var (share, fullNonceHex, headerHash, mixHash) = await job.ProcessShareAsync(worker, workerName, nonce, ct); - if(shareUbqhash.IsBlockCandidate) - { - logger.Info(() => $"Daemon accepted block {shareUbqhash.BlockHeight} submitted by {context.Miner}"); + // enrich share with common data + share.PoolId = poolConfig.Id; + share.NetworkDifficulty = BlockchainStats.NetworkDifficulty; + share.Source = clusterConfig.ClusterName; + share.Created = clock.Now; - OnBlockFound(); - } - } - - return shareUbqhash; - default: - var (share, fullNonceHex, headerHash, mixHash) = await job.ProcessShareAsync(worker, workerName, nonce, ethash, ct); - - // enrich share with common data - share.PoolId = poolConfig.Id; - share.NetworkDifficulty = BlockchainStats.NetworkDifficulty; - share.Source = clusterConfig.ClusterName; - share.Created = clock.Now; - - // if block candidate, submit & check if accepted by network - if(share.IsBlockCandidate) - { - logger.Info(() => $"Submitting block {share.BlockHeight}"); + // if block candidate, submit & check if accepted by network + if(share.IsBlockCandidate) + { + logger.Info(() => $"Submitting block {share.BlockHeight}"); - share.IsBlockCandidate = await SubmitBlockAsync(share, fullNonceHex, headerHash, mixHash); + share.IsBlockCandidate = await SubmitBlockAsync(share, fullNonceHex, headerHash, mixHash); - if(share.IsBlockCandidate) - { - logger.Info(() => $"Daemon accepted block {share.BlockHeight} submitted by {context.Miner}"); + if(share.IsBlockCandidate) + { + logger.Info(() => $"Daemon accepted block {share.BlockHeight} submitted by {context.Miner}"); - OnBlockFound(); - } - } - - return share; + OnBlockFound(); + } } + + return share; } public BlockchainStats BlockchainStats { get; } = new(); @@ -641,8 +553,8 @@ protected override async Task PostStartInitAsync(CancellationToken ct) // Periodically update network stats Observable.Interval(TimeSpan.FromMinutes(10)) .Select(via => Observable.FromAsync(() => - Guard(()=> UpdateNetworkStatsAsync(ct), - ex=> logger.Error(ex)))) + Guard(() => UpdateNetworkStatsAsync(ct), + ex => logger.Error(ex)))) .Concat() .Subscribe(); @@ -658,21 +570,9 @@ protected override async Task PostStartInitAsync(CancellationToken ct) if(blockTemplate != null) { logger.Info(() => "Loading current DAG ..."); - - // setup dag file - switch(coin.Symbol) - { - case "ETC": - await etchash.GetDagAsync(blockTemplate.Height, logger, ct); - break; - case "UBIQ": - await ubqhash.GetDagAsync(blockTemplate.Height, logger, ct); - break; - default: - await ethash.GetDagAsync(blockTemplate.Height, logger, ct); - break; - } - + + await coin.EthashFull.GetDagAsync(blockTemplate.Height, logger, ct); + logger.Info(() => "Loaded current DAG"); break; } @@ -698,7 +598,7 @@ protected virtual async Task SetupJobUpdates(CancellationToken ct) var endpointExtra = daemonEndpoints .Where(x => x.Extra.SafeExtensionDataAs() != null) - .Select(x=> Tuple.Create(x, x.Extra.SafeExtensionDataAs())) + .Select(x => Tuple.Create(x, x.Extra.SafeExtensionDataAs())) .FirstOrDefault(); if(endpointExtra?.Item2?.PortWs.HasValue == true) diff --git a/src/Miningcore/Configuration/ClusterConfig.cs b/src/Miningcore/Configuration/ClusterConfig.cs index 0fa3c07ad1..775c6f4339 100644 --- a/src/Miningcore/Configuration/ClusterConfig.cs +++ b/src/Miningcore/Configuration/ClusterConfig.cs @@ -24,7 +24,7 @@ public enum CoinFamily [EnumMember(Value = "conceal")] Conceal, - + [EnumMember(Value = "cryptonote")] Cryptonote, @@ -435,13 +435,13 @@ public partial class ConcealCoinTemplate : CoinTemplate /// [JsonProperty(Order = -4, DefaultValueHandling = DefaultValueHandling.Include)] public int HashVariant { get; set; } - + /// /// Conceal network hashrate = `Difficulty / DifficultyTarget` /// See: parameter -> DIFFICULTY_TARGET in src/CryptoNoteConfig.h /// public ulong DifficultyTarget { get; set; } - + /// /// Smallest unit for Blockreward formatting /// @@ -578,6 +578,11 @@ public partial class EthereumCoinTemplate : CoinTemplate [DefaultValue(EthereumSubfamily.None)] [JsonConverter(typeof(StringEnumConverter), true)] public EthereumSubfamily Subfamily { get; set; } + + /// + /// Which hashing algorithm to use. (ethash, etchash or ubqhash) + /// + public string Ethasher { get; set; } = "ethash"; } public partial class ErgoCoinTemplate : CoinTemplate @@ -827,7 +832,7 @@ public partial class ClusterPaymentProcessingConfig /// /// Indentifier used in coinbase transactions to identify the pool /// - public string CoinbaseString { get; set; } + public string CoinbaseString { get; set; } } public partial class PersistenceConfig diff --git a/src/Miningcore/Configuration/ClusterConfigExtensions.cs b/src/Miningcore/Configuration/ClusterConfigExtensions.cs index d7c783306b..d24ba57b8c 100644 --- a/src/Miningcore/Configuration/ClusterConfigExtensions.cs +++ b/src/Miningcore/Configuration/ClusterConfigExtensions.cs @@ -4,6 +4,7 @@ using JetBrains.Annotations; using Miningcore.Crypto; using Miningcore.Crypto.Hashing.Algorithms; +using Miningcore.Crypto.Hashing.Ethash; using NBitcoin; using Newtonsoft.Json; @@ -152,11 +153,11 @@ public partial class ConcealCoinTemplate public override string GetAlgorithmName() { -// switch(Hash) -// { -// case CryptonightHashType.RandomX: -// return "RandomX"; -// } + // switch(Hash) + // { + // case CryptonightHashType.RandomX: + // return "RandomX"; + // } return Hash.ToString(); } @@ -170,11 +171,11 @@ public partial class CryptonoteCoinTemplate public override string GetAlgorithmName() { -// switch(Hash) -// { -// case CryptonightHashType.RandomX: -// return "RandomX"; -// } + // switch(Hash) + // { + // case CryptonightHashType.RandomX: + // return "RandomX"; + // } return Hash.ToString(); } @@ -186,9 +187,21 @@ public partial class EthereumCoinTemplate { #region Overrides of CoinTemplate + public EthereumCoinTemplate() + { + ethashFullValue = new Lazy(() => + EthashFactory.GetEthashFull(ComponentContext, Ethasher)); + } + + private readonly Lazy ethashFullValue; + + public IComponentContext ComponentContext { get; [UsedImplicitly] init; } + + public IEthashFull EthashFull => ethashFullValue.Value; + public override string GetAlgorithmName() { - return "Ethhash"; + return EthashFull.AlgoName; } #endregion diff --git a/src/Miningcore/Crypto/Hashing/Ethash/Abstractions.cs b/src/Miningcore/Crypto/Hashing/Ethash/Abstractions.cs new file mode 100644 index 0000000000..87c2c98311 --- /dev/null +++ b/src/Miningcore/Crypto/Hashing/Ethash/Abstractions.cs @@ -0,0 +1,19 @@ +using NLog; + +namespace Miningcore.Crypto.Hashing.Ethash; + +public interface IEthashDag : IDisposable +{ + ulong Epoch { get; set; } + DateTime LastUsed { get; set; } + Task GenerateAsync(string dagDir, ulong dagEpochLength, ILogger logger, CancellationToken ct); + bool Compute(ILogger logger, byte[] hash, ulong nonce, out byte[] mixDigest, out byte[] result); +} + +public interface IEthashFull : IDisposable +{ + string GetDefaultDagDirectory(); + void Setup(int numCaches, string dagDir, ulong hardForkBlock); + Task GetDagAsync(ulong block, ILogger logger, CancellationToken ct); + string AlgoName { get; } +} \ No newline at end of file diff --git a/src/Miningcore/Crypto/Hashing/Etchash/DagEtchash.cs b/src/Miningcore/Crypto/Hashing/Ethash/Etchash/Dag.cs similarity index 81% rename from src/Miningcore/Crypto/Hashing/Etchash/DagEtchash.cs rename to src/Miningcore/Crypto/Hashing/Ethash/Etchash/Dag.cs index 447c372cef..33bf49a0e4 100644 --- a/src/Miningcore/Crypto/Hashing/Etchash/DagEtchash.cs +++ b/src/Miningcore/Crypto/Hashing/Ethash/Etchash/Dag.cs @@ -8,11 +8,12 @@ using Miningcore.Notifications.Messages; using NLog; -namespace Miningcore.Crypto.Hashing.Etchash; +namespace Miningcore.Crypto.Hashing.Ethash.Etchash; -public class DagEtchash : IDisposable +[Identifier("etchash")] +public class Dag : IEthashDag { - public DagEtchash(ulong epoch) + public Dag(ulong epoch) { Epoch = epoch; } @@ -26,27 +27,6 @@ public DagEtchash(ulong epoch) public DateTime LastUsed { get; set; } - public static unsafe string GetDefaultDagDirectory() - { - var chars = new byte[512]; - - fixed (byte* data = chars) - { - if(EtcHash.ethash_get_default_dirname(data, chars.Length)) - { - int length; - for(length = 0; length < chars.Length; length++) - { - if(data[length] == 0) - break; - } - - return Encoding.UTF8.GetString(data, length); - } - } - - return null; - } public void Dispose() { @@ -77,7 +57,7 @@ await Task.Run(() => var started = DateTime.Now; var block = Epoch * dagEpochLength; - + logger.Debug(() => $"Epoch length used: {dagEpochLength}"); // Generate a temporary cache @@ -125,7 +105,7 @@ public unsafe bool Compute(ILogger logger, byte[] hash, ulong nonce, out byte[] var value = new EtcHash.ethash_return_value(); - fixed (byte* input = hash) + fixed(byte* input = hash) { EtcHash.ethash_full_compute(handle, input, nonce, ref value); } diff --git a/src/Miningcore/Crypto/Hashing/Etchash/EtchashFull.cs b/src/Miningcore/Crypto/Hashing/Ethash/Etchash/EtchashFull.cs similarity index 70% rename from src/Miningcore/Crypto/Hashing/Etchash/EtchashFull.cs rename to src/Miningcore/Crypto/Hashing/Ethash/Etchash/EtchashFull.cs index a5edd7aa0b..215d7c93b7 100644 --- a/src/Miningcore/Crypto/Hashing/Etchash/EtchashFull.cs +++ b/src/Miningcore/Crypto/Hashing/Ethash/Etchash/EtchashFull.cs @@ -1,15 +1,20 @@ +using System.Text; using Miningcore.Blockchain.Ethereum; using Miningcore.Contracts; +using Miningcore.Native; using NLog; -namespace Miningcore.Crypto.Hashing.Etchash; -public class EtchashFull : IDisposable +namespace Miningcore.Crypto.Hashing.Ethash.Etchash; + +[Identifier("etchash")] +public class EtchashFull : IEthashFull { - public EtchashFull(int numCaches, string dagDir, ulong hardForkBlock) + public void Setup(int numCaches, string dagDir, ulong hardForkBlock) { + Contract.Requires(!string.IsNullOrEmpty(dagDir)); - + this.numCaches = numCaches; this.dagDir = dagDir; this.hardForkBlock = hardForkBlock; @@ -17,10 +22,11 @@ public EtchashFull(int numCaches, string dagDir, ulong hardForkBlock) private int numCaches; // Maximum number of caches to keep before eviction (only init, don't modify) private readonly object cacheLock = new(); - private readonly Dictionary caches = new(); - private DagEtchash future; - private readonly string dagDir; - private readonly ulong hardForkBlock; + private readonly Dictionary caches = new(); + private Dag future; + private string dagDir; + private ulong hardForkBlock; + public string AlgoName { get; } = "Etchash"; public void Dispose() { @@ -28,12 +34,12 @@ public void Dispose() value.Dispose(); } - public async Task GetDagAsync(ulong block, ILogger logger, CancellationToken ct) + public async Task GetDagAsync(ulong block, ILogger logger, CancellationToken ct) { var dagEpochLength = block >= hardForkBlock ? EthereumClassicConstants.EpochLength : EthereumConstants.EpochLength; logger.Debug(() => $"Epoch length used: {dagEpochLength}"); var epoch = block / dagEpochLength; - DagEtchash result; + Dag result; lock(cacheLock) { @@ -66,7 +72,7 @@ public async Task GetDagAsync(ulong block, ILogger logger, Cancellat else { logger.Info(() => $"No pre-generated DAG available, creating new for epoch {epoch}"); - result = new DagEtchash(epoch); + result = new Dag(epoch); } caches[epoch] = result; @@ -76,7 +82,7 @@ public async Task GetDagAsync(ulong block, ILogger logger, Cancellat else if(future == null || future.Epoch <= epoch) { logger.Info(() => $"Pre-generating DAG for epoch {epoch + 1}"); - future = new DagEtchash(epoch + 1); + future = new Dag(epoch + 1); #pragma warning disable 4014 future.GenerateAsync(dagDir, dagEpochLength, logger, ct); @@ -91,4 +97,26 @@ public async Task GetDagAsync(ulong block, ILogger logger, Cancellat return result; } + + public unsafe string GetDefaultDagDirectory() + { + var chars = new byte[512]; + + fixed(byte* data = chars) + { + if(EtcHash.ethash_get_default_dirname(data, chars.Length)) + { + int length; + for(length = 0; length < chars.Length; length++) + { + if(data[length] == 0) + break; + } + + return Encoding.UTF8.GetString(data, length); + } + } + + return null; + } } diff --git a/src/Miningcore/Crypto/Hashing/Ethash/Dag.cs b/src/Miningcore/Crypto/Hashing/Ethash/Ethash/Dag.cs similarity index 80% rename from src/Miningcore/Crypto/Hashing/Ethash/Dag.cs rename to src/Miningcore/Crypto/Hashing/Ethash/Ethash/Dag.cs index 5bb3936d28..e34cc6d0b4 100644 --- a/src/Miningcore/Crypto/Hashing/Ethash/Dag.cs +++ b/src/Miningcore/Crypto/Hashing/Ethash/Ethash/Dag.cs @@ -1,5 +1,4 @@ using System.Diagnostics; -using System.Text; using Miningcore.Blockchain.Ethereum; using Miningcore.Contracts; using Miningcore.Extensions; @@ -8,9 +7,10 @@ using Miningcore.Notifications.Messages; using NLog; -namespace Miningcore.Crypto.Hashing.Ethash; +namespace Miningcore.Crypto.Hashing.Ethash.Ethash; -public class Dag : IDisposable +[Identifier("ethash")] +public class Dag : IEthashDag { public Dag(ulong epoch) { @@ -26,27 +26,6 @@ public Dag(ulong epoch) public DateTime LastUsed { get; set; } - public static unsafe string GetDefaultDagDirectory() - { - var chars = new byte[512]; - - fixed (byte* data = chars) - { - if(EthHash.ethash_get_default_dirname(data, chars.Length)) - { - int length; - for(length = 0; length < chars.Length; length++) - { - if(data[length] == 0) - break; - } - - return Encoding.UTF8.GetString(data, length); - } - } - - return null; - } public void Dispose() { @@ -57,8 +36,11 @@ public void Dispose() } } - public async Task GenerateAsync(string dagDir, ILogger logger, CancellationToken ct) + public async Task GenerateAsync(string dagDir, ulong dagEpochLength, ILogger logger, CancellationToken ct) { + // note that dagEpochLength is not used here + // it is only used in the etchash implementation + Contract.Requires(!string.IsNullOrEmpty(dagDir)); if(handle == IntPtr.Zero) @@ -123,7 +105,7 @@ public unsafe bool Compute(ILogger logger, byte[] hash, ulong nonce, out byte[] var value = new EthHash.ethash_return_value(); - fixed (byte* input = hash) + fixed(byte* input = hash) { EthHash.ethash_full_compute(handle, input, nonce, ref value); } diff --git a/src/Miningcore/Crypto/Hashing/Ethash/EthashFull.cs b/src/Miningcore/Crypto/Hashing/Ethash/Ethash/EthashFull.cs similarity index 70% rename from src/Miningcore/Crypto/Hashing/Ethash/EthashFull.cs rename to src/Miningcore/Crypto/Hashing/Ethash/Ethash/EthashFull.cs index a625010a57..fa567572d3 100644 --- a/src/Miningcore/Crypto/Hashing/Ethash/EthashFull.cs +++ b/src/Miningcore/Crypto/Hashing/Ethash/Ethash/EthashFull.cs @@ -1,12 +1,15 @@ +using System.Text; using Miningcore.Blockchain.Ethereum; using Miningcore.Contracts; +using Miningcore.Native; using NLog; -namespace Miningcore.Crypto.Hashing.Ethash; +namespace Miningcore.Crypto.Hashing.Ethash.Ethash; -public class EthashFull : IDisposable +[Identifier("ethash")] +public class EthashFull : IEthashFull { - public EthashFull(int numCaches, string dagDir) + public void Setup(int numCaches, string dagDir, ulong hardForkBlock) { Contract.Requires(!string.IsNullOrEmpty(dagDir)); @@ -18,7 +21,8 @@ public EthashFull(int numCaches, string dagDir) private readonly object cacheLock = new(); private readonly Dictionary caches = new(); private Dag future; - private readonly string dagDir; + private string dagDir; + public string AlgoName { get; } = "Ethash"; public void Dispose() { @@ -26,7 +30,7 @@ public void Dispose() value.Dispose(); } - public async Task GetDagAsync(ulong block, ILogger logger, CancellationToken ct) + public async Task GetDagAsync(ulong block, ILogger logger, CancellationToken ct) { var epoch = block / EthereumConstants.EpochLength; Dag result; @@ -75,7 +79,7 @@ public async Task GetDagAsync(ulong block, ILogger logger, CancellationToke future = new Dag(epoch + 1); #pragma warning disable 4014 - future.GenerateAsync(dagDir, logger, ct); + future.GenerateAsync(dagDir, 0, logger, ct); #pragma warning restore 4014 } @@ -83,8 +87,30 @@ public async Task GetDagAsync(ulong block, ILogger logger, CancellationToke } // get/generate current one - await result.GenerateAsync(dagDir, logger, ct); + await result.GenerateAsync(dagDir, 0, logger, ct); return result; } + + public unsafe string GetDefaultDagDirectory() + { + var chars = new byte[512]; + + fixed(byte* data = chars) + { + if(EthHash.ethash_get_default_dirname(data, chars.Length)) + { + int length; + for(length = 0; length < chars.Length; length++) + { + if(data[length] == 0) + break; + } + + return Encoding.UTF8.GetString(data, length); + } + } + + return null; + } } diff --git a/src/Miningcore/Crypto/Hashing/Ethash/EthashFactory.cs b/src/Miningcore/Crypto/Hashing/Ethash/EthashFactory.cs new file mode 100644 index 0000000000..bded75b948 --- /dev/null +++ b/src/Miningcore/Crypto/Hashing/Ethash/EthashFactory.cs @@ -0,0 +1,25 @@ +using System.Collections.Concurrent; +using Autofac; + +namespace Miningcore.Crypto.Hashing.Ethash; + +public static class EthashFactory +{ + private static readonly ConcurrentDictionary cacheFull = new(); + + public static IEthashFull GetEthashFull(IComponentContext ctx, string name) + { + if(name == "") + return null; + + // check cache + if(cacheFull.TryGetValue(name, out var result)) + return result; + + result = ctx.ResolveNamed(name); + + cacheFull.TryAdd(name, result); + + return result; + } +} \ No newline at end of file diff --git a/src/Miningcore/Crypto/Hashing/Ubqhash/DagUbqhash.cs b/src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/Dag.cs similarity index 79% rename from src/Miningcore/Crypto/Hashing/Ubqhash/DagUbqhash.cs rename to src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/Dag.cs index 9902f7cabe..0901bfcfe8 100644 --- a/src/Miningcore/Crypto/Hashing/Ubqhash/DagUbqhash.cs +++ b/src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/Dag.cs @@ -8,11 +8,12 @@ using Miningcore.Notifications.Messages; using NLog; -namespace Miningcore.Crypto.Hashing.Ubqhash; +namespace Miningcore.Crypto.Hashing.Ethash.Ubqhash; -public class DagUbqhash : IDisposable +[Identifier("ubqhash")] +public class Dag : IEthashDag { - public DagUbqhash(ulong epoch) + public Dag(ulong epoch) { Epoch = epoch; } @@ -26,28 +27,6 @@ public DagUbqhash(ulong epoch) public DateTime LastUsed { get; set; } - public static unsafe string GetDefaultDagDirectory() - { - var chars = new byte[512]; - - fixed (byte* data = chars) - { - if(UbqHash.ethash_get_default_dirname(data, chars.Length)) - { - int length; - for(length = 0; length < chars.Length; length++) - { - if(data[length] == 0) - break; - } - - return Encoding.UTF8.GetString(data, length); - } - } - - return null; - } - public void Dispose() { if(handle != IntPtr.Zero) @@ -57,8 +36,11 @@ public void Dispose() } } - public async Task GenerateAsync(string dagDir, ILogger logger, CancellationToken ct) + public async Task GenerateAsync(string dagDir, ulong dagEpochLength, ILogger logger, CancellationToken ct) { + // note that dagEpochLength is not used here + // it is only used in the etchash implementation + Contract.Requires(!string.IsNullOrEmpty(dagDir)); if(handle == IntPtr.Zero) @@ -123,7 +105,7 @@ public unsafe bool Compute(ILogger logger, byte[] hash, ulong nonce, out byte[] var value = new UbqHash.ethash_return_value(); - fixed (byte* input = hash) + fixed(byte* input = hash) { UbqHash.ethash_full_compute(handle, input, nonce, ref value); } diff --git a/src/Miningcore/Crypto/Hashing/Ubqhash/UbqhashFull.cs b/src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/UbqhashFull.cs similarity index 65% rename from src/Miningcore/Crypto/Hashing/Ubqhash/UbqhashFull.cs rename to src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/UbqhashFull.cs index dbbb62bc36..cb205c3188 100644 --- a/src/Miningcore/Crypto/Hashing/Ubqhash/UbqhashFull.cs +++ b/src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/UbqhashFull.cs @@ -1,12 +1,15 @@ +using System.Text; using Miningcore.Blockchain.Ethereum; using Miningcore.Contracts; +using Miningcore.Native; using NLog; -namespace Miningcore.Crypto.Hashing.Ubqhash; +namespace Miningcore.Crypto.Hashing.Ethash.Ubqhash; -public class UbqhashFull : IDisposable +[Identifier("ubqhash")] +public class UbqhashFull : IEthashFull { - public UbqhashFull(int numCaches, string dagDir) + public void Setup(int numCaches, string dagDir, ulong hardForkBlock) { Contract.Requires(!string.IsNullOrEmpty(dagDir)); @@ -16,9 +19,10 @@ public UbqhashFull(int numCaches, string dagDir) private int numCaches; // Maximum number of caches to keep before eviction (only init, don't modify) private readonly object cacheLock = new(); - private readonly Dictionary caches = new(); - private DagUbqhash future; - private readonly string dagDir; + private readonly Dictionary caches = new(); + private Dag future; + private string dagDir; + public string AlgoName { get; } = "Ubqhash"; public void Dispose() { @@ -26,10 +30,10 @@ public void Dispose() value.Dispose(); } - public async Task GetDagAsync(ulong block, ILogger logger, CancellationToken ct) + public async Task GetDagAsync(ulong block, ILogger logger, CancellationToken ct) { var epoch = block / EthereumConstants.EpochLength; - DagUbqhash result; + Dag result; lock(cacheLock) { @@ -62,7 +66,7 @@ public async Task GetDagAsync(ulong block, ILogger logger, Cancellat else { logger.Info(() => $"No pre-generated DAG available, creating new for epoch {epoch}"); - result = new DagUbqhash(epoch); + result = new Dag(epoch); } caches[epoch] = result; @@ -72,10 +76,10 @@ public async Task GetDagAsync(ulong block, ILogger logger, Cancellat else if(future == null || future.Epoch <= epoch) { logger.Info(() => $"Pre-generating DAG for epoch {epoch + 1}"); - future = new DagUbqhash(epoch + 1); + future = new Dag(epoch + 1); #pragma warning disable 4014 - future.GenerateAsync(dagDir, logger, ct); + future.GenerateAsync(dagDir, 0, logger, ct); #pragma warning restore 4014 } @@ -83,8 +87,30 @@ public async Task GetDagAsync(ulong block, ILogger logger, Cancellat } // get/generate current one - await result.GenerateAsync(dagDir, logger, ct); + await result.GenerateAsync(dagDir, 0, logger, ct); return result; } + + public unsafe string GetDefaultDagDirectory() + { + var chars = new byte[512]; + + fixed(byte* data = chars) + { + if(UbqHash.ethash_get_default_dirname(data, chars.Length)) + { + int length; + for(length = 0; length < chars.Length; length++) + { + if(data[length] == 0) + break; + } + + return Encoding.UTF8.GetString(data, length); + } + } + + return null; + } } diff --git a/src/Miningcore/Program.cs b/src/Miningcore/Program.cs index 42bc7761da..6ba8590086 100644 --- a/src/Miningcore/Program.cs +++ b/src/Miningcore/Program.cs @@ -27,7 +27,7 @@ using Miningcore.Configuration; using Miningcore.Crypto.Hashing.Algorithms; using Miningcore.Crypto.Hashing.Equihash; -using Miningcore.Crypto.Hashing.Ethash; +using Miningcore.Crypto.Hashing.Ethash.Ethash; using Miningcore.Extensions; using Miningcore.Messaging; using Miningcore.Mining; @@ -53,9 +53,9 @@ using NLog.Targets; using Prometheus; using WebSocketManager; +using static Miningcore.Util.ActionUtils; using ILogger = NLog.ILogger; using LogLevel = Microsoft.Extensions.Logging.LogLevel; -using static Miningcore.Util.ActionUtils; // ReSharper disable AssignNullToNotNullAttribute // ReSharper disable PossibleNullReferenceException @@ -183,12 +183,12 @@ public static async Task Main(string[] args) }); // NSwag - #if DEBUG +#if DEBUG services.AddOpenApiDocument(settings => { settings.DocumentProcessors.Insert(0, new NSwagDocumentProcessor()); }); - #endif +#endif services.AddResponseCompression(); services.AddCors(); @@ -218,9 +218,9 @@ public static async Task Main(string[] args) "/metrics" }, clusterConfig.Api?.MetricsIpWhitelist); - #if DEBUG +#if DEBUG app.UseOpenApi(); - #endif +#endif app.UseResponseCompression(); app.UseCors(corsPolicyBuilder => corsPolicyBuilder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()); @@ -369,20 +369,20 @@ protected override async Task ExecuteAsync(CancellationToken ct) .Where(config => config.Enabled) .Select(config => RunPool(config, coinTemplates, ct)); - await Guard(()=> Task.WhenAll(tasks), ex => + await Guard(() => Task.WhenAll(tasks), ex => { switch(ex) { case PoolStartupException pse: - { - var _logger = pse.PoolId != null ? LogUtil.GetPoolScopedLogger(GetType(), pse.PoolId) : logger; - _logger.Error(() => $"{pse.Message}"); + { + var _logger = pse.PoolId != null ? LogUtil.GetPoolScopedLogger(GetType(), pse.PoolId) : logger; + _logger.Error(() => $"{pse.Message}"); - logger.Error(() => "Cluster cannot start. Good Bye!"); + logger.Error(() => "Cluster cannot start. Good Bye!"); - hal.StopApplication(); - break; - } + hal.StopApplication(); + break; + } default: throw ex; @@ -533,7 +533,7 @@ private static CommandLineApplication ParseCommandLine(string[] args) versionOption = app.Option("-v|--version", "Version Information", CommandOptionType.NoValue); configFileOption = app.Option("-c|--config ", "Configuration File", CommandOptionType.SingleValue); - dumpConfigOption = app.Option("-dc|--dumpconfig", "Dump the configuration (useful for trouble-shooting typos in the config file)",CommandOptionType.NoValue); + dumpConfigOption = app.Option("-dc|--dumpconfig", "Dump the configuration (useful for trouble-shooting typos in the config file)", CommandOptionType.NoValue); shareRecoveryOption = app.Option("-rs", "Import lost shares using existing recovery file", CommandOptionType.SingleValue); generateSchemaOption = app.Option("-gcs|--generate-config-schema ", "Generate JSON schema from configuration options", CommandOptionType.SingleValue); app.HelpOption("-? | -h | --help"); @@ -560,7 +560,7 @@ private static ClusterConfig ReadConfig(string file) { using(var validatingReader = new JSchemaValidatingReader(jsonReader) { - Schema = LoadSchema() + Schema = LoadSchema() }) { return serializer.Deserialize(validatingReader); @@ -781,8 +781,14 @@ private static async Task PreFlightChecks(IServiceProvider services) EquihashSolver.messageBus = messageBus; EquihashSolver.MaxThreads = clusterConfig.EquihashMaxThreads ?? 1; - // Configure Ethhash - Dag.messageBus = messageBus; + // Configure Ethash + Miningcore.Crypto.Hashing.Ethash.Ethash.Dag.messageBus = messageBus; + + // Configure Etchash + Miningcore.Crypto.Hashing.Ethash.Etchash.Dag.messageBus = messageBus; + + // Configure Ubqhash + Miningcore.Crypto.Hashing.Ethash.Ubqhash.Dag.messageBus = messageBus; // Configure Verthash Verthash.messageBus = messageBus; @@ -823,7 +829,7 @@ private static async Task ConfigurePostgresCompatibilityOptions(IServiceProvider if(enableLegacyTimestampBehavior) { - logger.Info(()=> "Enabling Npgsql Legacy Timestamp Behavior"); + logger.Info(() => "Enabling Npgsql Legacy Timestamp Behavior"); AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); } @@ -886,7 +892,7 @@ private static void ConfigurePostgres(PostgresConfig pgConfig, ContainerBuilder connectionString.Append($"CommandTimeout={pgConfig.CommandTimeout ?? 300};"); - logger.Debug(()=> $"Using postgres connection string: {connectionString}"); + logger.Debug(() => $"Using postgres connection string: {connectionString}"); // register connection factory builder.RegisterInstance(new PgConnectionFactory(connectionString.ToString())) diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index 80c1c11bdf..064c033599 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -4276,7 +4276,8 @@ "uncle": "https://explorer.callisto.network/blocks/$height$" }, "explorerTxLink": "https://explorer.callisto.network/tx/{0}", - "explorerAccountLink": "https://explorer.callisto.network/address/{0}" + "explorerAccountLink": "https://explorer.callisto.network/address/{0}", + "ethasher": "ethash" }, "ethereum": { "name": "Ethereum", @@ -4293,7 +4294,8 @@ "uncle": "https://etherscan.io/uncle/$height$" }, "explorerTxLink": "https://etherscan.io/tx/{0}", - "explorerAccountLink": "https://etherscan.io/address/{0}" + "explorerAccountLink": "https://etherscan.io/address/{0}", + "ethasher": "ethash" }, "ethereumclassic": { "name": "Ethereum Classic", @@ -4310,7 +4312,8 @@ "uncle": "https://blockscout.com/etc/mainnet/block/$height$" }, "explorerTxLink": "https://blockscout.com/etc/mainnet/tx/{0}", - "explorerAccountLink": "https://blockscout.com/etc/mainnet/address/{0}" + "explorerAccountLink": "https://blockscout.com/etc/mainnet/address/{0}", + "ethasher": "etchash" }, "ethereum-pow": { "name": "EthereumPoW", @@ -4327,7 +4330,8 @@ "uncle": "https://www.oklink.com/en/ethw/uncle/$height$" }, "explorerTxLink": "https://www.oklink.com/en/ethw/tx/{0}", - "explorerAccountLink": "https://www.oklink.com/en/ethw/address/{0}" + "explorerAccountLink": "https://www.oklink.com/en/ethw/address/{0}", + "ethasher": "ethash" }, "etherone": { "name": "EtherOne", @@ -4344,7 +4348,8 @@ "uncle": "https://blockscout.etherone.one/uncles/$height$" }, "explorerTxLink": "https://blockscout.etherone.one/tx/{0}", - "explorerAccountLink": "https://blockscout.etherone.one/address/{0}" + "explorerAccountLink": "https://blockscout.etherone.one/address/{0}", + "ethasher": "ethash" }, "pinkchain": { "name": "PinkChain", @@ -4361,7 +4366,8 @@ "uncle": "https://pinkscan.org/uncle/$height$" }, "explorerTxLink": "https://pinkscan.org/tx/{0}", - "explorerAccountLink": "https://pinkscan.org/address/{0}" + "explorerAccountLink": "https://pinkscan.org/address/{0}", + "ethasher": "ethash" }, "ubiq": { "name": "Ubiq", @@ -4378,7 +4384,8 @@ "uncle": "https://ubiqscan.io/uncle/$height$" }, "explorerTxLink": "https://ubiqscan.io/tx/{0}", - "explorerAccountLink": "https://ubiqscan.io/address/{0}" + "explorerAccountLink": "https://ubiqscan.io/address/{0}", + "ethasher": "ubqhash" }, "ergo": { "name": "Ergo", From c5448b392b3c7e318e9604e4481b49de9e019c13 Mon Sep 17 00:00:00 2001 From: jon4hz Date: Mon, 30 Jan 2023 19:13:11 +0100 Subject: [PATCH 3/5] fix: simpler dag interface --- src/Miningcore/Crypto/Hashing/Ethash/Abstractions.cs | 3 --- src/Miningcore/Crypto/Hashing/Ethash/Ethash/Dag.cs | 5 +---- src/Miningcore/Crypto/Hashing/Ethash/Ethash/EthashFull.cs | 4 ++-- src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/Dag.cs | 5 +---- src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/UbqhashFull.cs | 4 ++-- 5 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/Miningcore/Crypto/Hashing/Ethash/Abstractions.cs b/src/Miningcore/Crypto/Hashing/Ethash/Abstractions.cs index 87c2c98311..602bded2b2 100644 --- a/src/Miningcore/Crypto/Hashing/Ethash/Abstractions.cs +++ b/src/Miningcore/Crypto/Hashing/Ethash/Abstractions.cs @@ -4,9 +4,6 @@ namespace Miningcore.Crypto.Hashing.Ethash; public interface IEthashDag : IDisposable { - ulong Epoch { get; set; } - DateTime LastUsed { get; set; } - Task GenerateAsync(string dagDir, ulong dagEpochLength, ILogger logger, CancellationToken ct); bool Compute(ILogger logger, byte[] hash, ulong nonce, out byte[] mixDigest, out byte[] result); } diff --git a/src/Miningcore/Crypto/Hashing/Ethash/Ethash/Dag.cs b/src/Miningcore/Crypto/Hashing/Ethash/Ethash/Dag.cs index e34cc6d0b4..dbc941131e 100644 --- a/src/Miningcore/Crypto/Hashing/Ethash/Ethash/Dag.cs +++ b/src/Miningcore/Crypto/Hashing/Ethash/Ethash/Dag.cs @@ -36,11 +36,8 @@ public void Dispose() } } - public async Task GenerateAsync(string dagDir, ulong dagEpochLength, ILogger logger, CancellationToken ct) + public async Task GenerateAsync(string dagDir, ILogger logger, CancellationToken ct) { - // note that dagEpochLength is not used here - // it is only used in the etchash implementation - Contract.Requires(!string.IsNullOrEmpty(dagDir)); if(handle == IntPtr.Zero) diff --git a/src/Miningcore/Crypto/Hashing/Ethash/Ethash/EthashFull.cs b/src/Miningcore/Crypto/Hashing/Ethash/Ethash/EthashFull.cs index fa567572d3..359f5d88e8 100644 --- a/src/Miningcore/Crypto/Hashing/Ethash/Ethash/EthashFull.cs +++ b/src/Miningcore/Crypto/Hashing/Ethash/Ethash/EthashFull.cs @@ -79,7 +79,7 @@ public async Task GetDagAsync(ulong block, ILogger logger, Cancellat future = new Dag(epoch + 1); #pragma warning disable 4014 - future.GenerateAsync(dagDir, 0, logger, ct); + future.GenerateAsync(dagDir, logger, ct); #pragma warning restore 4014 } @@ -87,7 +87,7 @@ public async Task GetDagAsync(ulong block, ILogger logger, Cancellat } // get/generate current one - await result.GenerateAsync(dagDir, 0, logger, ct); + await result.GenerateAsync(dagDir, logger, ct); return result; } diff --git a/src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/Dag.cs b/src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/Dag.cs index 0901bfcfe8..e9882efdeb 100644 --- a/src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/Dag.cs +++ b/src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/Dag.cs @@ -36,11 +36,8 @@ public void Dispose() } } - public async Task GenerateAsync(string dagDir, ulong dagEpochLength, ILogger logger, CancellationToken ct) + public async Task GenerateAsync(string dagDir, ILogger logger, CancellationToken ct) { - // note that dagEpochLength is not used here - // it is only used in the etchash implementation - Contract.Requires(!string.IsNullOrEmpty(dagDir)); if(handle == IntPtr.Zero) diff --git a/src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/UbqhashFull.cs b/src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/UbqhashFull.cs index cb205c3188..85cc0b36b7 100644 --- a/src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/UbqhashFull.cs +++ b/src/Miningcore/Crypto/Hashing/Ethash/Ubqhash/UbqhashFull.cs @@ -79,7 +79,7 @@ public async Task GetDagAsync(ulong block, ILogger logger, Cancellat future = new Dag(epoch + 1); #pragma warning disable 4014 - future.GenerateAsync(dagDir, 0, logger, ct); + future.GenerateAsync(dagDir, logger, ct); #pragma warning restore 4014 } @@ -87,7 +87,7 @@ public async Task GetDagAsync(ulong block, ILogger logger, Cancellat } // get/generate current one - await result.GenerateAsync(dagDir, 0, logger, ct); + await result.GenerateAsync(dagDir, logger, ct); return result; } From 9afd8fe2272ff3c201a0d1d953b5755a3daf5cf4 Mon Sep 17 00:00:00 2001 From: jon4hz Date: Tue, 31 Jan 2023 14:02:03 +0100 Subject: [PATCH 4/5] feat: log error from configure daemons --- .../Blockchain/Ethereum/EthereumJobManager.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Miningcore/Blockchain/Ethereum/EthereumJobManager.cs b/src/Miningcore/Blockchain/Ethereum/EthereumJobManager.cs index d65c629974..4e453f7a98 100644 --- a/src/Miningcore/Blockchain/Ethereum/EthereumJobManager.cs +++ b/src/Miningcore/Blockchain/Ethereum/EthereumJobManager.cs @@ -476,13 +476,19 @@ protected override void ConfigureDaemons() protected override async Task AreDaemonsHealthyAsync(CancellationToken ct) { var response = await rpc.ExecuteAsync(logger, EC.GetBlockByNumber, ct, new[] { (object) "latest", true }); - - return response.Error == null; + if(response.Error != null) + { + logger.Error(() => $"Daemon reports: {response.Error.Message}"); + return false; + } + return true; } protected override async Task AreDaemonsConnectedAsync(CancellationToken ct) { var response = await rpc.ExecuteAsync(logger, EC.GetPeerCount, ct); + if(response.Error != null) + logger.Error(() => $"Daemon reports: {response.Error.Message}"); return response.Error == null && response.Response.IntegralFromHex() > 0; } From 354d9664e921a7b47567c6dacc3547fb8e1e1f1a Mon Sep 17 00:00:00 2001 From: jon4hz Date: Tue, 31 Jan 2023 16:35:31 +0100 Subject: [PATCH 5/5] fix: dont hardcode forkblock in libetchash --- .../Crypto/Hashing/Ethash/Etchash/Dag.cs | 6 +- .../Hashing/Ethash/Etchash/EtchashFull.cs | 4 +- src/Miningcore/Native/EtcHash.cs | 6 +- src/Native/libetchash/ethash.h | 200 ++++++------ src/Native/libetchash/exports.cpp | 23 +- src/Native/libetchash/internal.c | 251 ++++++++------- src/Native/libetchash/internal.h | 291 +++++++++--------- 7 files changed, 408 insertions(+), 373 deletions(-) diff --git a/src/Miningcore/Crypto/Hashing/Ethash/Etchash/Dag.cs b/src/Miningcore/Crypto/Hashing/Ethash/Etchash/Dag.cs index 33bf49a0e4..0a55a722a2 100644 --- a/src/Miningcore/Crypto/Hashing/Ethash/Etchash/Dag.cs +++ b/src/Miningcore/Crypto/Hashing/Ethash/Etchash/Dag.cs @@ -37,7 +37,7 @@ public void Dispose() } } - public async Task GenerateAsync(string dagDir, ulong dagEpochLength, ILogger logger, CancellationToken ct) + public async Task GenerateAsync(string dagDir, ulong dagEpochLength, ulong hardForkBlock, ILogger logger, CancellationToken ct) { Contract.Requires(!string.IsNullOrEmpty(dagDir)); @@ -61,12 +61,12 @@ await Task.Run(() => logger.Debug(() => $"Epoch length used: {dagEpochLength}"); // Generate a temporary cache - var light = EtcHash.ethash_light_new(block); + var light = EtcHash.ethash_light_new(block, hardForkBlock); try { // Generate the actual DAG - handle = EtcHash.ethash_full_new(dagDir, light, progress => + handle = EtcHash.ethash_full_new(dagDir, light, hardForkBlock, progress => { logger.Info(() => $"Generating DAG for epoch {Epoch}: {progress}%"); diff --git a/src/Miningcore/Crypto/Hashing/Ethash/Etchash/EtchashFull.cs b/src/Miningcore/Crypto/Hashing/Ethash/Etchash/EtchashFull.cs index 215d7c93b7..7f747baf4d 100644 --- a/src/Miningcore/Crypto/Hashing/Ethash/Etchash/EtchashFull.cs +++ b/src/Miningcore/Crypto/Hashing/Ethash/Etchash/EtchashFull.cs @@ -85,7 +85,7 @@ public async Task GetDagAsync(ulong block, ILogger logger, Cancellat future = new Dag(epoch + 1); #pragma warning disable 4014 - future.GenerateAsync(dagDir, dagEpochLength, logger, ct); + future.GenerateAsync(dagDir, dagEpochLength, hardForkBlock, logger, ct); #pragma warning restore 4014 } @@ -93,7 +93,7 @@ public async Task GetDagAsync(ulong block, ILogger logger, Cancellat } // get/generate current one - await result.GenerateAsync(dagDir, dagEpochLength, logger, ct); + await result.GenerateAsync(dagDir, dagEpochLength, hardForkBlock, logger, ct); return result; } diff --git a/src/Miningcore/Native/EtcHash.cs b/src/Miningcore/Native/EtcHash.cs index 3dd80fd5fa..209e55eb61 100644 --- a/src/Miningcore/Native/EtcHash.cs +++ b/src/Miningcore/Native/EtcHash.cs @@ -29,7 +29,7 @@ public struct ethash_return_value /// The block number for which to create the handler /// Newly allocated ethash_light handler or NULL [DllImport("libetchash", EntryPoint = "ethash_light_new_export", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr ethash_light_new(ulong block_number); + public static extern IntPtr ethash_light_new(ulong block_number, ulong fork_block); /// /// Frees a previously allocated ethash_light handler @@ -46,7 +46,7 @@ public struct ethash_return_value /// The nonce to pack into the mix /// an object of ethash_return_value_t holding the return values [DllImport("libetchash", EntryPoint = "ethash_light_compute_export", CallingConvention = CallingConvention.Cdecl)] - public static extern void ethash_light_compute(IntPtr handle, byte* header_hash, ulong nonce, ref ethash_return_value result); + public static extern void ethash_light_compute(IntPtr handle, byte* header_hash, ulong nonce, ulong fork_block, ref ethash_return_value result); /// /// Allocate and initialize a new ethash_full handler @@ -64,7 +64,7 @@ public struct ethash_return_value /// /// [DllImport("libetchash", EntryPoint = "ethash_full_new_export", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr ethash_full_new(string dagDir, IntPtr light, ethash_callback_t callback); + public static extern IntPtr ethash_full_new(string dagDir, IntPtr light, ulong fork_block, ethash_callback_t callback); /// /// Frees a previously allocated ethash_full handler diff --git a/src/Native/libetchash/ethash.h b/src/Native/libetchash/ethash.h index 875f5e8914..513304da21 100644 --- a/src/Native/libetchash/ethash.h +++ b/src/Native/libetchash/ethash.h @@ -16,8 +16,8 @@ */ /** @file ethash.h -* @date 2015 -*/ + * @date 2015 + */ #pragma once #include @@ -29,12 +29,12 @@ #define ETHASH_REVISION 23 #define ETHASH_DATASET_BYTES_INIT 1073741824U // 2**30 #define ETHASH_DATASET_BYTES_GROWTH 8388608U // 2**23 -#define ETHASH_CACHE_BYTES_INIT 1073741824U // 2**24 -#define ETHASH_CACHE_BYTES_GROWTH 131072U // 2**17 +#define ETHASH_CACHE_BYTES_INIT 1073741824U // 2**24 +#define ETHASH_CACHE_BYTES_GROWTH 131072U // 2**17 #define ETHASH_EPOCH_LENGTH 30000U #define ETHASH_EPOCH_LENGTH_NEW 60000U -#define ETCHASH_FORK_BLOCK 11700000 // classic mainnet -//#define ETCHASH_FORK_BLOCK 2520000 // mordor +// #define ETCHASH_FORK_BLOCK 11700000 // classic mainnet +// #define ETCHASH_FORK_BLOCK 2520000 // mordor #define ETHASH_MIX_BYTES 128 #define ETHASH_HASH_BYTES 64 #define ETHASH_DATASET_PARENTS 256 @@ -44,108 +44,116 @@ #define ETHASH_DAG_MAGIC_NUM 0xFEE1DEADBADDCAFE #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/// Type of a seedhash/blockhash e.t.c. -typedef struct ethash_h256 { uint8_t b[32]; } ethash_h256_t; + /// Type of a seedhash/blockhash e.t.c. + typedef struct ethash_h256 + { + uint8_t b[32]; + } ethash_h256_t; // convenience macro to statically initialize an h256_t // usage: // ethash_h256_t a = ethash_h256_static_init(1, 2, 3, ... ) // have to provide all 32 values. If you don't provide all the rest // will simply be unitialized (not guranteed to be 0) -#define ethash_h256_static_init(...) \ - { {__VA_ARGS__} } - -struct ethash_light; -typedef struct ethash_light* ethash_light_t; -struct ethash_full; -typedef struct ethash_full* ethash_full_t; -typedef int(*ethash_callback_t)(unsigned); +#define ethash_h256_static_init(...) \ + { \ + { \ + __VA_ARGS__ \ + } \ + } + + struct ethash_light; + typedef struct ethash_light *ethash_light_t; + struct ethash_full; + typedef struct ethash_full *ethash_full_t; + typedef int (*ethash_callback_t)(unsigned); #pragma pack(push, 1) -typedef struct ethash_return_value { - ethash_h256_t result; - ethash_h256_t mix_hash; - bool success; -} ethash_return_value_t; + typedef struct ethash_return_value + { + ethash_h256_t result; + ethash_h256_t mix_hash; + bool success; + } ethash_return_value_t; #pragma pack(pop) -/** - * Allocate and initialize a new ethash_light handler - * - * @param block_number The block number for which to create the handler - * @return Newly allocated ethash_light handler or NULL in case of - * ERRNOMEM or invalid parameters used for @ref ethash_compute_cache_nodes() - */ -ethash_light_t ethash_light_new(uint64_t block_number); -/** - * Frees a previously allocated ethash_light handler - * @param light The light handler to free - */ -void ethash_light_delete(ethash_light_t light); -/** - * Calculate the light client data - * - * @param light The light client handler - * @param header_hash The header hash to pack into the mix - * @param nonce The nonce to pack into the mix - * @return an object of ethash_return_value_t holding the return values - */ -ethash_return_value_t ethash_light_compute( - ethash_light_t light, - ethash_h256_t const header_hash, - uint64_t nonce -); - -/** - * Allocate and initialize a new ethash_full handler - * - * @param light The light handler containing the cache. - * @param callback A callback function with signature of @ref ethash_callback_t - * It accepts an unsigned with which a progress of DAG calculation - * can be displayed. If all goes well the callback should return 0. - * If a non-zero value is returned then DAG generation will stop. - * Be advised. A progress value of 100 means that DAG creation is - * almost complete and that this function will soon return succesfully. - * It does not mean that the function has already had a succesfull return. - * @return Newly allocated ethash_full handler or NULL in case of - * ERRNOMEM or invalid parameters used for @ref ethash_compute_full_data() - */ -ethash_full_t ethash_full_new(ethash_light_t light, ethash_callback_t callback); - -/** - * Frees a previously allocated ethash_full handler - * @param full The light handler to free - */ -void ethash_full_delete(ethash_full_t full); -/** - * Calculate the full client data - * - * @param full The full client handler - * @param header_hash The header hash to pack into the mix - * @param nonce The nonce to pack into the mix - * @return An object of ethash_return_value to hold the return value - */ -ethash_return_value_t ethash_full_compute( - ethash_full_t full, - ethash_h256_t const header_hash, - uint64_t nonce -); -/** - * Get a pointer to the full DAG data - */ -void const* ethash_full_dag(ethash_full_t full); -/** - * Get the size of the DAG data - */ -uint64_t ethash_full_dag_size(ethash_full_t full); - -/** - * Calculate the seedhash for a given block number - */ -ethash_h256_t ethash_get_seedhash(uint64_t block_number); + /** + * Allocate and initialize a new ethash_light handler + * + * @param block_number The block number for which to create the handler + * @return Newly allocated ethash_light handler or NULL in case of + * ERRNOMEM or invalid parameters used for @ref ethash_compute_cache_nodes() + */ + ethash_light_t ethash_light_new(uint64_t block_number, uint64_t const fork_block); + /** + * Frees a previously allocated ethash_light handler + * @param light The light handler to free + */ + void ethash_light_delete(ethash_light_t light); + /** + * Calculate the light client data + * + * @param light The light client handler + * @param header_hash The header hash to pack into the mix + * @param nonce The nonce to pack into the mix + * @return an object of ethash_return_value_t holding the return values + */ + ethash_return_value_t ethash_light_compute( + ethash_light_t light, + ethash_h256_t const header_hash, + uint64_t nonce, + uint64_t const fork_block); + + /** + * Allocate and initialize a new ethash_full handler + * + * @param light The light handler containing the cache. + * @param callback A callback function with signature of @ref ethash_callback_t + * It accepts an unsigned with which a progress of DAG calculation + * can be displayed. If all goes well the callback should return 0. + * If a non-zero value is returned then DAG generation will stop. + * Be advised. A progress value of 100 means that DAG creation is + * almost complete and that this function will soon return succesfully. + * It does not mean that the function has already had a succesfull return. + * @return Newly allocated ethash_full handler or NULL in case of + * ERRNOMEM or invalid parameters used for @ref ethash_compute_full_data() + */ + ethash_full_t ethash_full_new(ethash_light_t light, uint64_t const fork_block, ethash_callback_t callback); + + /** + * Frees a previously allocated ethash_full handler + * @param full The light handler to free + */ + void ethash_full_delete(ethash_full_t full); + /** + * Calculate the full client data + * + * @param full The full client handler + * @param header_hash The header hash to pack into the mix + * @param nonce The nonce to pack into the mix + * @return An object of ethash_return_value to hold the return value + */ + ethash_return_value_t ethash_full_compute( + ethash_full_t full, + ethash_h256_t const header_hash, + uint64_t nonce); + /** + * Get a pointer to the full DAG data + */ + void const *ethash_full_dag(ethash_full_t full); + /** + * Get the size of the DAG data + */ + uint64_t ethash_full_dag_size(ethash_full_t full); + + /** + * Calculate the seedhash for a given block number + */ + ethash_h256_t ethash_get_seedhash(uint64_t block_number); #ifdef __cplusplus } diff --git a/src/Native/libetchash/exports.cpp b/src/Native/libetchash/exports.cpp index 506cb149c9..bed4e80d68 100644 --- a/src/Native/libetchash/exports.cpp +++ b/src/Native/libetchash/exports.cpp @@ -19,7 +19,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "internal.h" #include "ethash.h" -extern "C" bool ethash_get_default_dirname(char* strbuf, size_t buffsize); +extern "C" bool ethash_get_default_dirname(char *strbuf, size_t buffsize); #ifdef _WIN32 #define MODULE_API __declspec(dllexport) @@ -27,19 +27,19 @@ extern "C" bool ethash_get_default_dirname(char* strbuf, size_t buffsize); #define MODULE_API #endif -extern "C" MODULE_API uint64_t ethash_get_datasize_export(uint64_t const block_number) +extern "C" MODULE_API uint64_t ethash_get_datasize_export(uint64_t const block_number, uint64_t const fork_block) { - return ethash_get_datasize(block_number); + return ethash_get_datasize(block_number, fork_block); } -extern "C" MODULE_API uint64_t ethash_get_cachesize_export(uint64_t const block_number) +extern "C" MODULE_API uint64_t ethash_get_cachesize_export(uint64_t const block_number, uint64_t const fork_block) { - return ethash_get_cachesize(block_number); + return ethash_get_cachesize(block_number, fork_block); } -extern "C" MODULE_API ethash_light_t ethash_light_new_export(uint64_t block_number) +extern "C" MODULE_API ethash_light_t ethash_light_new_export(uint64_t block_number, uint64_t const fork_block) { - return ethash_light_new(block_number); + return ethash_light_new(block_number, fork_block); } extern "C" MODULE_API void ethash_light_delete_export(ethash_light_t light) @@ -51,14 +51,15 @@ extern "C" MODULE_API void ethash_light_compute_export( ethash_light_t light, ethash_h256_t const *header_hash, uint64_t nonce, + uint64_t const fork_block, ethash_return_value_t *result) { - *result = ethash_light_compute(light, *header_hash, nonce); + *result = ethash_light_compute(light, *header_hash, nonce, fork_block); } -extern "C" MODULE_API ethash_full_t ethash_full_new_export(const char *dirname, ethash_light_t light, ethash_callback_t callback) +extern "C" MODULE_API ethash_full_t ethash_full_new_export(const char *dirname, ethash_light_t light, uint64_t const fork_block, ethash_callback_t callback) { - uint64_t full_size = ethash_get_datasize(light->block_number); + uint64_t full_size = ethash_get_datasize(light->block_number, fork_block); ethash_h256_t seedhash = ethash_get_seedhash(light->block_number); return ethash_full_new_internal(dirname, seedhash, full_size, light, callback); } @@ -77,7 +78,7 @@ extern "C" MODULE_API void ethash_full_compute_export( *result = ethash_full_compute(full, *header_hash, nonce); } -extern "C" MODULE_API void const* ethash_full_dag_export(ethash_full_t full) +extern "C" MODULE_API void const *ethash_full_dag_export(ethash_full_t full) { return ethash_full_dag(full); } diff --git a/src/Native/libetchash/internal.c b/src/Native/libetchash/internal.c index 3ab113d478..09cf71e2be 100644 --- a/src/Native/libetchash/internal.c +++ b/src/Native/libetchash/internal.c @@ -15,10 +15,10 @@ along with cpp-ethereum. If not, see . */ /** @file internal.c -* @author Tim Hughes -* @author Matthew Wampler-Doty -* @date 2015 -*/ + * @author Tim Hughes + * @author Matthew Wampler-Doty + * @date 2015 + */ #include #include @@ -45,42 +45,46 @@ #include #endif -uint64_t ethash_get_datasize(uint64_t const block_number) +uint64_t ethash_get_datasize(uint64_t const block_number, uint64_t const fork_block) { - return dag_sizes[etchash_calc_epoch(block_number)]; + return dag_sizes[etchash_calc_epoch(block_number, fork_block)]; } -uint64_t ethash_get_cachesize(uint64_t const block_number) +uint64_t ethash_get_cachesize(uint64_t const block_number, uint64_t const fork_block) { - return cache_sizes[etchash_calc_epoch(block_number)]; + return cache_sizes[etchash_calc_epoch(block_number, fork_block)]; } // Follows Sergio's "STRICT MEMORY HARD HASHING FUNCTIONS" (2014) // https://bitslog.files.wordpress.com/2013/12/memohash-v0-3.pdf // SeqMemoHash(s, R, N) bool static ethash_compute_cache_nodes( - node* const nodes, + node *const nodes, uint64_t cache_size, - ethash_h256_t const* seed -) + ethash_h256_t const *seed) { - if (cache_size % sizeof(node) != 0) { + if (cache_size % sizeof(node) != 0) + { return false; } - uint32_t const num_nodes = (uint32_t) (cache_size / sizeof(node)); + uint32_t const num_nodes = (uint32_t)(cache_size / sizeof(node)); - SHA3_512(nodes[0].bytes, (uint8_t*)seed, 32); + SHA3_512(nodes[0].bytes, (uint8_t *)seed, 32); - for (uint32_t i = 1; i != num_nodes; ++i) { + for (uint32_t i = 1; i != num_nodes; ++i) + { SHA3_512(nodes[i].bytes, nodes[i - 1].bytes, 64); } - for (uint32_t j = 0; j != ETHASH_CACHE_ROUNDS; j++) { - for (uint32_t i = 0; i != num_nodes; i++) { + for (uint32_t j = 0; j != ETHASH_CACHE_ROUNDS; j++) + { + for (uint32_t i = 0; i != num_nodes; i++) + { uint32_t const idx = nodes[i].words[0] % num_nodes; node data; data = nodes[(num_nodes - 1 + i) % num_nodes]; - for (uint32_t w = 0; w != NODE_WORDS; ++w) { + for (uint32_t w = 0; w != NODE_WORDS; ++w) + { data.words[w] ^= nodes[idx].words[w]; } SHA3_512(nodes[i].bytes, data.bytes, sizeof(data)); @@ -93,14 +97,13 @@ bool static ethash_compute_cache_nodes( } void ethash_calculate_dag_item( - node* const ret, + node *const ret, uint32_t node_index, - ethash_light_t const light -) + ethash_light_t const light) { - uint32_t num_parent_nodes = (uint32_t) (light->cache_size / sizeof(node)); - node const* cache_nodes = (node const *) light->cache; - node const* init = &cache_nodes[node_index % num_parent_nodes]; + uint32_t num_parent_nodes = (uint32_t)(light->cache_size / sizeof(node)); + node const *cache_nodes = (node const *)light->cache; + node const *init = &cache_nodes[node_index % num_parent_nodes]; memcpy(ret, init, sizeof(node)); ret->words[0] ^= node_index; SHA3_512(ret->bytes, ret->bytes, sizeof(node)); @@ -112,7 +115,8 @@ void ethash_calculate_dag_item( __m128i xmm3 = ret->xmm[3]; #endif - for (uint32_t i = 0; i != ETHASH_DATASET_PARENTS; ++i) { + for (uint32_t i = 0; i != ETHASH_DATASET_PARENTS; ++i) + { uint32_t parent_index = fnv_hash(node_index ^ i, ret->words[i % NODE_WORDS]) % num_parent_nodes; node const *parent = &cache_nodes[parent_index]; @@ -133,9 +137,10 @@ void ethash_calculate_dag_item( ret->xmm[2] = xmm2; ret->xmm[3] = xmm3; } - #else +#else { - for (unsigned w = 0; w != NODE_WORDS; ++w) { + for (unsigned w = 0; w != NODE_WORDS; ++w) + { ret->words[w] = fnv_hash(ret->words[w], parent->words[w]); } } @@ -145,25 +150,27 @@ void ethash_calculate_dag_item( } bool ethash_compute_full_data( - void* mem, + void *mem, uint64_t full_size, ethash_light_t const light, - ethash_callback_t callback -) + ethash_callback_t callback) { if (full_size % (sizeof(uint32_t) * MIX_WORDS) != 0 || - (full_size % sizeof(node)) != 0) { + (full_size % sizeof(node)) != 0) + { return false; } uint32_t const max_n = (uint32_t)(full_size / sizeof(node)); - node* full_nodes = mem; + node *full_nodes = mem; double const progress_change = 1.0f / max_n; double progress = 0.0f; // now compute full nodes - for (uint32_t n = 0; n != max_n; ++n) { + for (uint32_t n = 0; n != max_n; ++n) + { if (callback && n % (max_n / 100) == 0 && - callback((unsigned int)(ceil(progress * 100.0f))) != 0) { + callback((unsigned int)(ceil(progress * 100.0f))) != 0) + { return false; } @@ -174,15 +181,15 @@ bool ethash_compute_full_data( } static bool ethash_hash( - ethash_return_value_t* ret, - node const* full_nodes, + ethash_return_value_t *ret, + node const *full_nodes, ethash_light_t const light, uint64_t full_size, ethash_h256_t const header_hash, - uint64_t const nonce -) + uint64_t const nonce) { - if (full_size % MIX_WORDS != 0) { + if (full_size % MIX_WORDS != 0) + { return false; } @@ -196,22 +203,28 @@ static bool ethash_hash( SHA3_512(s_mix->bytes, s_mix->bytes, 40); fix_endian_arr32(s_mix[0].words, 16); - node* const mix = s_mix + 1; - for (uint32_t w = 0; w != MIX_WORDS; ++w) { + node *const mix = s_mix + 1; + for (uint32_t w = 0; w != MIX_WORDS; ++w) + { mix->words[w] = s_mix[0].words[w % NODE_WORDS]; } unsigned const page_size = sizeof(uint32_t) * MIX_WORDS; - unsigned const num_full_pages = (unsigned) (full_size / page_size); + unsigned const num_full_pages = (unsigned)(full_size / page_size); - for (unsigned i = 0; i != ETHASH_ACCESSES; ++i) { + for (unsigned i = 0; i != ETHASH_ACCESSES; ++i) + { uint32_t const index = fnv_hash(s_mix->words[0] ^ i, mix->words[i % MIX_WORDS]) % num_full_pages; - for (unsigned n = 0; n != MIX_NODES; ++n) { - node const* dag_node; - if (full_nodes) { + for (unsigned n = 0; n != MIX_NODES; ++n) + { + node const *dag_node; + if (full_nodes) + { dag_node = &full_nodes[MIX_NODES * index + n]; - } else { + } + else + { node tmp_node; ethash_calculate_dag_item(&tmp_node, index * MIX_NODES + n, light); dag_node = &tmp_node; @@ -229,19 +242,20 @@ static bool ethash_hash( mix[n].xmm[2] = _mm_xor_si128(xmm2, dag_node->xmm[2]); mix[n].xmm[3] = _mm_xor_si128(xmm3, dag_node->xmm[3]); } - #else +#else { - for (unsigned w = 0; w != NODE_WORDS; ++w) { + for (unsigned w = 0; w != NODE_WORDS; ++w) + { mix[n].words[w] = fnv_hash(mix[n].words[w], dag_node->words[w]); } } #endif } - } // compress mix - for (uint32_t w = 0; w != MIX_WORDS; w += 4) { + for (uint32_t w = 0; w != MIX_WORDS; w += 4) + { uint32_t reduction = mix->words[w + 0]; reduction = reduction * FNV_PRIME ^ mix->words[w + 1]; reduction = reduction * FNV_PRIME ^ mix->words[w + 2]; @@ -257,11 +271,10 @@ static bool ethash_hash( } void ethash_quick_hash( - ethash_h256_t* return_hash, - ethash_h256_t const* header_hash, + ethash_h256_t *return_hash, + ethash_h256_t const *header_hash, uint64_t nonce, - ethash_h256_t const* mix_hash -) + ethash_h256_t const *mix_hash) { uint8_t buf[64 + 32]; memcpy(buf, header_hash, 32); @@ -278,16 +291,15 @@ ethash_h256_t ethash_get_seedhash(uint64_t block_number) ethash_h256_reset(&ret); uint64_t const epochs = block_number / ETHASH_EPOCH_LENGTH; for (uint32_t i = 0; i < epochs; ++i) - SHA3_256(&ret, (uint8_t*)&ret, 32); + SHA3_256(&ret, (uint8_t *)&ret, 32); return ret; } bool ethash_quick_check_difficulty( - ethash_h256_t const* header_hash, + ethash_h256_t const *header_hash, uint64_t const nonce, - ethash_h256_t const* mix_hash, - ethash_h256_t const* boundary -) + ethash_h256_t const *mix_hash, + ethash_h256_t const *boundary) { ethash_h256_t return_hash; @@ -295,19 +307,22 @@ bool ethash_quick_check_difficulty( return ethash_check_difficulty(&return_hash, boundary); } -ethash_light_t ethash_light_new_internal(uint64_t cache_size, ethash_h256_t const* seed) +ethash_light_t ethash_light_new_internal(uint64_t cache_size, ethash_h256_t const *seed) { struct ethash_light *ret; ret = calloc(sizeof(*ret), 1); - if (!ret) { + if (!ret) + { return NULL; } ret->cache = malloc((size_t)cache_size); - if (!ret->cache) { + if (!ret->cache) + { goto fail_free_light; } - node* nodes = (node*)ret->cache; - if (!ethash_compute_cache_nodes(nodes, cache_size, seed)) { + node *nodes = (node *)ret->cache; + if (!ethash_compute_cache_nodes(nodes, cache_size, seed)) + { goto fail_free_cache_mem; } ret->cache_size = cache_size; @@ -320,39 +335,40 @@ ethash_light_t ethash_light_new_internal(uint64_t cache_size, ethash_h256_t cons return NULL; } -ethash_light_t ethash_light_new(uint64_t block_number) +ethash_light_t ethash_light_new(uint64_t block_number, uint64_t const fork_block) { ethash_h256_t seedhash = ethash_get_seedhash(block_number); ethash_light_t ret; - ret = ethash_light_new_internal(ethash_get_cachesize(block_number), &seedhash); + ret = ethash_light_new_internal(ethash_get_cachesize(block_number, fork_block), &seedhash); ret->block_number = block_number; return ret; } void ethash_light_delete(ethash_light_t light) { - if (light->cache) { + if (light->cache) + { free(light->cache); } free(light); } -uint64_t static etchash_calc_epoch(uint64_t const block_number) +uint64_t static etchash_calc_epoch(uint64_t const block_number, uint64_t const fork_block) { - uint64_t epochLen = block_number >= ETCHASH_FORK_BLOCK ? ETHASH_EPOCH_LENGTH_NEW : ETHASH_EPOCH_LENGTH; - return block_number / epochLen; + uint64_t epochLen = block_number >= fork_block ? ETHASH_EPOCH_LENGTH_NEW : ETHASH_EPOCH_LENGTH; + return block_number / epochLen; } ethash_return_value_t ethash_light_compute_internal( ethash_light_t light, uint64_t full_size, ethash_h256_t const header_hash, - uint64_t nonce -) + uint64_t nonce) { - ethash_return_value_t ret; + ethash_return_value_t ret; ret.success = true; - if (!ethash_hash(&ret, NULL, light, full_size, header_hash, nonce)) { + if (!ethash_hash(&ret, NULL, light, full_size, header_hash, nonce)) + { ret.success = false; } return ret; @@ -361,93 +377,102 @@ ethash_return_value_t ethash_light_compute_internal( ethash_return_value_t ethash_light_compute( ethash_light_t light, ethash_h256_t const header_hash, - uint64_t nonce -) + uint64_t nonce, + uint64_t const fork_block) { - uint64_t full_size = ethash_get_datasize(light->block_number); + uint64_t full_size = ethash_get_datasize(light->block_number, fork_block); return ethash_light_compute_internal(light, full_size, header_hash, nonce); } -static bool ethash_mmap(struct ethash_full* ret, FILE* f) +static bool ethash_mmap(struct ethash_full *ret, FILE *f) { int fd; - char* mmapped_data; + char *mmapped_data; errno = 0; ret->file = f; - if ((fd = ethash_fileno(ret->file)) == -1) { + if ((fd = ethash_fileno(ret->file)) == -1) + { return false; } - mmapped_data= mmap( + mmapped_data = mmap( NULL, (size_t)ret->file_size + ETHASH_DAG_MAGIC_NUM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, - 0 - ); - if (mmapped_data == MAP_FAILED) { + 0); + if (mmapped_data == MAP_FAILED) + { return false; } - ret->data = (node*)(mmapped_data + ETHASH_DAG_MAGIC_NUM_SIZE); + ret->data = (node *)(mmapped_data + ETHASH_DAG_MAGIC_NUM_SIZE); return true; } ethash_full_t ethash_full_new_internal( - char const* dirname, + char const *dirname, ethash_h256_t const seed_hash, uint64_t full_size, ethash_light_t const light, - ethash_callback_t callback -) + ethash_callback_t callback) { - struct ethash_full* ret; + struct ethash_full *ret; FILE *f = NULL; ret = calloc(sizeof(*ret), 1); - if (!ret) { + if (!ret) + { return NULL; } ret->file_size = (size_t)full_size; - switch (ethash_io_prepare(dirname, seed_hash, &f, (size_t)full_size, false)) { + switch (ethash_io_prepare(dirname, seed_hash, &f, (size_t)full_size, false)) + { case ETHASH_IO_FAIL: // ethash_io_prepare will do all ETHASH_CRITICAL() logging in fail case goto fail_free_full; case ETHASH_IO_MEMO_MATCH: - if (!ethash_mmap(ret, f)) { + if (!ethash_mmap(ret, f)) + { ETHASH_CRITICAL("mmap failure()"); goto fail_close_file; } return ret; case ETHASH_IO_MEMO_SIZE_MISMATCH: // if a DAG of same filename but unexpected size is found, silently force new file creation - if (ethash_io_prepare(dirname, seed_hash, &f, (size_t)full_size, true) != ETHASH_IO_MEMO_MISMATCH) { + if (ethash_io_prepare(dirname, seed_hash, &f, (size_t)full_size, true) != ETHASH_IO_MEMO_MISMATCH) + { ETHASH_CRITICAL("Could not recreate DAG file after finding existing DAG with unexpected size."); goto fail_free_full; } // fallthrough to the mismatch case here, DO NOT go through match case ETHASH_IO_MEMO_MISMATCH: - if (!ethash_mmap(ret, f)) { + if (!ethash_mmap(ret, f)) + { ETHASH_CRITICAL("mmap failure()"); goto fail_close_file; } break; } - if (!ethash_compute_full_data(ret->data, full_size, light, callback)) { + if (!ethash_compute_full_data(ret->data, full_size, light, callback)) + { ETHASH_CRITICAL("Failure at computing DAG data."); goto fail_free_full_data; } // after the DAG has been filled then we finalize it by writting the magic number at the beginning - if (fseek(f, 0, SEEK_SET) != 0) { + if (fseek(f, 0, SEEK_SET) != 0) + { ETHASH_CRITICAL("Could not seek to DAG file start to write magic number."); goto fail_free_full_data; } uint64_t const magic_num = ETHASH_DAG_MAGIC_NUM; - if (fwrite(&magic_num, ETHASH_DAG_MAGIC_NUM_SIZE, 1, f) != 1) { + if (fwrite(&magic_num, ETHASH_DAG_MAGIC_NUM_SIZE, 1, f) != 1) + { ETHASH_CRITICAL("Could not write magic number to DAG's beginning."); goto fail_free_full_data; } - if (fflush(f) != 0) {// make sure the magic number IS there + if (fflush(f) != 0) + { // make sure the magic number IS there ETHASH_CRITICAL("Could not flush memory mapped data to DAG file. Insufficient space?"); goto fail_free_full_data; } @@ -463,13 +488,14 @@ ethash_full_t ethash_full_new_internal( return NULL; } -ethash_full_t ethash_full_new(ethash_light_t light, ethash_callback_t callback) +ethash_full_t ethash_full_new(ethash_light_t light, uint64_t const fork_block, ethash_callback_t callback) { char strbuf[256]; - if (!ethash_get_default_dirname(strbuf, 256)) { + if (!ethash_get_default_dirname(strbuf, 256)) + { return NULL; } - uint64_t full_size = ethash_get_datasize(light->block_number); + uint64_t full_size = ethash_get_datasize(light->block_number, fork_block); ethash_h256_t seedhash = ethash_get_seedhash(light->block_number); return ethash_full_new_internal(strbuf, seedhash, full_size, light, callback); } @@ -478,7 +504,8 @@ void ethash_full_delete(ethash_full_t full) { // could check that munmap(..) == 0 but even if it did not can't really do anything here munmap(full->data, (size_t)full->file_size); - if (full->file) { + if (full->file) + { fclose(full->file); } free(full); @@ -487,24 +514,24 @@ void ethash_full_delete(ethash_full_t full) ethash_return_value_t ethash_full_compute( ethash_full_t full, ethash_h256_t const header_hash, - uint64_t nonce -) + uint64_t nonce) { ethash_return_value_t ret; ret.success = true; if (!ethash_hash( - &ret, - (node const*)full->data, - NULL, - full->file_size, - header_hash, - nonce)) { + &ret, + (node const *)full->data, + NULL, + full->file_size, + header_hash, + nonce)) + { ret.success = false; } return ret; } -void const* ethash_full_dag(ethash_full_t full) +void const *ethash_full_dag(ethash_full_t full) { return full->data; } diff --git a/src/Native/libetchash/internal.h b/src/Native/libetchash/internal.h index 7d630d272d..ea59385d15 100644 --- a/src/Native/libetchash/internal.h +++ b/src/Native/libetchash/internal.h @@ -9,169 +9,168 @@ #endif #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif // compile time settings -#define NODE_WORDS (64/4) -#define MIX_WORDS (ETHASH_MIX_BYTES/4) +#define NODE_WORDS (64 / 4) +#define MIX_WORDS (ETHASH_MIX_BYTES / 4) #define MIX_NODES (MIX_WORDS / NODE_WORDS) #include -typedef union node { - uint8_t bytes[NODE_WORDS * 4]; - uint32_t words[NODE_WORDS]; - uint64_t double_words[NODE_WORDS / 2]; + typedef union node + { + uint8_t bytes[NODE_WORDS * 4]; + uint32_t words[NODE_WORDS]; + uint64_t double_words[NODE_WORDS / 2]; #if defined(_M_X64) && HAVE_SSE2 - __m128i xmm[NODE_WORDS/4]; + __m128i xmm[NODE_WORDS / 4]; #endif -} node; + } node; -static inline uint8_t ethash_h256_get(ethash_h256_t const* hash, unsigned int i) -{ - return hash->b[i]; -} + static inline uint8_t ethash_h256_get(ethash_h256_t const *hash, unsigned int i) + { + return hash->b[i]; + } -static inline void ethash_h256_set(ethash_h256_t* hash, unsigned int i, uint8_t v) -{ - hash->b[i] = v; -} + static inline void ethash_h256_set(ethash_h256_t *hash, unsigned int i, uint8_t v) + { + hash->b[i] = v; + } -static inline void ethash_h256_reset(ethash_h256_t* hash) -{ - memset(hash, 0, 32); -} + static inline void ethash_h256_reset(ethash_h256_t *hash) + { + memset(hash, 0, 32); + } -// Returns if hash is less than or equal to boundary (2^256/difficulty) -static inline bool ethash_check_difficulty( - ethash_h256_t const* hash, - ethash_h256_t const* boundary -) -{ - // Boundary is big endian - for (int i = 0; i < 32; i++) { - if (ethash_h256_get(hash, i) == ethash_h256_get(boundary, i)) { - continue; + // Returns if hash is less than or equal to boundary (2^256/difficulty) + static inline bool ethash_check_difficulty( + ethash_h256_t const *hash, + ethash_h256_t const *boundary) + { + // Boundary is big endian + for (int i = 0; i < 32; i++) + { + if (ethash_h256_get(hash, i) == ethash_h256_get(boundary, i)) + { + continue; + } + return ethash_h256_get(hash, i) < ethash_h256_get(boundary, i); } - return ethash_h256_get(hash, i) < ethash_h256_get(boundary, i); + return true; } - return true; -} -/** - * Difficulty quick check for POW preverification - * - * @param header_hash The hash of the header - * @param nonce The block's nonce - * @param mix_hash The mix digest hash - * @param boundary The boundary is defined as (2^256 / difficulty) - * @return true for succesful pre-verification and false otherwise - */ -bool ethash_quick_check_difficulty( - ethash_h256_t const* header_hash, - uint64_t const nonce, - ethash_h256_t const* mix_hash, - ethash_h256_t const* boundary -); - -struct ethash_light { - void* cache; - uint64_t cache_size; - uint64_t block_number; -}; - -/** - * Allocate and initialize a new ethash_light handler. Internal version - * - * @param cache_size The size of the cache in bytes - * @param seed Block seedhash to be used during the computation of the - * cache nodes - * @return Newly allocated ethash_light handler or NULL in case of - * ERRNOMEM or invalid parameters used for @ref ethash_compute_cache_nodes() - */ -ethash_light_t ethash_light_new_internal(uint64_t cache_size, ethash_h256_t const* seed); - -/** - * Calculate the light client data. Internal version. - * - * @param light The light client handler - * @param full_size The size of the full data in bytes. - * @param header_hash The header hash to pack into the mix - * @param nonce The nonce to pack into the mix - * @return The resulting hash. - */ -ethash_return_value_t ethash_light_compute_internal( - ethash_light_t light, - uint64_t full_size, - ethash_h256_t const header_hash, - uint64_t nonce -); - -struct ethash_full { - FILE* file; - uint64_t file_size; - node* data; -}; - -/** - * Allocate and initialize a new ethash_full handler. Internal version. - * - * @param dirname The directory in which to put the DAG file. - * @param seedhash The seed hash of the block. Used in the DAG file naming. - * @param full_size The size of the full data in bytes. - * @param cache A cache object to use that was allocated with @ref ethash_cache_new(). - * Iff this function succeeds the ethash_full_t will take memory - * memory ownership of the cache and free it at deletion. If - * not then the user still has to handle freeing of the cache himself. - * @param callback A callback function with signature of @ref ethash_callback_t - * It accepts an unsigned with which a progress of DAG calculation - * can be displayed. If all goes well the callback should return 0. - * If a non-zero value is returned then DAG generation will stop. - * @return Newly allocated ethash_full handler or NULL in case of - * ERRNOMEM or invalid parameters used for @ref ethash_compute_full_data() - */ -ethash_full_t ethash_full_new_internal( - char const* dirname, - ethash_h256_t const seed_hash, - uint64_t full_size, - ethash_light_t const light, - ethash_callback_t callback -); - -void ethash_calculate_dag_item( - node* const ret, - uint32_t node_index, - ethash_light_t const cache -); - -void ethash_quick_hash( - ethash_h256_t* return_hash, - ethash_h256_t const* header_hash, - const uint64_t nonce, - ethash_h256_t const* mix_hash -); - -uint64_t ethash_get_datasize(uint64_t const block_number); -uint64_t ethash_get_cachesize(uint64_t const block_number); -static uint64_t etchash_calc_epoch(uint64_t const block_number); - -/** - * Compute the memory data for a full node's memory - * - * @param mem A pointer to an ethash full's memory - * @param full_size The size of the full data in bytes - * @param cache A cache object to use in the calculation - * @param callback The callback function. Check @ref ethash_full_new() for details. - * @return true if all went fine and false for invalid parameters - */ -bool ethash_compute_full_data( - void* mem, - uint64_t full_size, - ethash_light_t const light, - ethash_callback_t callback -); + /** + * Difficulty quick check for POW preverification + * + * @param header_hash The hash of the header + * @param nonce The block's nonce + * @param mix_hash The mix digest hash + * @param boundary The boundary is defined as (2^256 / difficulty) + * @return true for succesful pre-verification and false otherwise + */ + bool ethash_quick_check_difficulty( + ethash_h256_t const *header_hash, + uint64_t const nonce, + ethash_h256_t const *mix_hash, + ethash_h256_t const *boundary); + + struct ethash_light + { + void *cache; + uint64_t cache_size; + uint64_t block_number; + }; + + /** + * Allocate and initialize a new ethash_light handler. Internal version + * + * @param cache_size The size of the cache in bytes + * @param seed Block seedhash to be used during the computation of the + * cache nodes + * @return Newly allocated ethash_light handler or NULL in case of + * ERRNOMEM or invalid parameters used for @ref ethash_compute_cache_nodes() + */ + ethash_light_t ethash_light_new_internal(uint64_t cache_size, ethash_h256_t const *seed); + + /** + * Calculate the light client data. Internal version. + * + * @param light The light client handler + * @param full_size The size of the full data in bytes. + * @param header_hash The header hash to pack into the mix + * @param nonce The nonce to pack into the mix + * @return The resulting hash. + */ + ethash_return_value_t ethash_light_compute_internal( + ethash_light_t light, + uint64_t full_size, + ethash_h256_t const header_hash, + uint64_t nonce); + + struct ethash_full + { + FILE *file; + uint64_t file_size; + node *data; + }; + + /** + * Allocate and initialize a new ethash_full handler. Internal version. + * + * @param dirname The directory in which to put the DAG file. + * @param seedhash The seed hash of the block. Used in the DAG file naming. + * @param full_size The size of the full data in bytes. + * @param cache A cache object to use that was allocated with @ref ethash_cache_new(). + * Iff this function succeeds the ethash_full_t will take memory + * memory ownership of the cache and free it at deletion. If + * not then the user still has to handle freeing of the cache himself. + * @param callback A callback function with signature of @ref ethash_callback_t + * It accepts an unsigned with which a progress of DAG calculation + * can be displayed. If all goes well the callback should return 0. + * If a non-zero value is returned then DAG generation will stop. + * @return Newly allocated ethash_full handler or NULL in case of + * ERRNOMEM or invalid parameters used for @ref ethash_compute_full_data() + */ + ethash_full_t ethash_full_new_internal( + char const *dirname, + ethash_h256_t const seed_hash, + uint64_t full_size, + ethash_light_t const light, + ethash_callback_t callback); + + void ethash_calculate_dag_item( + node *const ret, + uint32_t node_index, + ethash_light_t const cache); + + void ethash_quick_hash( + ethash_h256_t *return_hash, + ethash_h256_t const *header_hash, + const uint64_t nonce, + ethash_h256_t const *mix_hash); + + uint64_t ethash_get_datasize(uint64_t const block_number, uint64_t const fork_block); + uint64_t ethash_get_cachesize(uint64_t const block_number, uint64_t const fork_block); + static uint64_t etchash_calc_epoch(uint64_t const block_number, uint64_t const fork_block); + + /** + * Compute the memory data for a full node's memory + * + * @param mem A pointer to an ethash full's memory + * @param full_size The size of the full data in bytes + * @param cache A cache object to use in the calculation + * @param callback The callback function. Check @ref ethash_full_new() for details. + * @return true if all went fine and false for invalid parameters + */ + bool ethash_compute_full_data( + void *mem, + uint64_t full_size, + ethash_light_t const light, + ethash_callback_t callback); #ifdef __cplusplus }