Merge pull request #1 from psychocrypt/topic-restructure11

refactor xmr-stak
This commit is contained in:
psychocrypt
2017-10-01 00:36:33 +02:00
committed by GitHub
143 changed files with 9758 additions and 1435 deletions
+6 -7
View File
@@ -5,7 +5,7 @@ image: Visual Studio 2017
platform: x64
# clone directory
clone_folder: c:\xmr-stak-cpu
clone_folder: c:\xmr-stak
install:
- mkdir c:\xmr-stak-dep
@@ -14,15 +14,14 @@ install:
build_script:
- call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsMSBuildCmd.bat"
- cd c:\xmr-stak-cpu
- cd c:\xmr-stak
- mkdir build
- cd build
- set CMAKE_PREFIX_PATH=C:\xmr-stak-dep\hwloc;C:\xmr-stak-dep\libmicrohttpd;C:\xmr-stak-dep\openssl;
- cmake -G "Visual Studio 15 2017 Win64" -T v141,host=x64 ..
- msbuild xmr-stak-cpu.sln /p:Configuration=Release
- cmake -G "Visual Studio 15 2017 Win64" -T v140,host=x64 -DCUDA_ENABLE=OFF -DOpenCL_ENABLE=OFF ..
- cmake --build . --config Release --target install
test_script:
- cd c:\xmr-stak-cpu\build\bin\Release
- cd c:\xmr-stak\build\bin\Release
- dir
- copy ..\..\..\config.txt .
# - xmr-stak-cpu.exe
# - xmr-stak.exe
+37 -5
View File
@@ -6,6 +6,11 @@ sudo: false
language: cpp
cache:
apt: true
directories:
- $HOME/.cache/cuda
addons:
apt:
packages: &default_packages
@@ -14,6 +19,10 @@ addons:
- libssl-dev
- libhwloc-dev
env:
global:
- CUDA_ROOT: $HOME/.cache/cuda
matrix:
include:
- os: linux
@@ -29,6 +38,7 @@ matrix:
env:
- CMAKE_CXX_COMPILER=g++-5
- CMAKE_C_COMPILER=gcc-5
- XMRSTAK_CMAKE_FLAGS="-DCUDA_ARCH=30 -DOpenCL_ENABLE=OFF"
- os: linux
compiler: gcc
@@ -43,6 +53,7 @@ matrix:
env:
- CMAKE_CXX_COMPILER=g++-6
- CMAKE_C_COMPILER=gcc-6
- XMRSTAK_CMAKE_FLAGS="-DCUDA_ENABLE=OFF -DOpenCL_ENABLE=OFF"
- os: linux
compiler: gcc
@@ -57,19 +68,40 @@ matrix:
env:
- CMAKE_CXX_COMPILER=g++-7
- CMAKE_C_COMPILER=gcc-7
- XMRSTAK_CMAKE_FLAGS="-DCUDA_ENABLE=OFF -DOpenCL_ENABLE=OFF"
- os: osx
compiler: gcc
env:
- XMRSTAK_CMAKE_FLAGS="-DCUDA_ENABLE=OFF -DOpenCL_ENABLE=OFF"
before_install:
- if [ $TRAVIS_OS_NAME = osx ]; then brew tap homebrew/science; fi
- export PATH=$CUDA_ROOT/bin:$PATH
install:
# CUDA
- if [ $TRAVIS_OS_NAME != osx ]; then
NVCC_FOUND=$(which nvcc >/dev/null && { echo 0; } || { echo 1; });
if [ $NVCC_FOUND -ne 0 ]; then
mkdir -p $CUDA_ROOT &&
cd $CUDA_ROOT &&
travis_retry wget https://developer.nvidia.com/compute/cuda/8.0/prod/local_installers/cuda_8.0.44_linux-run &&
ls -la &&
chmod u+x *-run &&
./cuda_8.0.44_linux-run --silent --toolkit --toolkitpath=$CUDA_ROOT &&
rm -rf ./cuda_8.0.44_linux-run $CUDA_ROOT/{samples,jre,doc,share} &&
cd -;
fi
fi;
script:
- if [ $TRAVIS_OS_NAME = osx ]; then
brew install hwloc;
cmake -DMICROHTTPD_ENABLE=OFF -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl .;
else
cmake -D CMAKE_C_COMPILER=${CMAKE_C_COMPILER} -D CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} .;
cmake -DMICROHTTPD_ENABLE=OFF -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl ${XMRSTAK_CMAKE_FLAGS} .;
else
cmake -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} ${XMRSTAK_CMAKE_FLAGS} .;
fi;
- make VERBOSE=1
- ./bin/xmr-stak-cpu -c ./config.txt
- make VERBOSE=1 install
- ./bin/xmr-stak --help
+257 -21
View File
@@ -11,6 +11,8 @@ if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}" CACHE PATH "install prefix" FORCE)
endif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
# help to find cuda on systems with a software module system
list(APPEND CMAKE_PREFIX_PATH "$ENV{CUDA_ROOT}")
# allow user to extent CMAKE_PREFIX_PATH via environment variable
list(APPEND CMAKE_PREFIX_PATH "$ENV{CMAKE_PREFIX_PATH}")
@@ -37,13 +39,160 @@ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${BUILD_TYPE}")
# option to add static libgcc and libstdc++
option(CMAKE_LINK_STATIC "link as much as possible libraries static" OFF)
################################################################################
# Find CUDA
################################################################################
#option(CUDA_USE_STATIC_CUDA_RUNTIME "Use the static version of the CUDA runtime library if available" OFF)
#set(CUDA_USE_STATIC_CUDA_RUNTIME OFF CACHE BOOL "Use the static version of the CUDA runtime library if available" FORCE)
option(CUDA_ENABLE "Enable or disable CUDA support (NVIDIA backend)" ON)
if(CUDA_ENABLE)
find_package(CUDA 7.5 QUIET)
if(CUDA_FOUND)
option(XMR-STAK_LARGEGRID "Support large CUDA block count > 128" ON)
if(XMR-STAK_LARGEGRID)
add_definitions("-DXMR_STAK_LARGEGRID=${XMR-STAK_LARGEGRID}")
endif()
set(DEVICE_COMPILER "nvcc")
set(CUDA_COMPILER "${DEVICE_COMPILER}" CACHE STRING "Select the device compiler")
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
list(APPEND DEVICE_COMPILER "clang")
endif()
set_property(CACHE CUDA_COMPILER PROPERTY STRINGS "${DEVICE_COMPILER}")
set(XMR-STAK_THREADS 0 CACHE STRING "Set maximum number of threads (for compile time optimization)")
if(NOT XMR-STAK_THREADS EQUAL 0)
message(STATUS "xmr-stak-nvidia: set max threads per block to ${XMR-STAK_THREADS}")
add_definitions("-DXMR_STAK_THREADS=${XMR-STAK_THREADS}")
endif()
set(CUDA_ARCH "20;30;35;37;50;52;60;61;62" CACHE STRING "Set GPU architecture (semicolon separated list, e.g. '-DCUDA_ARCH=20;35;60')")
# validate architectures (only numbers are allowed)
foreach(CUDA_ARCH_ELEM ${CUDA_ARCH})
string(REGEX MATCH "^[0-9]+$" IS_NUMBER ${CUDA_ARCH})
if(NOT IS_NUMBER)
message(FATAL_ERROR "Defined compute architecture '${CUDA_ARCH_ELEM}' in "
"'${CUDA_ARCH}' is not an integral number, use e.g. '30' (for compute architecture 3.0).")
endif()
unset(IS_NUMBER)
if(${CUDA_ARCH_ELEM} LESS 20)
message(FATAL_ERROR "Unsupported CUDA architecture '${CUDA_ARCH_ELEM}' specified. "
"Use '20' (for compute architecture 2.0) or higher.")
endif()
endforeach()
option(CUDA_SHOW_REGISTER "Show registers used for each kernel and compute architecture" OFF)
option(CUDA_KEEP_FILES "Keep all intermediate files that are generated during internal compilation steps" OFF)
if("${CUDA_COMPILER}" STREQUAL "clang")
set(CLANG_BUILD_FLAGS "-O3 -x cuda --cuda-path=${CUDA_TOOLKIT_ROOT_DIR}")
# activation usage of FMA
set(CLANG_BUILD_FLAGS "${CLANG_BUILD_FLAGS} -ffp-contract=fast")
if(CUDA_SHOW_REGISTER)
set(CLANG_BUILD_FLAGS "${CLANG_BUILD_FLAGS} -Xcuda-ptxas -v")
endif(CUDA_SHOW_REGISTER)
if(CUDA_KEEP_FILES)
set(CLANG_BUILD_FLAGS "${CLANG_BUILD_FLAGS} -save-temps=${PROJECT_BINARY_DIR}")
endif(CUDA_KEEP_FILES)
foreach(CUDA_ARCH_ELEM ${CUDA_ARCH})
# set flags to create device code for the given architectures
set(CLANG_BUILD_FLAGS "${CLANG_BUILD_FLAGS} --cuda-gpu-arch=sm_${CUDA_ARCH_ELEM}")
endforeach()
elseif("${CUDA_COMPILER}" STREQUAL "nvcc")
# add c++11 for cuda
if(NOT "${CMAKE_CXX_FLAGS}" MATCHES "-std=c\\+\\+11")
set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -std=c++11")
endif()
# avoid that nvcc in CUDA < 8 tries to use libc `memcpy` within the kernel
if(CUDA_VERSION VERSION_LESS 8.0)
add_definitions(-D_FORCE_INLINES)
endif()
foreach(CUDA_ARCH_ELEM ${CUDA_ARCH})
# set flags to create device code for the given architecture
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS}
"--generate-code arch=compute_${CUDA_ARCH_ELEM},code=sm_${CUDA_ARCH_ELEM} --generate-code arch=compute_${CUDA_ARCH_ELEM},code=compute_${CUDA_ARCH_ELEM}")
endforeach()
# give each thread an independent default stream
set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} --default-stream per-thread")
option(CUDA_SHOW_CODELINES "Show kernel lines in cuda-gdb and cuda-memcheck" OFF)
if(CUDA_SHOW_CODELINES)
set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS}" --source-in-ptx -lineinfo)
set(CUDA_KEEP_FILES ON CACHE BOOL "activate keep files" FORCE)
endif(CUDA_SHOW_CODELINES)
if(CUDA_SHOW_REGISTER)
set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS}" -Xptxas=-v)
endif(CUDA_SHOW_REGISTER)
if(CUDA_KEEP_FILES)
set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS}" --keep --keep-dir "${PROJECT_BINARY_DIR}")
endif(CUDA_KEEP_FILES)
else()
message(FATAL_ERROR "selected CUDA compiler '${CUDA_COMPILER}' is not supported")
endif()
else()
message(FATAL_ERROR "CUDA NOT found: use `-DCUDA_ENABLE=OFF` to build without NVIDIA GPU support")
endif()
else()
add_definitions("-DCONF_NO_CUDA")
endif()
# help to find AMD app SDK on systems with a software module system
list(APPEND CMAKE_PREFIX_PATH "$ENV{AMDAPPSDKROOT}")
# allow user to extent CMAKE_PREFIX_PATH via environment variable
list(APPEND CMAKE_PREFIX_PATH "$ENV{CMAKE_PREFIX_PATH}")
###############################################################################
# Find OpenCL
###############################################################################
option(OpenCL_ENABLE "Enable or disable OpenCL spport (AMD GPU support)" ON)
if(OpenCL_ENABLE)
find_package(OpenCL QUIET)
if(OpenCL_FOUND)
include_directories(SYSTEM ${OpenCL_INCLUDE_DIRS})
#set(LIBS ${LIBS} ${OpenCL_LIBRARY})
link_directories(${OpenCL_LIBRARY})
else()
message(FATAL_ERROR "OpenCL NOT found: use `-DOpenCL_ENABLE=OFF` to build without OpenCL support for AMD gpu's")
endif()
else()
add_definitions("-DCONF_NO_OPENCL")
endif()
###############################################################################
# CPU backend
###############################################################################
option(CPU_ENABLE "Enable or disable CPU support" ON)
if(NOT CPU_ENABLE)
add_definitions("-DCONF_NO_CPU")
endif()
################################################################################
# Find PThreads
################################################################################
find_package(Threads REQUIRED)
set(LIBS ${LIBS} ${CMAKE_THREAD_LIBS_INIT})
if(NOT WIN32)
find_package(Threads REQUIRED)
set(LIBS ${LIBS} ${CMAKE_THREAD_LIBS_INIT})
endif()
################################################################################
# Find microhttpd
################################################################################
@@ -111,7 +260,7 @@ if(HWLOC_ENABLE)
/usr/local
/usr
ENV "PROGRAMFILES(X86)"
ENV "HWLOC_ROOT"
ENV "MICROHTTPD_ROOT"
PATH_SUFFIXES
include)
@@ -146,10 +295,18 @@ endif()
# Compile & Link
################################################################################
# activate sse2 and aes-ni
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
include_directories(BEFORE .)
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
# remove warnings that f_open() is not save and f_open_s should be used
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
# disable min define to allow usage of std::min
add_definitions(-DNOMINMAX)
else()
# activate sse2 and aes-ni
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2 -maes")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse2 -maes")
endif()
# activate static libgcc and libstdc++ linking
@@ -160,8 +317,8 @@ if(CMAKE_LINK_STATIC)
set(LIBS "-static-libgcc -static-libstdc++ ${LIBS}")
endif()
file(GLOB SRCFILES_CPP "*.cpp" "crypto/*.cpp")
file(GLOB SRCFILES_C "crypto/*.c")
# compile C files
file(GLOB SRCFILES_C "xmrstak/backend/cpu/crypto/*.c")
add_library(xmr-stak-c
STATIC
@@ -170,29 +327,108 @@ add_library(xmr-stak-c
set_property(TARGET xmr-stak-c PROPERTY C_STANDARD 99)
target_link_libraries(xmr-stak-c ${LIBS})
add_executable(xmr-stak-cpu
# compile generic backend files
file(GLOB BACKEND_CPP
"xmrstak/*.cpp"
"xmrstak/backend/cpu/*.cpp"
"xmrstak/backend/*.cpp"
"xmrstak/backend/cpu/crypto/*.cpp"
"xmrstak/http/*.cpp"
"xmrstak/misc/*.cpp"
"xmrstak/net/*.cpp")
add_library(xmr-stak-backend
STATIC
${BACKEND_CPP}
)
target_link_libraries(xmr-stak-backend xmr-stak-c ${CMAKE_DL_LIBS})
# compile CUDA backend
if(CUDA_FOUND)
file(GLOB CUDASRCFILES
"xmrstak/backend/nvidia/nvcc_code/*.cu"
"xmrstak/backend/nvidia/*.cpp")
if("${CUDA_COMPILER}" STREQUAL "clang")
# build device code with clang
add_library(
xmrstak_cuda_backend
SHARED
${CUDASRCFILES}
)
set_target_properties(xmrstak_cuda_backend PROPERTIES COMPILE_FLAGS ${CLANG_BUILD_FLAGS})
set_target_properties(xmrstak_cuda_backend PROPERTIES LINKER_LANGUAGE CXX)
set_source_files_properties(${CUDASRCFILES} PROPERTIES LANGUAGE CXX)
else()
# build device code with nvcc
cuda_add_library(
xmrstak_cuda_backend
SHARED
${CUDASRCFILES}
)
endif()
target_link_libraries(xmrstak_cuda_backend ${CUDA_LIBRARIES})
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
target_link_libraries(xmrstak_cuda_backend xmr-stak-backend)
endif()
endif()
# compile AMD backend
if(OpenCL_FOUND)
file(GLOB OPENCLSRCFILES
"xmrstak/backend/amd/amd_gpu/*.cpp"
"xmrstak/backend/amd/*.cpp")
add_library(xmrstak_opencl_backend
SHARED
${OPENCLSRCFILES}
)
target_link_libraries(xmrstak_opencl_backend ${OpenCL_LIBRARY} )
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
target_link_libraries(xmrstak_opencl_backend xmr-stak-backend)
endif()
endif()
# compile final binary
file(GLOB SRCFILES_CPP "xmrstak/cli/*.cpp")
set_source_files_properties(${SRCFILES_CPP} PROPERTIES LANGUAGE CXX)
add_executable(xmr-stak
${SRCFILES_CPP}
)
set(EXECUTABLE_OUTPUT_PATH "bin")
target_link_libraries(xmr-stak-cpu ${LIBS} xmr-stak-c)
set(LIBRARY_OUTPUT_PATH "bin")
target_link_libraries(xmr-stak ${LIBS} xmr-stak-c xmr-stak-backend)
################################################################################
# Install
################################################################################
# do not install the binary if the project and install are equal
if( NOT "${CMAKE_INSTALL_PREFIX}" STREQUAL "${PROJECT_BINARY_DIR}" )
install(TARGETS xmr-stak-cpu
install(TARGETS xmr-stak
RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
if(CUDA_FOUND)
if(WIN32)
install(TARGETS xmrstak_cuda_backend
RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
else()
install(TARGETS xmrstak_cuda_backend
LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
endif()
endif()
if(OpenCL_FOUND)
if(WIN32)
install(TARGETS xmrstak_opencl_backend
RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
else()
install(TARGETS xmrstak_opencl_backend
LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
endif()
endif()
else()
# this rule is used if the install prefix is the build directory
install(CODE "MESSAGE(\"xmr-stak installed to folder 'bin'\")")
endif()
# avoid overwrite of user defined settings
# install `config.txt`if file not exists in `${CMAKE_INSTALL_PREFIX}/bin`
install(CODE " \
if(NOT EXISTS ${CMAKE_INSTALL_PREFIX}/bin/config.txt)\n \
file(INSTALL ${CMAKE_CURRENT_SOURCE_DIR}/config.txt \
DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)\n \
endif()"
)
+201
View File
@@ -0,0 +1,201 @@
# XMR-Stak-CPU - Monero mining software
XMR-Stak is a universal Stratum pool miner. This is the CPU-mining version; there is also an [AMD GPU version](https://github.com/fireice-uk/xmr-stak-amd) and an [NVIDA GPU version](https://github.com/fireice-uk/xmr-stak-nvidia)
## HTML reports
<img src="https://gist.githubusercontent.com/fireice-uk/2da301131ac01695ff79539a27b81d68/raw/4c09cdeee86f94df2e9dd86b927e64aded6184f5/xmr-stak-cpu-hashrate.png" width="260"> <img src="https://gist.githubusercontent.com/fireice-uk/2da301131ac01695ff79539a27b81d68/raw/4c09cdeee86f94df2e9dd86b927e64aded6184f5/xmr-stak-cpu-results.png" width="260"> <img src="https://gist.githubusercontent.com/fireice-uk/2da301131ac01695ff79539a27b81d68/raw/4c09cdeee86f94df2e9dd86b927e64aded6184f5/xmr-stak-cpu-connection.png" width="260">
## HTML and JSON API report configuraton
To configure the reports shown above you need to edit the httpd_port variable. Then enable wifi on your phone and navigate to [miner ip address]:[httpd_port] in your phone browser. If you want to use the data in scripts, you can get the JSON version of the data at url [miner ip address]:[httpd_port]/api.json
## Usage on Windows
1) Edit the config.txt file to enter your pool login and password.
2) Double click the exe file.
XMR-Stak should compile on any C++11 compliant compiler.
```
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
sha1sum
d34a0ba0dd7b3b1f900a7e02772e197e974b4a73 libeay32.dll
2ee9966a0fc163da58408d91be36b84fa287c10b ssleay32.dll
e4d8a974e58985214de163df0c1ed0f54250d7ee xmr-stak-cpu.exe
ae0153ff98df82022b2c392d6a17c5f3614f6a50 xmr-stak-cpu-notls.exe
sha3sum
05003137a87313c81d6c348c9b96411c95d48dc22c35f36c39129747 libeay32.dll
133c065d9ef2c93396382e2ba5d8c3ca8c6a57c6beb0159cb9a4b6c5 ssleay32.dll
7bfc30b06524dc9139a3157e2661d2a6f5720738dde8e490f05cc8e2 xmr-stak-cpu.exe
005fb81fc3711a97b2ce65bad0ca97318d878dc793a8cba99c7d1f6f xmr-stak-cpu-notls.exe
date
Wed 19 Jul 21:18:58 BST 2017
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
iQEcBAEBCAAGBQJZb77XAAoJEPsk95p+1Bw0GU4H/26sBwJzYSeWoLwo0LdmOPk3
19n+svFYnz6NlxAjs+fvuTK992ilLMy2pa4PHKhot2oyZIgt2rRaFsvRADcHVraG
nsIh4Oq31T9epZI0WxIH5FJlDx30fdGkpMTu9xt6ta2JXsmkDiCoZxmETuljB7Rw
xvnKeHiuTccp73C6Nd7dkuiemsOw0FZA7XXS/Kmwqm7n8BtCztY70R6SVN7QFbCz
C49s0A9cT4UbAUPuu8KvxFozmJHA/wDBYHgkq95Y6n/q116+Sc9BpdF8j+qK4YzZ
uM+B10XY0g7Qv376UoJRYKokpVaBxF08nD+JXLdL+zfQvnEfKgrhTnjaTkWFfEY=
=jpgE
-----END PGP SIGNATURE-----
```
## Compile guides
- [Free BSD](FREEBSDCOMPILE.md)
- [Linux](LINUXCOMPILE.md)
- [Windows](WINCOMPILE.md)
#### CPU mining performance
Performance is nearly identical to the closed source paid miners. Here are some numbers:
* **I7-2600K** - 266 H/s
* **I7-6700** - 276 H/s (with a separate GPU miner)
* **Dual X5650** - 466 H/s (depends on NUMA)
* **Dual E5640** - 365 H/s (same as above)
## Default dev donation
By default the miner will donate 2% of the hashpower (2 minute in 100 minutes) to my pool. If you want to change that, edit **xmrstak/donate-level.hpp** before you build the binaries.
If you want to donate directly to support further development, here is my wallet
fireice-uk:
```
4581HhZkQHgZrZjKeCfCJxZff9E3xCgHGF25zABZz7oR71TnbbgiS7sK9jveE6Dx6uMs2LwszDuvQJgRZQotdpHt1fTdDhk
```
psychocrypt:
```
43NoJVEXo21hGZ6tDG6Z3g4qimiGdJPE6GRxAmiWwm26gwr62Lqo7zRiCJFSBmbkwTGNuuES9ES5TgaVHceuYc4Y75txCTU
```
## Common Issues
**SeLockMemoryPrivilege failed**
Please see [config.txt](config.txt) under section **LARGE PAGE SUPPORT**
For Windows 7 pro, or Windows 8 and above see [this article](https://msdn.microsoft.com/en-gb/library/ms190730.aspx) (make sure to reboot afterwards!).
For Windows 7 Home :
1) Download and install [Windows Server 2003 Resource Kit Tools](https://www.microsoft.com/en-us/download/details.aspx?id=17657). Ignore incompatiablity warning during installation.
2) In cmd or power shell: `ntrights -u %USERNAME% +r SeLockMemoryPrivilege` (where %USERNAME% is the user that will be running the program. This command needs to be run as admin)
3) Reboot.
Reference: http://rybkaforum.net/cgi-bin/rybkaforum/topic_show.pl?pid=259791#pid259791
*Warning: do not download ntrights.exe from any other site other then the offical Microsoft download page.*
**VirtualAlloc failed**
If you set up the user rights properly (see above), and your system has 4-8GB of RAM (50%+ use), there is a significant chance that there simply won't be a large enough chunk of contiguous memory because Windows is fairly bad at mitigating memory fragmentation.
If that happens, disable all auto-staring applications and run the miner after a reboot.
**msvcp140.dll and vcruntime140.dll not available errors**
Download and install this [runtime package](https://go.microsoft.com/fwlink/?LinkId=746572) from Microsoft. *Warning: Do NOT use "missing dll" sites - dll's are exe files with another name, and it is a fairly safe bet that any dll on a shady site like that will be trojaned. Please download offical runtimes from Microsoft above.*
**Error: MEMORY ALLOC FAILED: mmap failed**
From [config.txt](config.txt):
On Linux you will need to configure large page support `sudo sysctl -w vm.nr_hugepages=128` and increase your
ulimit -l. To do this you need to add following lines to /etc/security/limits.conf:
* soft memlock 262144
* hard memlock 262144
Save file. You WILL need to log out and log back in for these settings to take affect on your user (no need to reboot, just relogin in your session).
You can also do it Windows-style and simply run-as-root, but this is NOT recommended for security reasons.
**Illegal instruction (core dumped)**
This typically means you are trying to run it on a CPU that does not have [AES](https://en.wikipedia.org/wiki/AES_instruction_set). This only happens on older version of miner, new version gives better error message (but still wont' work since your CPU doesn't support the required instructions).
## Advanced Compile Options
The build system is CMake, if you are not familiar with CMake you can learn more [here](https://cmake.org/runningcmake/).
### Short Description
There are two easy ways to set variables for `cmake` to configure *xmr-stak-cpu*
- use the ncurses GUI
- `ccmake .`
- edit your options
- end the GUI by pressing the key `c`(create) and than `g`(generate)
- set Options on the command line
- enable a option: `cmake . -DNAME_OF_THE_OPTION=ON`
- disable a option `cmake . -DNAME_OF_THE_OPTION=OFF`
- set a value `cmake . -DNAME_OF_THE_OPTION=value`
After the configuration you need to call
`make install` for slow sequential build
or
`make -j install` for faster parallel build
and install.
### xmr-stak-cpu Compile Options
- `CMAKE_INSTALL_PREFIX` install miner to the home folder
- `cmake . -DCMAKE_INSTALL_PREFIX=$HOME/xmr-stak-cpu`
- you can find the binary and the `config.txt` file after `make install` in `$HOME/xmr-stak-cpu/bin`
- `CMAKE_LINK_STATIC` link libgcc and libstdc++ libraries static (default OFF)
- disable with `cmake . -DCMAKE_LINK_STATIC=ON`
-`CMAKE_BUILD_TYPE` set the build type
- valid options: `Release` or `Debug`
- you should always keep `Release` for your productive miners
- `MICROHTTPD_ENABLE` allow to disable/enable the dependency *microhttpd*
- by default enabled
- there is no *http* interface available if option is disabled: `cmake . -DMICROHTTPD_ENABLE=OFF`
- `OpenSSL_ENABLE` allow to disable/enable the dependency *OpenSSL*
- by default enabled
- it is not possible to connect to a *https* secured pool if option is disabled: `cmake . -DOpenSSL_ENABLE=OFF`
- `HWLOC_ENABLE` allow to disable/enable the dependency *hwloc*
- by default enabled
- the config suggestion is not optimal if option is disabled: `cmake . -DHWLOC_ENABLE=OFF`
## PGP Key
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2
mQENBFhYUmUBCAC6493W5y1MMs38ApRbI11jWUqNdFm686XLkZWGDfYImzL6pEYk
RdWkyt9ziCyA6NUeWFQYniv/z10RxYKq8ulVVJaKb9qPGMU0ESfdxlFNJkU/pf28
sEVBagGvGw8uFxjQONnBJ7y7iNRWMN7qSRS636wN5ryTHNsmqI4ClXPHkXkDCDUX
QvhXZpG9RRM6jsE3jBGz/LJi3FyZLo/vB60OZBODJ2IA0wSR41RRiOq01OqDueva
9jPoAokNglJfn/CniQ+lqUEXj1vjAZ1D5Mn9fISzA/UPen5Z7Sipaa9aAtsDBOfP
K9iPKOsWa2uTafoyXgiwEVXCCeMMUjCGaoFBABEBAAG0ImZpcmVpY2VfdWsgPGZp
cmVpY2UueG1yQGdtYWlsLmNvbT6JATcEEwEIACEFAlhYUmUCGwMFCwkIBwIGFQgJ
CgsCBBYCAwECHgECF4AACgkQ+yT3mn7UHDTEcQf8CMhqaZ0IOBxeBnsq5HZr2X6z
E5bODp5cPs6ha1tjH3CWpk1AFeykNtXH7kPW9hcDt/e4UQtcHs+lu6YU59X7xLJQ
udOkpWdmooJMXRWS/zeeon4ivT9d69jNnwubh8EJOyw8xm/se6n48BcewfHekW/6
mVrbhLbF1dnuUGXzRN1WxsUZx3uJd2UvrkJhAtHtX92/qIVhT0+3PXV0bmpHURlK
YKhhm8dPLV9jPX8QVRHQXCOHSMqy/KoWEe6CnT0Isbkq3JtS3K4VBVeTX9gkySRc
IFxrNJdXsI9BxKv4O8yajP8DohpoGLMDKZKSO0yq0BRMgMh0cw6Lk22uyulGALkB
DQRYWFJlAQgAqikfViOmIccCZKVMZfNHjnigKtQqNrbJpYZCOImql4FqbZu9F7TD
9HIXA43SPcwziWlyazSy8Pa9nCpc6PuPPO1wxAaNIc5nt+w/x2EGGTIFGjRoubmP
3i5jZzOFYsvR2W3PgVa3/ujeYYJYo1oeVeuGmmJRejs0rp1mbvBSKw1Cq6C4cI0x
GTY1yXFGLIgdfYNMmiLsTy1Qwq8YStbFKeUYAMMG3128SAIaT3Eet911f5Jx4tC8
6kWUr6PX1rQ0LQJqyIsLq9U53XybUksRfJC9IEfgvgBxRBHSD8WfqEhHjhW1VsZG
dcYgr7A1PIneWsCEY+5VUnqTlt2HPaKweQARAQABiQEfBBgBCAAJBQJYWFJlAhsM
AAoJEPsk95p+1Bw0Pr8H/0vZ6U2zaih03jOHOvsrYxRfDXSmgudOp1VS45aHIREd
2nrJ+drleeFVyb14UQqO/6iX9GuDX2yBEHdCg2aljeP98AaMU//RiEtebE6CUWsL
HPVXHIkxwBCBe0YkJINHUQqLz/5f6qLsNUp1uTH2++zhdBWvg+gErTYbx8aFMFYH
0GoOtqE5rtlAh5MTvDZm+UcDwKJCxhrLaN3R3dDoyrDNRTgHQQuX5/opJBiUnVNK
d+vugnxzpMIJQP11yCZkz/KxV8zQ2QPMuZdAoh3znd/vGCJcp0rWphn4pqxA4vDp
c4hC0Yg9Dha1OoE5CJCqVL+ic4vAyB1urAwBlsd/wH8=
=B5I+
-----END PGP PUBLIC KEY BLOCK-----
```
+22 -148
View File
@@ -1,69 +1,34 @@
# XMR-Stak-CPU - Monero mining software
# XMR-Stak - Monero All-in-One Mining Software
XMR-Stak is a universal Stratum pool miner. This is the CPU-mining version; there is also an [AMD GPU version](https://github.com/fireice-uk/xmr-stak-amd) and an [NVIDA GPU version](https://github.com/fireice-uk/xmr-stak-nvidia)
XMR-Stak is a universal Stratum pool miner. This miner supports CPUs, AMD and NVIDIA gpus.
## HTML reports
<img src="https://gist.githubusercontent.com/fireice-uk/2da301131ac01695ff79539a27b81d68/raw/4c09cdeee86f94df2e9dd86b927e64aded6184f5/xmr-stak-cpu-hashrate.png" width="260"> <img src="https://gist.githubusercontent.com/fireice-uk/2da301131ac01695ff79539a27b81d68/raw/4c09cdeee86f94df2e9dd86b927e64aded6184f5/xmr-stak-cpu-results.png" width="260"> <img src="https://gist.githubusercontent.com/fireice-uk/2da301131ac01695ff79539a27b81d68/raw/4c09cdeee86f94df2e9dd86b927e64aded6184f5/xmr-stak-cpu-connection.png" width="260">
## HTML and JSON API report configuraton
## Content Overview
* [Features](#features)
* [Download](#download)
* [Usage](doc/usage.md)
* [HowTo Compile](doc/compile.md)
* [FAQ](doc/FAQ.md)
* [Developer Donation](#default-developer-donation)
* [PGP Key](#pgp-key)
To configure the reports shown above you need to edit the httpd_port variable. Then enable wifi on your phone and navigate to [miner ip address]:[httpd_port] in your phone browser. If you want to use the data in scripts, you can get the JSON version of the data at url [miner ip address]:[httpd_port]/api.json
## Features
## Usage on Windows
1) Edit the config.txt file to enter your pool login and password.
2) Double click the exe file.
- support all common backends (CPU/x86, AMD-GPU and NVIDIA-GPU)
- support all common OS (Linux, Windows and MacOS)
- easy to use
- guided start (no need to edit a config file for the first start)
- auto configuration for each backend
- open source software (GPLv3)
- TLS support
- HTML statistics
- JSON API for monitoring
XMR-Stak should compile on any C++11 compliant compiler.
```
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
## Download
sha1sum
d34a0ba0dd7b3b1f900a7e02772e197e974b4a73 libeay32.dll
2ee9966a0fc163da58408d91be36b84fa287c10b ssleay32.dll
e4d8a974e58985214de163df0c1ed0f54250d7ee xmr-stak-cpu.exe
ae0153ff98df82022b2c392d6a17c5f3614f6a50 xmr-stak-cpu-notls.exe
sha3sum
05003137a87313c81d6c348c9b96411c95d48dc22c35f36c39129747 libeay32.dll
133c065d9ef2c93396382e2ba5d8c3ca8c6a57c6beb0159cb9a4b6c5 ssleay32.dll
7bfc30b06524dc9139a3157e2661d2a6f5720738dde8e490f05cc8e2 xmr-stak-cpu.exe
005fb81fc3711a97b2ce65bad0ca97318d878dc793a8cba99c7d1f6f xmr-stak-cpu-notls.exe
date
Wed 19 Jul 21:18:58 BST 2017
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
iQEcBAEBCAAGBQJZb77XAAoJEPsk95p+1Bw0GU4H/26sBwJzYSeWoLwo0LdmOPk3
19n+svFYnz6NlxAjs+fvuTK992ilLMy2pa4PHKhot2oyZIgt2rRaFsvRADcHVraG
nsIh4Oq31T9epZI0WxIH5FJlDx30fdGkpMTu9xt6ta2JXsmkDiCoZxmETuljB7Rw
xvnKeHiuTccp73C6Nd7dkuiemsOw0FZA7XXS/Kmwqm7n8BtCztY70R6SVN7QFbCz
C49s0A9cT4UbAUPuu8KvxFozmJHA/wDBYHgkq95Y6n/q116+Sc9BpdF8j+qK4YzZ
uM+B10XY0g7Qv376UoJRYKokpVaBxF08nD+JXLdL+zfQvnEfKgrhTnjaTkWFfEY=
=jpgE
-----END PGP SIGNATURE-----
```
## Compile guides
- [Free BSD](FREEBSDCOMPILE.md)
- [Linux](LINUXCOMPILE.md)
- [Windows](WINCOMPILE.md)
#### CPU mining performance
Performance is nearly identical to the closed source paid miners. Here are some numbers:
* **I7-2600K** - 266 H/s
* **I7-6700** - 276 H/s (with a separate GPU miner)
* **Dual X5650** - 466 H/s (depends on NUMA)
* **Dual E5640** - 365 H/s (same as above)
## Default dev donation
By default the miner will donate 2% of the hashpower (2 minute in 100 minutes) to my pool. If you want to change that, edit **donate-level.h** before you build the binaries.
If you want to donate directly to support further development, here is my wallet
You can find the latest releases and precompiled binaries on GitHub under [Releases](https://github.com/xmr-stak/xmr-stak/releases).
fireice-uk:
```
@@ -75,97 +40,6 @@ psychocrypt:
43NoJVEXo21hGZ6tDG6Z3g4qimiGdJPE6GRxAmiWwm26gwr62Lqo7zRiCJFSBmbkwTGNuuES9ES5TgaVHceuYc4Y75txCTU
```
## Common Issues
**SeLockMemoryPrivilege failed**
Please see [config.txt](config.txt) under section **LARGE PAGE SUPPORT**
For Windows 7 pro, or Windows 8 and above see [this article](https://msdn.microsoft.com/en-gb/library/ms190730.aspx) (make sure to reboot afterwards!).
For Windows 7 Home :
1) Download and install [Windows Server 2003 Resource Kit Tools](https://www.microsoft.com/en-us/download/details.aspx?id=17657). Ignore incompatiablity warning during installation.
2) In cmd or power shell: `ntrights -u %USERNAME% +r SeLockMemoryPrivilege` (where %USERNAME% is the user that will be running the program. This command needs to be run as admin)
3) Reboot.
Reference: http://rybkaforum.net/cgi-bin/rybkaforum/topic_show.pl?pid=259791#pid259791
*Warning: do not download ntrights.exe from any other site other then the offical Microsoft download page.*
**VirtualAlloc failed**
If you set up the user rights properly (see above), and your system has 4-8GB of RAM (50%+ use), there is a significant chance that there simply won't be a large enough chunk of contiguous memory because Windows is fairly bad at mitigating memory fragmentation.
If that happens, disable all auto-staring applications and run the miner after a reboot.
**msvcp140.dll and vcruntime140.dll not available errors**
Download and install this [runtime package](https://go.microsoft.com/fwlink/?LinkId=746572) from Microsoft. *Warning: Do NOT use "missing dll" sites - dll's are exe files with another name, and it is a fairly safe bet that any dll on a shady site like that will be trojaned. Please download offical runtimes from Microsoft above.*
**Error: MEMORY ALLOC FAILED: mmap failed**
From [config.txt](config.txt):
On Linux you will need to configure large page support `sudo sysctl -w vm.nr_hugepages=128` and increase your
ulimit -l. To do this you need to add following lines to /etc/security/limits.conf:
* soft memlock 262144
* hard memlock 262144
Save file. You WILL need to log out and log back in for these settings to take affect on your user (no need to reboot, just relogin in your session).
You can also do it Windows-style and simply run-as-root, but this is NOT recommended for security reasons.
**Illegal instruction (core dumped)**
This typically means you are trying to run it on a CPU that does not have [AES](https://en.wikipedia.org/wiki/AES_instruction_set). This only happens on older version of miner, new version gives better error message (but still wont' work since your CPU doesn't support the required instructions).
## Advanced Compile Options
The build system is CMake, if you are not familiar with CMake you can learn more [here](https://cmake.org/runningcmake/).
### Short Description
There are two easy ways to set variables for `cmake` to configure *xmr-stak-cpu*
- use the ncurses GUI
- `ccmake .`
- edit your options
- end the GUI by pressing the key `c`(create) and than `g`(generate)
- set Options on the command line
- enable a option: `cmake . -DNAME_OF_THE_OPTION=ON`
- disable a option `cmake . -DNAME_OF_THE_OPTION=OFF`
- set a value `cmake . -DNAME_OF_THE_OPTION=value`
After the configuration you need to call
`make install` for slow sequential build
or
`make -j install` for faster parallel build
and install.
### xmr-stak-cpu Compile Options
- `CMAKE_INSTALL_PREFIX` install miner to the home folder
- `cmake . -DCMAKE_INSTALL_PREFIX=$HOME/xmr-stak-cpu`
- you can find the binary and the `config.txt` file after `make install` in `$HOME/xmr-stak-cpu/bin`
- `CMAKE_LINK_STATIC` link libgcc and libstdc++ libraries static (default OFF)
- disable with `cmake . -DCMAKE_LINK_STATIC=ON`
-`CMAKE_BUILD_TYPE` set the build type
- valid options: `Release` or `Debug`
- you should always keep `Release` for your productive miners
- `MICROHTTPD_ENABLE` allow to disable/enable the dependency *microhttpd*
- by default enabled
- there is no *http* interface available if option is disabled: `cmake . -DMICROHTTPD_ENABLE=OFF`
- `OpenSSL_ENABLE` allow to disable/enable the dependency *OpenSSL*
- by default enabled
- it is not possible to connect to a *https* secured pool if option is disabled: `cmake . -DOpenSSL_ENABLE=OFF`
- `HWLOC_ENABLE` allow to disable/enable the dependency *hwloc*
- by default enabled
- the config suggestion is not optimal if option is disabled: `cmake . -DHWLOC_ENABLE=OFF`
## PGP Key
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
-154
View File
@@ -1,154 +0,0 @@
#pragma once
#include "jconf.h"
#include "console.h"
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif // _WIN32
// Mask bits between h and l and return the value
// This enables us to put in values exactly like in the manual
// For example EBX[31:22] is get_masked(cpu_info[1], 31, 22)
inline int32_t get_masked(int32_t val, int32_t h, int32_t l)
{
val &= (0x7FFFFFFF >> (31-(h-l))) << l;
return val >> l;
}
class autoAdjust
{
public:
autoAdjust()
{
}
void printConfig()
{
printer::inst()->print_str("The configuration for 'cpu_threads_conf' in your config file is 'null'.\n");
printer::inst()->print_str("The miner evaluates your system and prints a suggestion for the section `cpu_threads_conf` to the terminal.\n");
printer::inst()->print_str("The values are not optimal, please try to tweak the values based on notes in config.txt.\n");
printer::inst()->print_str("Please copy & paste the block within the asterisks to your config.\n\n");
if(!detectL3Size() || L3KB_size < 1024 || L3KB_size > 102400)
{
if(L3KB_size < 1024 || L3KB_size > 102400)
printer::inst()->print_msg(L0, "Autoconf failed: L3 size sanity check failed - %u KB.", L3KB_size);
printer::inst()->print_msg(L0, "Autoconf failed: Printing config for a single thread. Please try to add new ones until the hashrate slows down.");
printer::inst()->print_str("\n**************** Copy&Paste BEGIN ****************\n\n");
printer::inst()->print_str("\"cpu_threads_conf\" :\n[\n");
printer::inst()->print_str(" { \"low_power_mode\" : false, \"no_prefetch\" : true, \"affine_to_cpu\" : false },\n");
printer::inst()->print_str("],\n\n**************** Copy&Paste END ****************\n");
return;
}
printer::inst()->print_msg(L0, "Autoconf L3 size detected at %u KB.", L3KB_size);
detectCPUConf();
printer::inst()->print_msg(L0, "Autoconf core count detected as %u on %s.", corecnt,
linux_layout ? "Linux" : "Windows");
printer::inst()->print_str("\n**************** Copy&Paste BEGIN ****************\n\n");
printer::inst()->print_str("\"cpu_threads_conf\" :\n[\n");
uint32_t aff_id = 0;
char strbuf[256];
for(uint32_t i=0; i < corecnt; i++)
{
bool double_mode;
if(L3KB_size <= 0)
break;
double_mode = L3KB_size / 2048 > (int32_t)(corecnt-i);
snprintf(strbuf, sizeof(strbuf), " { \"low_power_mode\" : %s, \"no_prefetch\" : true, \"affine_to_cpu\" : %u },\n",
double_mode ? "true" : "false", aff_id);
printer::inst()->print_str(strbuf);
if(!linux_layout || old_amd)
{
aff_id += 2;
if(aff_id >= corecnt)
aff_id = 1;
}
else
aff_id++;
if(double_mode)
L3KB_size -= 4096;
else
L3KB_size -= 2048;
}
printer::inst()->print_str("],\n\n**************** Copy&Paste END ****************\n");
}
private:
bool detectL3Size()
{
int32_t cpu_info[4];
char cpustr[13] = {0};
jconf::cpuid(0, 0, cpu_info);
memcpy(cpustr, &cpu_info[1], 4);
memcpy(cpustr+4, &cpu_info[3], 4);
memcpy(cpustr+8, &cpu_info[2], 4);
if(strcmp(cpustr, "GenuineIntel") == 0)
{
jconf::cpuid(4, 3, cpu_info);
if(get_masked(cpu_info[0], 7, 5) != 3)
{
printer::inst()->print_msg(L0, "Autoconf failed: Couln't find L3 cache page.");
return false;
}
L3KB_size = ((get_masked(cpu_info[1], 31, 22) + 1) * (get_masked(cpu_info[1], 21, 12) + 1) *
(get_masked(cpu_info[1], 11, 0) + 1) * (cpu_info[2] + 1)) / 1024;
return true;
}
else if(strcmp(cpustr, "AuthenticAMD") == 0)
{
jconf::cpuid(0x80000006, 0, cpu_info);
L3KB_size = get_masked(cpu_info[3], 31, 18) * 512;
jconf::cpuid(1, 0, cpu_info);
if(get_masked(cpu_info[0], 11, 8) < 0x17) //0x17h is Zen
old_amd = true;
return true;
}
else
{
printer::inst()->print_msg(L0, "Autoconf failed: Unknown CPU type: %s.", cpustr);
return false;
}
}
void detectCPUConf()
{
#ifdef _WIN32
SYSTEM_INFO info;
GetSystemInfo(&info);
corecnt = info.dwNumberOfProcessors;
linux_layout = false;
#else
corecnt = sysconf(_SC_NPROCESSORS_ONLN);
linux_layout = true;
#endif // _WIN32
}
int32_t L3KB_size = 0;
uint32_t corecnt;
bool old_amd = false;
bool linux_layout;
};
-225
View File
@@ -1,225 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with OpenSSL (or a modified version of that library), containing parts
* covered by the terms of OpenSSL License and SSLeay License, the licensors
* of this Program grant you additional permission to convey the resulting work.
*
*/
#include "executor.h"
#include "minethd.h"
#include "jconf.h"
#include "console.h"
#include "donate-level.h"
#ifndef CONF_NO_HWLOC
# include "autoAdjustHwloc.hpp"
#else
# include "autoAdjust.hpp"
#endif
#include "version.h"
#ifndef CONF_NO_HTTPD
# include "httpd.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#ifndef CONF_NO_TLS
#include <openssl/ssl.h>
#include <openssl/err.h>
#endif
//Do a press any key for the windows folk. *insert any key joke here*
#ifdef _WIN32
void win_exit()
{
printer::inst()->print_str("Press any key to exit.");
get_key();
return;
}
#define strcasecmp _stricmp
#else
void win_exit() { return; }
#endif // _WIN32
void do_benchmark();
int main(int argc, char *argv[])
{
#ifndef CONF_NO_TLS
SSL_library_init();
SSL_load_error_strings();
ERR_load_BIO_strings();
ERR_load_crypto_strings();
SSL_load_error_strings();
OpenSSL_add_all_digests();
#endif
srand(time(0));
const char* sFilename = "config.txt";
bool benchmark_mode = false;
if(argc >= 2)
{
if(strcmp(argv[1], "-h") == 0)
{
printer::inst()->print_msg(L0, "Usage %s [CONFIG FILE]", argv[0]);
win_exit();
return 0;
}
if(argc >= 3 && strcasecmp(argv[1], "-c") == 0)
{
sFilename = argv[2];
}
else if(argc >= 3 && strcasecmp(argv[1], "benchmark_mode") == 0)
{
sFilename = argv[2];
benchmark_mode = true;
}
else
sFilename = argv[1];
}
if(!jconf::inst()->parse_config(sFilename))
{
win_exit();
return 0;
}
if(jconf::inst()->NeedsAutoconf())
{
autoAdjust adjust;
adjust.printConfig();
win_exit();
return 0;
}
if (!minethd::self_test())
{
win_exit();
return 0;
}
if(benchmark_mode)
{
do_benchmark();
win_exit();
return 0;
}
#ifndef CONF_NO_HTTPD
if(jconf::inst()->GetHttpdPort() != 0)
{
if (!httpd::inst()->start_daemon())
{
win_exit();
return 0;
}
}
#endif
printer::inst()->print_str("-------------------------------------------------------------------\n");
printer::inst()->print_str( XMR_STAK_NAME" " XMR_STAK_VERSION " mining software, CPU Version.\n");
printer::inst()->print_str("Based on CPU mining code by wolf9466 (heavily optimized by fireice_uk).\n");
printer::inst()->print_str("Brought to you by fireice_uk and psychocrypt under GPLv3.\n\n");
char buffer[64];
snprintf(buffer, sizeof(buffer), "Configurable dev donation level is set to %.1f %%\n\n", fDevDonationLevel * 100.0);
printer::inst()->print_str(buffer);
printer::inst()->print_str("You can use following keys to display reports:\n");
printer::inst()->print_str("'h' - hashrate\n");
printer::inst()->print_str("'r' - results\n");
printer::inst()->print_str("'c' - connection\n");
printer::inst()->print_str("-------------------------------------------------------------------\n");
if(strlen(jconf::inst()->GetOutputFile()) != 0)
printer::inst()->open_logfile(jconf::inst()->GetOutputFile());
executor::inst()->ex_start(jconf::inst()->DaemonMode());
using namespace std::chrono;
uint64_t lastTime = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
int key;
while(true)
{
key = get_key();
switch(key)
{
case 'h':
executor::inst()->push_event(ex_event(EV_USR_HASHRATE));
break;
case 'r':
executor::inst()->push_event(ex_event(EV_USR_RESULTS));
break;
case 'c':
executor::inst()->push_event(ex_event(EV_USR_CONNSTAT));
break;
default:
break;
}
uint64_t currentTime = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
/* Hard guard to make sure we never get called more than twice per second */
if( currentTime - lastTime < 500)
std::this_thread::sleep_for(std::chrono::milliseconds(500 - (currentTime - lastTime)));
lastTime = currentTime;
}
return 0;
}
void do_benchmark()
{
using namespace std::chrono;
std::vector<minethd*>* pvThreads;
printer::inst()->print_msg(L0, "Running a 60 second benchmark...");
uint8_t work[76] = {0};
minethd::miner_work oWork = minethd::miner_work("", work, sizeof(work), 0, 0, false, 0);
pvThreads = minethd::thread_starter(oWork);
uint64_t iStartStamp = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
std::this_thread::sleep_for(std::chrono::seconds(60));
oWork = minethd::miner_work();
minethd::switch_work(oWork);
double fTotalHps = 0.0;
for (uint32_t i = 0; i < pvThreads->size(); i++)
{
double fHps = pvThreads->at(i)->iHashCount;
fHps /= (pvThreads->at(i)->iTimestamp - iStartStamp) / 1000.0;
printer::inst()->print_msg(L0, "Thread %u: %.1f H/S", i, fHps);
fTotalHps += fHps;
}
printer::inst()->print_msg(L0, "Total: %.1f H/S", fTotalHps);
}
+61
View File
@@ -0,0 +1,61 @@
# FAQ
## Content Overview
* [SeLockMemoryPrivilege failed](#selockmemoryprivilege-failed)
* [VirtualAlloc failed](#virtualalloc-failed)
* [Error msvcp140.dll and vcruntime140.dll not available](#error-msvcp140dll-and-vcruntime140dll-not-available)
* [Error: MEMORY ALLOC FAILED: mmap failed](#error-memory-alloc-failed-mmap-failed)
* [Illegal instruction (core dumped)](#illegal-instruction)
* [Virus Protection Alert](#virus-protection-alert)
## SeLockMemoryPrivilege failed
Please see [config.txt](config.txt) under section **LARGE PAGE SUPPORT**
For Windows 7 pro, or Windows 8 and above see [this article](https://msdn.microsoft.com/en-gb/library/ms190730.aspx) (make sure to reboot afterwards!).
For Windows 7 Home :
1) Download and install [Windows Server 2003 Resource Kit Tools](https://www.microsoft.com/en-us/download/details.aspx?id=17657). Ignore incompatiablity warning during installation.
2) In cmd or power shell: `ntrights -u %USERNAME% +r SeLockMemoryPrivilege` (where %USERNAME% is the user that will be running the program. This command needs to be run as admin)
3) Reboot.
Reference: http://rybkaforum.net/cgi-bin/rybkaforum/topic_show.pl?pid=259791#pid259791
*Warning: do not download ntrights.exe from any other site other then the offical Microsoft download page.*
## VirtualAlloc failed
If you set up the user rights properly (see above), and your system has 4-8GB of RAM (50%+ use), there is a significant chance that there simply won't be a large enough chunk of contiguous memory because Windows is fairly bad at mitigating memory fragmentation.
If that happens, disable all auto-staring applications and run the miner after a reboot.
## Error msvcp140.dll and vcruntime140.dll not available
Download and install this [runtime package](https://go.microsoft.com/fwlink/?LinkId=746572) from Microsoft. *Warning: Do NOT use "missing dll" sites - dll's are exe files with another name, and it is a fairly safe bet that any dll on a shady site like that will be trojaned. Please download offical runtimes from Microsoft above.*
## Error: MEMORY ALLOC FAILED: mmap failed
On Linux you will need to configure large page support `sudo sysctl -w vm.nr_hugepages=128` and increase your
ulimit -l. To do this you need to add following lines to /etc/security/limits.conf:
* soft memlock 262144
* hard memlock 262144
Save file. You WILL need to log out and log back in for these settings to take affect on your user (no need to reboot, just relogin in your session).
You can also do it Windows-style and simply run-as-root, but this is NOT recommended for security reasons.
## Illegal Instruction
This typically means you are trying to run it on a CPU that does not have [AES](https://en.wikipedia.org/wiki/AES_instruction_set). This only happens on older version of miner, new version gives better error message (but still wont' work since your CPU doesn't support the required instructions).
## Virus Protection Alert
Some Virus protection software flag the miner binary as *Male Ware*.
In this case the binary is moved to the quarantine area of the protection software.
This is a wrong alert and not avoid by use.
Add the binary to to protection software white list to solve this issue.s
+81
View File
@@ -0,0 +1,81 @@
# Compile xmr-stak
## Content Overview
* [Build System](#build-system)
* [Generic Build Options](#generic-build-options)
* [CPU Build Options](#cpu-build-options)
* [AMD Build Options](#amd-build-options)
* [NVIDIA Build Options](#nvidia-build-options)
* [Compile in Windows](compile_Windows.md)
* [Compile in Linux](compile_Linux.md)
* [Compile in FreeBSD](compile_FreeBSD.md)
## Build System
The build system is CMake, if you are not familiar with CMake you can learn more [here](https://cmake.org/runningcmake/).
By default the miner will be build with all dependencies. Each optional dependency can be disabled (this will reduce the miner features).
There are two easy ways to set variables for `cmake` to configure *xmr-stak*
- use the ncurses GUI
- `ccmake .`
- edit your options
- end the GUI by pressing the key `c`(create) and than `g`(generate)
- set Options on the command line
- enable a option: `cmake . -DNAME_OF_THE_OPTION=ON`
- disable a option `cmake . -DNAME_OF_THE_OPTION=OFF`
- set a value `cmake . -DNAME_OF_THE_OPTION=value`
After the configuration you need to compile the miner, follow the guide for your platform:
* [Compile in Windows](compile_Windows.md)
* [Compile in Linux](compile_Linux.md)
* [Compile in FreeBSD](compile_FreeBSD.md)
## Generic Build Options
- `CMAKE_INSTALL_PREFIX` install miner to the home folder
- `cmake . -DCMAKE_INSTALL_PREFIX=$HOME/xmr-stak-cpu`
- you can find the binary and the `config.txt` file after `make install` in `$HOME/xmr-stak-cpu/bin`
- `CMAKE_LINK_STATIC` link libgcc and libstdc++ libraries static (default OFF)
- disable with `cmake . -DCMAKE_LINK_STATIC=ON`
- `CMAKE_BUILD_TYPE` set the build type
- valid options: `Release` or `Debug`
- you should always keep `Release` for your productive miners
- `MICROHTTPD_ENABLE` allow to disable/enable the dependency *microhttpd*
- there is no *http* interface available if option is disabled: `cmake . -DMICROHTTPD_ENABLE=OFF`
- `OpenSSL_ENABLE` allow to disable/enable the dependency *OpenSSL*
- it is not possible to connect to a *https* secured pool if option is disabled: `cmake . -DOpenSSL_ENABLE=OFF`
## CPU Build Options
- `CPU_ENABLE` allow to disable/enable the CPU backend of the miner
- `HWLOC_ENABLE` allow to disable/enable the dependency *hwloc*
- the config suggestion is not optimal if option is disabled: `cmake . -DHWLOC_ENABLE=OFF`
- disabling can be reduce the miner performance
## AMD Build Options
- `OpenCL_ENABLE` allow to disable/enable the AMD backend of the miner
## NVIDIA Build Options
- `CUDA_ENABLE` allow to disable/enable the NVIDIA backend of the miner
- `CUDA_ARCH` build for a certain compute architecture
- this option needs a semicolon separated list
- `cmake . -DCUDA_ARCH=61` or `cmake . -DCUDA_ARCH=20;61`
- [list](https://developer.nvidia.com/cuda-gpus) with NVIDIA compute architectures
- by default the miner is created for all currently available compute architectures
- `CUDA_COMPILER` select the compiler for the device code
- valid options: `nvcc` or `clang` if clang 3.9+ is installed
```
# compile host and device code with clang
export CC=/usr/bin/clang
export CXX=/usr/bin/clang++
cmake . -DCUDA_COMPILER=clang
```
- `XMR-STAK_LARGEGRID` use `32` or `64` bit integer for on device indices
- default is enabled
- on old GPUs it can increase the hash rate if disabled: `cmake . -DXMR-STAK_LARGEGRID=OFF`
- if disabled it is not allowed to use more than `1000` threads on the device
- `XMR-STAK_THREADS` give the compiler information which value for `threads` is used at runtime
- default is `0` (compile time optimization)
- if the miner is compiled and used at runtime with the some value it can increase the hash rate: `cmake . -DXMR-STAK_THREADS=32`
+2 -4
View File
@@ -13,8 +13,6 @@ Type 'y' and hit enter to proceed with installing the packages.
git clone https://github.com/fireice-uk/xmr-stak-cpu.git
cd xmr-stak-cpu
cmake .
make
make install
Now you have the binary located at "bin/xmr-stak-cpu". Either move this file to your desired location or run "make install" to install it to your path.
You can edit the prebuilt [config.txt](config.txt) file found in the root of the repository or you can make your own. This file is required to run xmr-stak-cpu.
Now you have the binary located at "bin/xmr-stak" and the needed shared libraries.
+1 -5
View File
@@ -37,8 +37,7 @@
make install
```
- g++ version 5.1 or higher is required for full C++11 support. CMake release compile scripts, as well as CodeBlocks build environment for debug builds is included.
- g++ version 5.1 or higher is required for full C++11 support.
If you want to compile the binary without installing libraries / compiler or just compile binary for some other distribution, please check the [build_xmr-stak_docker.sh script](scripts/build_xmr-stak_docker/build_xmr-stak_docker.sh).
### To do a static build for a system without gcc 5.1+
@@ -47,6 +46,3 @@ If you want to compile the binary without installing libraries / compiler or jus
make install
```
Note - cmake caches variables, so if you want to do a dynamic build later you need to specify '-DCMAKE_LINK_STATIC=OFF'
+3 -5
View File
@@ -58,7 +58,7 @@
## Compile
- download and unzip `xmr-stak-cpu`
- download and unzip `xmr-stak
- open the command line terminal `cmd`
- `cd` to your unzipped source code directory
- execute the following commands (NOTE: path to VS2017 can be different)
@@ -67,9 +67,7 @@
set CMAKE_PREFIX_PATH=C:\xmr-stak-dep\hwloc;C:\xmr-stak-dep\libmicrohttpd;C:\xmr-stak-dep\openssl
mkdir build
cd build
cmake -G "Visual Studio 15 2017 Win64" -T v141,host=x64 ..
msbuild xmr-stak-cpu.sln /p:Configuration=Release
cmake -G "Visual Studio 15 2017 Win64" -T v140,host=x64 ..
cmake --build . --config Release --target install
cd bin\Release
copy ..\..\..\config.txt .
```
- customize your `config.txt` file by adding the pool, username and password
+67
View File
@@ -0,0 +1,67 @@
# Tuning Guide
## Content Overview
* [NVIDIA Backend](#nvidia-backend)
* [Choose Value for `threads` and `blocks`](#choose-value-for-threads-and-blocks)
* [Add more GPUs](#add-more-gpus)
* [AMD Backend](#amd-backend)
* [Choose `intensity` and `worksize`](#choose-intensity-and-worksize)
* [Add more GPUs](#add-more-gpus)
## NVIDIA Backend
By default the NVIDIA backend can be tuned in the config file `nvidia.txt`
### Choose Value for `threads` and `blocks`
The optimal parameter for the `threads` and `blocks` option in `config.txt` depend on your GPU.
For all GPU's with a compute capability `>=2.0` and `<6.0` there is a restriction of the amount of RAM that can be used for the mining algorithm.
The maximum RAM that can be used must be less than 2GB (e.g. GTX TITAN) or 1GB (e.g. GTX 750-TI).
The amount of RAM used for mining can be changed with `"threads" : T, "blocks : B"`.
- `T` = threads used per block
- `B` = CUDA blocks started (should be a multiple of the multiprocessors `M` on the GPU)
For the 2GB limit the equations must be full filled: `T * B * 2 <= 1900` and ` B mod M == 0`.
The value `1900` is used because there is a little data overhead for administration.
The GTX Titan X has 24 multiprocessors `M`, this means a valid and good starting configuration is `"threads" : 16, "blocks : 48"`
and full fill all restrictions `16 * 48 * 2 = 1536` and `48 mod 24 = 0`.
The memory limit for NVIDIA Pascal GPUs is `16` GiB if the newest CUDA driver is used.
### Add More GPUs
To add a new GPU you need to add a new config set to `gpu_threads_conf`.
`index` is the number of the gpu, the index order not follow the order from `nvidia-smi` or the order shown in windows.
```
"gpu_threads_conf" :
[
{ "index" : 0, "threads" : 17, "blocks" : 60, "bfactor" : 0, "bsleep" : 0, "affine_to_cpu" : false},
{ "index" : 1, "threads" : 17, "blocks" : 60, "bfactor" : 0, "bsleep" : 0, "affine_to_cpu" : false},
],
```
## AMD Backend
By default the NVIDIA backend can be tuned in the config file `nvidia.txt`
### Choose `intensity` and `worksize`
Intensity means the number of threads used to mine.
`worksize` is the number of threads working together to increase the miner performance.
In the most cases a `worksize` of `16` or `8` is optimal.
### Add More GPUs
To add a new GPU you need to add a new config set to `gpu_threads_conf` and increase `gpu_thread_num"` to the number of gpus (entries in `gpu_threads_conf`).
`index` is the number of the gpu.
```
"gpu_thread_num" : 2,
"gpu_threads_conf" :
[
{ "index" : 0, "intensity" : 1000, "worksize" : 8, "affine_to_cpu" : false },
{ "index" : 1, "intensity" : 1000, "worksize" : 8, "affine_to_cpu" : false },
],
```
+54
View File
@@ -0,0 +1,54 @@
# HowTo Use xmr-stak
## Content Overview
* [Configuration](#configuration)
* [Usage on Windows](#usage-on-windows)
* [Usage on Linux](#usage-on-linux)
* [Command Line Options](#command-line-options)
* [HTML and JSON API report configuraton](#xx)
## Configurations
Before you started the miner the first time there are no config files available.
Config files will be created at the first start.
The number of files depends on the available backends.
`config.txt` contains the common miner settings.
`amd.txt`, `cpu.txt` and `nvidia.txt` contains miner backend specific settings and can be used for further tuning ([Tuning Guide](tuning.md)).
## Usage on Windows
1) Double click the `xmr-stak.exe` file
2) Fill in the pool url, username and password
## Usage on Linux
1) Open a terminal within the folder with the binary
2) Start the miner with `./xmr-stak`
## Command Line Options
The miner allow to overwrite some of the settings via command line options.
```
Usage: xmr-stak [OPTION]...
-c, --config FILE common miner configuration file
-h, --help show this help
--noCPU disable the CPU miner backend
--cpu FILE CPU backend miner config file
--noAMD disable the AMD miner backend
--amd FILE AMD backend miner config file
The Following options temporary overwrites the config file settings:
-o, --url URL pool url and port, e.g. pool.usxmrpool.com:3333
-u, --user USERNAME pool user name or wallet address
-p, --pass PASSWD pool password, in the most cases x or empty ""
## HTML and JSON API report configuraton
To configure the reports shown on the [README](README.md) side you need to edit the httpd_port variable. Then enable wifi on your phone and navigate to [miner ip address]:[httpd_port] in your phone browser. If you want to use the data in scripts, you can get the JSON version of the data at url [miner ip address]:[httpd_port]/api.json
## Default Developer Donation
By default the miner will donate 2% of the hashpower (2 minute in 100 minutes) to my pool. If you want to change that, edit **xmrstak/donate-level.hpp** before you build the binaries.
If you want to donate directly to support further development, here is my wallet
```
-144
View File
@@ -1,144 +0,0 @@
#pragma once
#include <thread>
#include <atomic>
#include <mutex>
#include "crypto/cryptonight.h"
class telemetry
{
public:
telemetry(size_t iThd);
void push_perf_value(size_t iThd, uint64_t iHashCount, uint64_t iTimestamp);
double calc_telemetry_data(size_t iLastMilisec, size_t iThread);
private:
constexpr static size_t iBucketSize = 2 << 11; //Power of 2 to simplify calculations
constexpr static size_t iBucketMask = iBucketSize - 1;
uint32_t* iBucketTop;
uint64_t** ppHashCounts;
uint64_t** ppTimestamps;
};
class minethd
{
public:
struct miner_work
{
char sJobID[64];
uint8_t bWorkBlob[112];
uint32_t iWorkSize;
uint32_t iResumeCnt;
uint64_t iTarget;
bool bNiceHash;
bool bStall;
size_t iPoolId;
miner_work() : iWorkSize(0), bStall(true), iPoolId(0) { }
miner_work(const char* sJobID, const uint8_t* bWork, uint32_t iWorkSize, uint32_t iResumeCnt,
uint64_t iTarget, bool bNiceHash, size_t iPoolId) : iWorkSize(iWorkSize), iResumeCnt(iResumeCnt),
iTarget(iTarget), bNiceHash(bNiceHash), bStall(false), iPoolId(iPoolId)
{
assert(iWorkSize <= sizeof(bWorkBlob));
memcpy(this->sJobID, sJobID, sizeof(miner_work::sJobID));
memcpy(this->bWorkBlob, bWork, iWorkSize);
}
miner_work(miner_work const&) = delete;
miner_work& operator=(miner_work const& from)
{
assert(this != &from);
iWorkSize = from.iWorkSize;
iResumeCnt = from.iResumeCnt;
iTarget = from.iTarget;
bNiceHash = from.bNiceHash;
bStall = from.bStall;
iPoolId = from.iPoolId;
assert(iWorkSize <= sizeof(bWorkBlob));
memcpy(sJobID, from.sJobID, sizeof(sJobID));
memcpy(bWorkBlob, from.bWorkBlob, iWorkSize);
return *this;
}
miner_work(miner_work&& from) : iWorkSize(from.iWorkSize), iTarget(from.iTarget),
bStall(from.bStall), iPoolId(from.iPoolId)
{
assert(iWorkSize <= sizeof(bWorkBlob));
memcpy(sJobID, from.sJobID, sizeof(sJobID));
memcpy(bWorkBlob, from.bWorkBlob, iWorkSize);
}
miner_work& operator=(miner_work&& from)
{
assert(this != &from);
iWorkSize = from.iWorkSize;
iResumeCnt = from.iResumeCnt;
iTarget = from.iTarget;
bNiceHash = from.bNiceHash;
bStall = from.bStall;
iPoolId = from.iPoolId;
assert(iWorkSize <= sizeof(bWorkBlob));
memcpy(sJobID, from.sJobID, sizeof(sJobID));
memcpy(bWorkBlob, from.bWorkBlob, iWorkSize);
return *this;
}
};
static void switch_work(miner_work& pWork);
static std::vector<minethd*>* thread_starter(miner_work& pWork);
static bool self_test();
std::atomic<uint64_t> iHashCount;
std::atomic<uint64_t> iTimestamp;
private:
typedef void (*cn_hash_fun)(const void*, size_t, void*, cryptonight_ctx*);
typedef void (*cn_hash_fun_dbl)(const void*, size_t, void*, cryptonight_ctx* __restrict, cryptonight_ctx* __restrict);
minethd(miner_work& pWork, size_t iNo, bool double_work, bool no_prefetch, int64_t affinity);
// We use the top 10 bits of the nonce for thread and resume
// This allows us to resume up to 128 threads 4 times before
// we get nonce collisions
// Bottom 22 bits allow for an hour of work at 1000 H/s
inline uint32_t calc_start_nonce(uint32_t resume)
{ return (resume * iThreadCount + iThreadNo) << 22; }
// Limited version of the nonce calc above
inline uint32_t calc_nicehash_nonce(uint32_t start, uint32_t resume)
{ return start | (resume * iThreadCount + iThreadNo) << 18; }
static cn_hash_fun func_selector(bool bHaveAes, bool bNoPrefetch);
static cn_hash_fun_dbl func_dbl_selector(bool bHaveAes, bool bNoPrefetch);
void work_main();
void double_work_main();
void consume_work();
static std::atomic<uint64_t> iGlobalJobNo;
static std::atomic<uint64_t> iConsumeCnt;
static uint64_t iThreadCount;
uint64_t iJobNo;
static miner_work oGlobalWork;
miner_work oWork;
void pin_thd_affinity();
// Held by the creating context to prevent a race cond with oWorkThd = std::thread(...)
std::mutex work_thd_mtx;
std::thread oWorkThd;
uint8_t iThreadNo;
int64_t affinity;
bool bQuit;
bool bNoPrefetch;
};
-4
View File
@@ -1,4 +0,0 @@
#pragma once
#define XMR_STAK_NAME "xmr-stak-cpu"
#define XMR_STAK_VERSION "1.3.0-1.5.0-dev"
-167
View File
@@ -1,167 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="xmr-stak-cpu" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/miner" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Debug/" />
<Option type="1" />
<Option compiler="gcc" />
<Option parameters="config-debug.txt" />
<Compiler>
<Add option="-std=c++11" />
<Add option="-m64" />
<Add option="-g" />
<Add directory="include" />
</Compiler>
<Linker>
<Add option="-m64" />
</Linker>
</Target>
<Target title="Release">
<Option output="bin/Release/miner" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Release/" />
<Option type="1" />
<Option compiler="gcc" />
<Option parameters="config-debug.txt" />
<Compiler>
<Add option="-O3" />
<Add option="-std=c++11" />
<Add option="-m64" />
<Add option="-DNDEBUG" />
<Add directory="include" />
</Compiler>
<Linker>
<Add option="-s" />
<Add option="-m64" />
</Linker>
</Target>
<Target title="Release_test">
<Option output="bin/Release_test/miner" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Release_test/" />
<Option type="1" />
<Option compiler="gcc" />
<Option parameters="config-debug.txt" />
<Compiler>
<Add option="-O3" />
<Add option="-std=c++11" />
<Add option="-m64" />
<Add directory="include" />
</Compiler>
<Linker>
<Add option="-s" />
<Add option="-m64" />
</Linker>
</Target>
</Build>
<Compiler>
<Add option="-march=haswell" />
<Add option="-Wall" />
</Compiler>
<Linker>
<Add library="pthread" />
<Add library="libmicrohttpd" />
<Add library="crypto" />
<Add library="ssl" />
<Add library="libhwloc" />
</Linker>
<Unit filename="autoAdjust.hpp" />
<Unit filename="autoAdjustHwloc.hpp" />
<Unit filename="cli-miner.cpp" />
<Unit filename="console.cpp" />
<Unit filename="console.h" />
<Unit filename="crypto/c_blake256.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="crypto/c_blake256.h" />
<Unit filename="crypto/c_groestl.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="crypto/c_groestl.h" />
<Unit filename="crypto/c_jh.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="crypto/c_jh.h" />
<Unit filename="crypto/c_keccak.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="crypto/c_keccak.h" />
<Unit filename="crypto/c_skein.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="crypto/c_skein.h" />
<Unit filename="crypto/cryptonight.h" />
<Unit filename="crypto/cryptonight_aesni.h" />
<Unit filename="crypto/cryptonight_common.cpp" />
<Unit filename="crypto/groestl_tables.h" />
<Unit filename="crypto/hash.h" />
<Unit filename="crypto/int-util.h" />
<Unit filename="crypto/skein_port.h" />
<Unit filename="crypto/soft_aes.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="donate-level.h" />
<Unit filename="executor.cpp" />
<Unit filename="executor.h" />
<Unit filename="httpd.cpp" />
<Unit filename="httpd.h" />
<Unit filename="hwlocMemory.hpp" />
<Unit filename="jconf.cpp" />
<Unit filename="jconf.h" />
<Unit filename="jext.h" />
<Unit filename="jpsock.cpp" />
<Unit filename="jpsock.h" />
<Unit filename="minethd.cpp" />
<Unit filename="minethd.h" />
<Unit filename="msgstruct.h" />
<Unit filename="rapidjson/allocators.h" />
<Unit filename="rapidjson/document.h" />
<Unit filename="rapidjson/encodedstream.h" />
<Unit filename="rapidjson/encodings.h" />
<Unit filename="rapidjson/error/en.h" />
<Unit filename="rapidjson/error/error.h" />
<Unit filename="rapidjson/filereadstream.h" />
<Unit filename="rapidjson/filewritestream.h" />
<Unit filename="rapidjson/fwd.h" />
<Unit filename="rapidjson/internal/biginteger.h" />
<Unit filename="rapidjson/internal/diyfp.h" />
<Unit filename="rapidjson/internal/dtoa.h" />
<Unit filename="rapidjson/internal/ieee754.h" />
<Unit filename="rapidjson/internal/itoa.h" />
<Unit filename="rapidjson/internal/meta.h" />
<Unit filename="rapidjson/internal/pow10.h" />
<Unit filename="rapidjson/internal/regex.h" />
<Unit filename="rapidjson/internal/stack.h" />
<Unit filename="rapidjson/internal/strfunc.h" />
<Unit filename="rapidjson/internal/strtod.h" />
<Unit filename="rapidjson/internal/swap.h" />
<Unit filename="rapidjson/istreamwrapper.h" />
<Unit filename="rapidjson/memorybuffer.h" />
<Unit filename="rapidjson/memorystream.h" />
<Unit filename="rapidjson/msinttypes/inttypes.h" />
<Unit filename="rapidjson/msinttypes/stdint.h" />
<Unit filename="rapidjson/ostreamwrapper.h" />
<Unit filename="rapidjson/pointer.h" />
<Unit filename="rapidjson/prettywriter.h" />
<Unit filename="rapidjson/rapidjson.h" />
<Unit filename="rapidjson/reader.h" />
<Unit filename="rapidjson/schema.h" />
<Unit filename="rapidjson/stream.h" />
<Unit filename="rapidjson/stringbuffer.h" />
<Unit filename="rapidjson/writer.h" />
<Unit filename="socket.cpp" />
<Unit filename="socket.h" />
<Unit filename="socks.h" />
<Unit filename="thdq.hpp" />
<Unit filename="webdesign.cpp" />
<Unit filename="webdesign.h" />
<Extensions>
<code_completion />
<debugger />
</Extensions>
</Project>
</CodeBlocks_project_file>
+887
View File
@@ -0,0 +1,887 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <regex>
#ifdef _WIN32
#include <windows.h>
static inline void port_sleep(size_t sec)
{
Sleep(sec * 1000);
}
#else
#include <unistd.h>
static inline void port_sleep(size_t sec)
{
sleep(sec);
}
#endif // _WIN32
#if 0
static inline long long unsigned int int_port(size_t i)
{
return i;
}
#endif
#include "gpu.hpp"
const char* err_to_str(cl_int ret)
{
switch(ret)
{
case CL_SUCCESS:
return "CL_SUCCESS";
case CL_DEVICE_NOT_FOUND:
return "CL_DEVICE_NOT_FOUND";
case CL_DEVICE_NOT_AVAILABLE:
return "CL_DEVICE_NOT_AVAILABLE";
case CL_COMPILER_NOT_AVAILABLE:
return "CL_COMPILER_NOT_AVAILABLE";
case CL_MEM_OBJECT_ALLOCATION_FAILURE:
return "CL_MEM_OBJECT_ALLOCATION_FAILURE";
case CL_OUT_OF_RESOURCES:
return "CL_OUT_OF_RESOURCES";
case CL_OUT_OF_HOST_MEMORY:
return "CL_OUT_OF_HOST_MEMORY";
case CL_PROFILING_INFO_NOT_AVAILABLE:
return "CL_PROFILING_INFO_NOT_AVAILABLE";
case CL_MEM_COPY_OVERLAP:
return "CL_MEM_COPY_OVERLAP";
case CL_IMAGE_FORMAT_MISMATCH:
return "CL_IMAGE_FORMAT_MISMATCH";
case CL_IMAGE_FORMAT_NOT_SUPPORTED:
return "CL_IMAGE_FORMAT_NOT_SUPPORTED";
case CL_BUILD_PROGRAM_FAILURE:
return "CL_BUILD_PROGRAM_FAILURE";
case CL_MAP_FAILURE:
return "CL_MAP_FAILURE";
case CL_MISALIGNED_SUB_BUFFER_OFFSET:
return "CL_MISALIGNED_SUB_BUFFER_OFFSET";
case CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST:
return "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST";
case CL_COMPILE_PROGRAM_FAILURE:
return "CL_COMPILE_PROGRAM_FAILURE";
case CL_LINKER_NOT_AVAILABLE:
return "CL_LINKER_NOT_AVAILABLE";
case CL_LINK_PROGRAM_FAILURE:
return "CL_LINK_PROGRAM_FAILURE";
case CL_DEVICE_PARTITION_FAILED:
return "CL_DEVICE_PARTITION_FAILED";
case CL_KERNEL_ARG_INFO_NOT_AVAILABLE:
return "CL_KERNEL_ARG_INFO_NOT_AVAILABLE";
case CL_INVALID_VALUE:
return "CL_INVALID_VALUE";
case CL_INVALID_DEVICE_TYPE:
return "CL_INVALID_DEVICE_TYPE";
case CL_INVALID_PLATFORM:
return "CL_INVALID_PLATFORM";
case CL_INVALID_DEVICE:
return "CL_INVALID_DEVICE";
case CL_INVALID_CONTEXT:
return "CL_INVALID_CONTEXT";
case CL_INVALID_QUEUE_PROPERTIES:
return "CL_INVALID_QUEUE_PROPERTIES";
case CL_INVALID_COMMAND_QUEUE:
return "CL_INVALID_COMMAND_QUEUE";
case CL_INVALID_HOST_PTR:
return "CL_INVALID_HOST_PTR";
case CL_INVALID_MEM_OBJECT:
return "CL_INVALID_MEM_OBJECT";
case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:
return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR";
case CL_INVALID_IMAGE_SIZE:
return "CL_INVALID_IMAGE_SIZE";
case CL_INVALID_SAMPLER:
return "CL_INVALID_SAMPLER";
case CL_INVALID_BINARY:
return "CL_INVALID_BINARY";
case CL_INVALID_BUILD_OPTIONS:
return "CL_INVALID_BUILD_OPTIONS";
case CL_INVALID_PROGRAM:
return "CL_INVALID_PROGRAM";
case CL_INVALID_PROGRAM_EXECUTABLE:
return "CL_INVALID_PROGRAM_EXECUTABLE";
case CL_INVALID_KERNEL_NAME:
return "CL_INVALID_KERNEL_NAME";
case CL_INVALID_KERNEL_DEFINITION:
return "CL_INVALID_KERNEL_DEFINITION";
case CL_INVALID_KERNEL:
return "CL_INVALID_KERNEL";
case CL_INVALID_ARG_INDEX:
return "CL_INVALID_ARG_INDEX";
case CL_INVALID_ARG_VALUE:
return "CL_INVALID_ARG_VALUE";
case CL_INVALID_ARG_SIZE:
return "CL_INVALID_ARG_SIZE";
case CL_INVALID_KERNEL_ARGS:
return "CL_INVALID_KERNEL_ARGS";
case CL_INVALID_WORK_DIMENSION:
return "CL_INVALID_WORK_DIMENSION";
case CL_INVALID_WORK_GROUP_SIZE:
return "CL_INVALID_WORK_GROUP_SIZE";
case CL_INVALID_WORK_ITEM_SIZE:
return "CL_INVALID_WORK_ITEM_SIZE";
case CL_INVALID_GLOBAL_OFFSET:
return "CL_INVALID_GLOBAL_OFFSET";
case CL_INVALID_EVENT_WAIT_LIST:
return "CL_INVALID_EVENT_WAIT_LIST";
case CL_INVALID_EVENT:
return "CL_INVALID_EVENT";
case CL_INVALID_OPERATION:
return "CL_INVALID_OPERATION";
case CL_INVALID_GL_OBJECT:
return "CL_INVALID_GL_OBJECT";
case CL_INVALID_BUFFER_SIZE:
return "CL_INVALID_BUFFER_SIZE";
case CL_INVALID_MIP_LEVEL:
return "CL_INVALID_MIP_LEVEL";
case CL_INVALID_GLOBAL_WORK_SIZE:
return "CL_INVALID_GLOBAL_WORK_SIZE";
case CL_INVALID_PROPERTY:
return "CL_INVALID_PROPERTY";
case CL_INVALID_IMAGE_DESCRIPTOR:
return "CL_INVALID_IMAGE_DESCRIPTOR";
case CL_INVALID_COMPILER_OPTIONS:
return "CL_INVALID_COMPILER_OPTIONS";
case CL_INVALID_LINKER_OPTIONS:
return "CL_INVALID_LINKER_OPTIONS";
case CL_INVALID_DEVICE_PARTITION_COUNT:
return "CL_INVALID_DEVICE_PARTITION_COUNT";
#ifdef CL_VERSION_2_0
case CL_INVALID_PIPE_SIZE:
return "CL_INVALID_PIPE_SIZE";
case CL_INVALID_DEVICE_QUEUE:
return "CL_INVALID_DEVICE_QUEUE";
#endif
default:
return "UNKNOWN_ERROR";
}
}
#if 0
void printer::inst()->print_msg(L1,const char* fmt, ...);
void printer::inst()->print_str(const char* str);
#endif
char* LoadTextFile(const char* filename)
{
size_t flen;
char* out;
FILE* kernel = fopen(filename, "rb");
if(kernel == NULL)
return NULL;
fseek(kernel, 0, SEEK_END);
flen = ftell(kernel);
fseek(kernel, 0, SEEK_SET);
out = (char*)malloc(flen+1);
size_t r = fread(out, flen, 1, kernel);
fclose(kernel);
if(r != 1)
{
free(out);
return NULL;
}
out[flen] = '\0';
return out;
}
size_t InitOpenCLGpu(cl_context opencl_ctx, GpuContext* ctx, const char* source_code)
{
size_t MaximumWorkSize;
cl_int ret;
if((ret = clGetDeviceInfo(ctx->DeviceID, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t), &MaximumWorkSize, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when querying a device's max worksize using clGetDeviceInfo.", err_to_str(ret));
return ERR_OCL_API;
}
printer::inst()->print_msg(L1,"Device %lu work size %lu / %lu.", ctx->deviceIdx, ctx->workSize, MaximumWorkSize);
#ifdef CL_VERSION_2_0
const cl_queue_properties CommandQueueProperties[] = { 0, 0, 0 };
ctx->CommandQueues = clCreateCommandQueueWithProperties(opencl_ctx, ctx->DeviceID, CommandQueueProperties, &ret);
#else
const cl_command_queue_properties CommandQueueProperties = { 0 };
ctx->CommandQueues = clCreateCommandQueue(opencl_ctx, ctx->DeviceID, CommandQueueProperties, &ret);
#endif
if(ret != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clCreateCommandQueueWithProperties.", err_to_str(ret));
return ERR_OCL_API;
}
ctx->InputBuffer = clCreateBuffer(opencl_ctx, CL_MEM_READ_ONLY, 88, NULL, &ret);
if(ret != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clCreateBuffer to create input buffer.", err_to_str(ret));
return ERR_OCL_API;
}
size_t g_thd = ctx->rawIntensity;
ctx->ExtraBuffers[0] = clCreateBuffer(opencl_ctx, CL_MEM_READ_WRITE, (1 << 21) * g_thd, NULL, &ret);
if(ret != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clCreateBuffer to create hash scratchpads buffer.", err_to_str(ret));
return ERR_OCL_API;
}
ctx->ExtraBuffers[1] = clCreateBuffer(opencl_ctx, CL_MEM_READ_WRITE, 200 * g_thd, NULL, &ret);
if(ret != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clCreateBuffer to create hash states buffer.", err_to_str(ret));
return ERR_OCL_API;
}
// Blake-256 branches
ctx->ExtraBuffers[2] = clCreateBuffer(opencl_ctx, CL_MEM_READ_WRITE, sizeof(cl_uint) * (g_thd + 2), NULL, &ret);
if(ret != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clCreateBuffer to create Branch 0 buffer.", err_to_str(ret));
return ERR_OCL_API;
}
// Groestl-256 branches
ctx->ExtraBuffers[3] = clCreateBuffer(opencl_ctx, CL_MEM_READ_WRITE, sizeof(cl_uint) * (g_thd + 2), NULL, &ret);
if(ret != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clCreateBuffer to create Branch 1 buffer.", err_to_str(ret));
return ERR_OCL_API;
}
// JH-256 branches
ctx->ExtraBuffers[4] = clCreateBuffer(opencl_ctx, CL_MEM_READ_WRITE, sizeof(cl_uint) * (g_thd + 2), NULL, &ret);
if(ret != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clCreateBuffer to create Branch 2 buffer.", err_to_str(ret));
return ERR_OCL_API;
}
// Skein-512 branches
ctx->ExtraBuffers[5] = clCreateBuffer(opencl_ctx, CL_MEM_READ_WRITE, sizeof(cl_uint) * (g_thd + 2), NULL, &ret);
if(ret != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clCreateBuffer to create Branch 3 buffer.", err_to_str(ret));
return ERR_OCL_API;
}
// Assume we may find up to 0xFF nonces in one run - it's reasonable
ctx->OutputBuffer = clCreateBuffer(opencl_ctx, CL_MEM_READ_WRITE, sizeof(cl_uint) * 0x100, NULL, &ret);
if(ret != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clCreateBuffer to create output buffer.", err_to_str(ret));
return ERR_OCL_API;
}
ctx->Program = clCreateProgramWithSource(opencl_ctx, 1, (const char**)&source_code, NULL, &ret);
if(ret != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clCreateProgramWithSource on the contents of cryptonight.cl", err_to_str(ret));
return ERR_OCL_API;
}
char options[32];
snprintf(options, sizeof(options), "-I. -DWORKSIZE=%llu", int_port(ctx->workSize));
ret = clBuildProgram(ctx->Program, 1, &ctx->DeviceID, options, NULL, NULL);
if(ret != CL_SUCCESS)
{
size_t len;
printer::inst()->print_msg(L1,"Error %s when calling clBuildProgram.", err_to_str(ret));
if((ret = clGetProgramBuildInfo(ctx->Program, ctx->DeviceID, CL_PROGRAM_BUILD_LOG, 0, NULL, &len)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clGetProgramBuildInfo for length of build log output.", err_to_str(ret));
return ERR_OCL_API;
}
char* BuildLog = (char*)malloc(len + 1);
BuildLog[0] = '\0';
if((ret = clGetProgramBuildInfo(ctx->Program, ctx->DeviceID, CL_PROGRAM_BUILD_LOG, len, BuildLog, NULL)) != CL_SUCCESS)
{
free(BuildLog);
printer::inst()->print_msg(L1,"Error %s when calling clGetProgramBuildInfo for build log.", err_to_str(ret));
return ERR_OCL_API;
}
printer::inst()->print_str("Build log:\n");
std::cerr<<BuildLog<<std::endl;
free(BuildLog);
return ERR_OCL_API;
}
cl_build_status status;
do
{
if((ret = clGetProgramBuildInfo(ctx->Program, ctx->DeviceID, CL_PROGRAM_BUILD_STATUS, sizeof(cl_build_status), &status, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clGetProgramBuildInfo for status of build.", err_to_str(ret));
return ERR_OCL_API;
}
port_sleep(1);
}
while(status == CL_BUILD_IN_PROGRESS);
const char *KernelNames[] = { "cn0", "cn1", "cn2", "Blake", "Groestl", "JH", "Skein" };
for(int i = 0; i < 7; ++i)
{
ctx->Kernels[i] = clCreateKernel(ctx->Program, KernelNames[i], &ret);
if(ret != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clCreateKernel for kernel %s.", err_to_str(ret), KernelNames[i]);
return ERR_OCL_API;
}
}
ctx->Nonce = 0;
return 0;
}
const cl_platform_info attributeTypes[5] = {
CL_PLATFORM_NAME,
CL_PLATFORM_VENDOR,
CL_PLATFORM_VERSION,
CL_PLATFORM_PROFILE,
CL_PLATFORM_EXTENSIONS
};
const char* const attributeNames[] = {
"CL_PLATFORM_NAME",
"CL_PLATFORM_VENDOR",
"CL_PLATFORM_VERSION",
"CL_PLATFORM_PROFILE",
"CL_PLATFORM_EXTENSIONS"
};
#define NELEMS(x) (sizeof(x) / sizeof((x)[0]))
void PrintDeviceInfo(cl_device_id device)
{
char queryBuffer[1024];
int queryInt;
cl_int clError;
clError = clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(queryBuffer), &queryBuffer, NULL);
printf(" CL_DEVICE_NAME: %s\n", queryBuffer);
queryBuffer[0] = '\0';
clError = clGetDeviceInfo(device, CL_DEVICE_VENDOR, sizeof(queryBuffer), &queryBuffer, NULL);
printf(" CL_DEVICE_VENDOR: %s\n", queryBuffer);
queryBuffer[0] = '\0';
clError = clGetDeviceInfo(device, CL_DRIVER_VERSION, sizeof(queryBuffer), &queryBuffer, NULL);
printf(" CL_DRIVER_VERSION: %s\n", queryBuffer);
queryBuffer[0] = '\0';
clError = clGetDeviceInfo(device, CL_DEVICE_VERSION, sizeof(queryBuffer), &queryBuffer, NULL);
printf(" CL_DEVICE_VERSION: %s\n", queryBuffer);
queryBuffer[0] = '\0';
clError = clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(int), &queryInt, NULL);
printf(" CL_DEVICE_MAX_COMPUTE_UNITS: %d\n", queryInt);
}
uint32_t getNumPlatforms()
{
cl_uint num_platforms = 0;
cl_platform_id * platforms = NULL;
cl_int clStatus;
// Get platform and device information
clStatus = clGetPlatformIDs(0, NULL, &num_platforms);
platforms = (cl_platform_id *) malloc(sizeof(cl_platform_id) * num_platforms);
clStatus = clGetPlatformIDs(num_platforms, platforms, NULL);
return num_platforms;
}
std::vector<GpuContext> getAMDDevices(int index)
{
std::vector<GpuContext> ctxVec;
cl_platform_id * platforms = NULL;
cl_int clStatus;
cl_uint num_devices;
cl_device_id *device_list = NULL;
uint32_t numPlatforms = getNumPlatforms();
platforms = (cl_platform_id *) malloc(sizeof(cl_platform_id) * numPlatforms);
clStatus = clGetPlatformIDs(numPlatforms, platforms, NULL);
clStatus = clGetDeviceIDs( platforms[index], CL_DEVICE_TYPE_GPU, 0, NULL, &num_devices);
device_list = (cl_device_id *) malloc(sizeof(cl_device_id)*num_devices);
clStatus = clGetDeviceIDs( platforms[index], CL_DEVICE_TYPE_GPU, num_devices, device_list, NULL);
for (int k = 0; k < num_devices; k++) {
cl_int clError;
std::vector<char> devVendorVec(1024);
clError = clGetDeviceInfo(device_list[k], CL_DEVICE_VENDOR, devVendorVec.size(), devVendorVec.data(), NULL);
std::string devVendor(devVendorVec.data());
if( devVendor.find("Advanced Micro Devices") != std::string::npos)
{
GpuContext ctx;
ctx.deviceIdx = k;
clError = clGetDeviceInfo(device_list[k], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(int), &(ctx.computeUnits), NULL);
size_t maxMem;
clError = clGetDeviceInfo(device_list[k], CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(size_t), &(maxMem), NULL);
clError = clGetDeviceInfo(device_list[k], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(size_t), &(ctx.freeMem), NULL);
// if environment variable GPU_SINGLE_ALLOC_PERCENT is not set we can not allocate the full memory
ctx.freeMem = std::min(ctx.freeMem, maxMem);
std::vector<char> devNameVec(1024);
clError = clGetDeviceInfo(device_list[k], CL_DEVICE_NAME, devNameVec.size(), devNameVec.data(), NULL);
ctx.name = std::string(devNameVec.data());
printer::inst()->print_msg(L0,"Found OpenCL GPU %s.",ctx.name.c_str());
ctx.DeviceID = device_list[k];
ctxVec.push_back(ctx);
}
}
free(device_list);
free(platforms);
return ctxVec;
}
int getAMDPlatformIdx()
{
uint32_t numPlatforms = getNumPlatforms();
if(numPlatforms == 0)
{
printer::inst()->print_msg(L0,"WARNING: No OpenCL platform found.");
return -1;
}
cl_platform_id * platforms = NULL;
cl_int clStatus;
platforms = (cl_platform_id *) malloc(sizeof(cl_platform_id) * numPlatforms);
clStatus = clGetPlatformIDs(numPlatforms, platforms, NULL);
int platformIndex = -1;
for (int i = 0; i < numPlatforms; i++) {
size_t infoSize;
clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, 0, NULL, &infoSize);
std::vector<char> platformNameVec(infoSize);
clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, infoSize, platformNameVec.data(), NULL);
std::string platformName(platformNameVec.data());
if( platformName.find("Advanced Micro Devices") != std::string::npos)
{
platformIndex = i;
printer::inst()->print_msg(L0,"Found AMD platform index id = %i, name = %s",i , platformName.c_str());
break;
}
}
free(platforms);
return platformIndex;
}
// RequestedDeviceIdxs is a list of OpenCL device indexes
// NumDevicesRequested is number of devices in RequestedDeviceIdxs list
// Returns 0 on success, -1 on stupid params, -2 on OpenCL API error
size_t InitOpenCL(GpuContext* ctx, size_t num_gpus, size_t platform_idx)
{
cl_context opencl_ctx;
cl_int ret;
cl_uint entries;
if((ret = clGetPlatformIDs(0, NULL, &entries)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clGetPlatformIDs for number of platforms.", err_to_str(ret));
return ERR_OCL_API;
}
// The number of platforms naturally is the index of the last platform plus one.
if(entries <= platform_idx)
{
printer::inst()->print_msg(L1,"Selected OpenCL platform index %d doesn't exist.", platform_idx);
return ERR_STUPID_PARAMS;
}
cl_platform_id * platforms = NULL;
cl_int clStatus;
uint32_t numPlatforms = getNumPlatforms();
platforms = (cl_platform_id *) malloc(sizeof(cl_platform_id) * numPlatforms);
clStatus = clGetPlatformIDs(numPlatforms, platforms, NULL);
size_t infoSize;
clGetPlatformInfo(platforms[platform_idx], CL_PLATFORM_VENDOR, 0, NULL, &infoSize);
std::vector<char> platformNameVec(infoSize);
clGetPlatformInfo(platforms[platform_idx], CL_PLATFORM_VENDOR, infoSize, platformNameVec.data(), NULL);
std::string platformName(platformNameVec.data());
if( platformName.find("Advanced Micro Devices") == std::string::npos)
{
printer::inst()->print_msg(L1,"WARNING: using non AMD device: %s", platformName.c_str());
}
free(platforms);
/*MSVC skimping on devel costs by shoehorning C99 to be a subset of C++? Noooo... can't be.*/
#ifdef __GNUC__
cl_platform_id PlatformIDList[entries];
#else
cl_platform_id* PlatformIDList = (cl_platform_id*)_alloca(entries * sizeof(cl_platform_id));
#endif
if((ret = clGetPlatformIDs(entries, PlatformIDList, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clGetPlatformIDs for platform ID information.", err_to_str(ret));
return ERR_OCL_API;
}
if((ret = clGetDeviceIDs(PlatformIDList[platform_idx], CL_DEVICE_TYPE_GPU, 0, NULL, &entries)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clGetDeviceIDs for number of devices.", err_to_str(ret));
return ERR_OCL_API;
}
// Same as the platform index sanity check, except we must check all requested device indexes
for(int i = 0; i < num_gpus; ++i)
{
if(entries <= ctx[i].deviceIdx)
{
printer::inst()->print_msg(L1,"Selected OpenCL device index %lu doesn't exist.\n", ctx[i].deviceIdx);
return ERR_STUPID_PARAMS;
}
}
#ifdef __GNUC__
cl_device_id DeviceIDList[entries];
#else
cl_device_id* DeviceIDList = (cl_device_id*)_alloca(entries * sizeof(cl_device_id));
#endif
if((ret = clGetDeviceIDs(PlatformIDList[platform_idx], CL_DEVICE_TYPE_GPU, entries, DeviceIDList, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clGetDeviceIDs for device ID information.", err_to_str(ret));
return ERR_OCL_API;
}
// Indexes sanity checked above
#ifdef __GNUC__
cl_device_id TempDeviceList[num_gpus];
#else
cl_device_id* TempDeviceList = (cl_device_id*)_alloca(entries * sizeof(cl_device_id));
#endif
for(int i = 0; i < num_gpus; ++i)
{
ctx[i].DeviceID = DeviceIDList[ctx[i].deviceIdx];
TempDeviceList[i] = DeviceIDList[ctx[i].deviceIdx];
}
opencl_ctx = clCreateContext(NULL, num_gpus, TempDeviceList, NULL, NULL, &ret);
if(ret != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clCreateContext.", err_to_str(ret));
return ERR_OCL_API;
}
//char* source_code = LoadTextFile(sSourcePath);
const char *cryptonightCL =
#include "./opencl/cryptonight.cl"
;
const char *blake256CL =
#include "./opencl/blake256.cl"
;
const char *groestl256CL =
#include "./opencl/groestl256.cl"
;
const char *jhCL =
#include "./opencl/jh.cl"
;
const char *wolfAesCL =
#include "./opencl/wolf-aes.cl"
;
const char *wolfSkeinCL =
#include "./opencl/wolf-skein.cl"
;
std::string source_code(cryptonightCL);
source_code = std::regex_replace(source_code, std::regex("XMRSTAK_INCLUDE_WOLF_AES"), wolfAesCL);
source_code = std::regex_replace(source_code, std::regex("XMRSTAK_INCLUDE_WOLF_SKEIN"), wolfSkeinCL);
source_code = std::regex_replace(source_code, std::regex("XMRSTAK_INCLUDE_JH"), jhCL);
source_code = std::regex_replace(source_code, std::regex("XMRSTAK_INCLUDE_BLAKE256"), blake256CL);
source_code = std::regex_replace(source_code, std::regex("XMRSTAK_INCLUDE_GROESTL256"), groestl256CL);
for(int i = 0; i < num_gpus; ++i)
{
if((ret = InitOpenCLGpu(opencl_ctx, &ctx[i], source_code.c_str())) != ERR_SUCCESS)
{
return ret;
}
}
return ERR_SUCCESS;
}
size_t XMRSetJob(GpuContext* ctx, uint8_t* input, size_t input_len, uint32_t target)
{
cl_int ret;
if(input_len > 84)
return ERR_STUPID_PARAMS;
input[input_len] = 0x01;
memset(input + input_len + 1, 0, 88 - input_len - 1);
if((ret = clEnqueueWriteBuffer(ctx->CommandQueues, ctx->InputBuffer, CL_TRUE, 0, 88, input, 0, NULL, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clEnqueueWriteBuffer to fill input buffer.", err_to_str(ret));
return ERR_OCL_API;
}
if((ret = clSetKernelArg(ctx->Kernels[0], 0, sizeof(cl_mem), &ctx->InputBuffer)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel 0, argument 0.", err_to_str(ret));
return ERR_OCL_API;
}
// Scratchpads
if((ret = clSetKernelArg(ctx->Kernels[0], 1, sizeof(cl_mem), ctx->ExtraBuffers + 0)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel 0, argument 1.", err_to_str(ret));
return ERR_OCL_API;
}
// States
if((ret = clSetKernelArg(ctx->Kernels[0], 2, sizeof(cl_mem), ctx->ExtraBuffers + 1)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel 0, argument 2.", err_to_str(ret));
return ERR_OCL_API;
}
// CN2 Kernel
// Scratchpads
if((ret = clSetKernelArg(ctx->Kernels[1], 0, sizeof(cl_mem), ctx->ExtraBuffers + 0)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel 1, argument 0.", err_to_str(ret));
return ERR_OCL_API;
}
// States
if((ret = clSetKernelArg(ctx->Kernels[1], 1, sizeof(cl_mem), ctx->ExtraBuffers + 1)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel 1, argument 1.", err_to_str(ret));
return ERR_OCL_API;
}
// CN3 Kernel
// Scratchpads
if((ret = clSetKernelArg(ctx->Kernels[2], 0, sizeof(cl_mem), ctx->ExtraBuffers + 0)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel 2, argument 0.", err_to_str(ret));
return ERR_OCL_API;
}
// States
if((ret = clSetKernelArg(ctx->Kernels[2], 1, sizeof(cl_mem), ctx->ExtraBuffers + 1)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel 2, argument 1.", err_to_str(ret));
return ERR_OCL_API;
}
// Branch 0
if((ret = clSetKernelArg(ctx->Kernels[2], 2, sizeof(cl_mem), ctx->ExtraBuffers + 2)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel 2, argument 2.", err_to_str(ret));
return ERR_OCL_API;
}
// Branch 1
if((ret = clSetKernelArg(ctx->Kernels[2], 3, sizeof(cl_mem), ctx->ExtraBuffers + 3)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel 2, argument 3.", err_to_str(ret));
return ERR_OCL_API;
}
// Branch 2
if((ret = clSetKernelArg(ctx->Kernels[2], 4, sizeof(cl_mem), ctx->ExtraBuffers + 4)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel 2, argument 4.", err_to_str(ret));
return ERR_OCL_API;
}
// Branch 3
if((ret = clSetKernelArg(ctx->Kernels[2], 5, sizeof(cl_mem), ctx->ExtraBuffers + 5)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel 2, argument 5.", err_to_str(ret));
return ERR_OCL_API;
}
for(int i = 0; i < 4; ++i)
{
// States
if((ret = clSetKernelArg(ctx->Kernels[i + 3], 0, sizeof(cl_mem), ctx->ExtraBuffers + 1)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel %d, argument %d.", err_to_str(ret), i + 3, 0);
return ERR_OCL_API;
}
// Nonce buffer
if((ret = clSetKernelArg(ctx->Kernels[i + 3], 1, sizeof(cl_mem), ctx->ExtraBuffers + (i + 2))) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel %d, argument %d.", err_to_str(ret), i + 3, 1);
return ERR_OCL_API;
}
// Output
if((ret = clSetKernelArg(ctx->Kernels[i + 3], 2, sizeof(cl_mem), &ctx->OutputBuffer)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel %d, argument %d.", err_to_str(ret), i + 3, 2);
return ERR_OCL_API;
}
// Target
if((ret = clSetKernelArg(ctx->Kernels[i + 3], 3, sizeof(cl_uint), &target)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel %d, argument %d.", err_to_str(ret), i + 3, 3);
return ERR_OCL_API;
}
}
return ERR_SUCCESS;
}
size_t XMRRunJob(GpuContext* ctx, cl_uint* HashOutput)
{
cl_int ret;
cl_uint zero = 0;
size_t BranchNonces[4];
memset(BranchNonces,0,sizeof(size_t)*4);
size_t g_thd = ctx->rawIntensity;
size_t w_size = ctx->workSize;
for(int i = 2; i < 6; ++i)
{
if((ret = clEnqueueWriteBuffer(ctx->CommandQueues, ctx->ExtraBuffers[i], CL_FALSE, sizeof(cl_uint) * g_thd, sizeof(cl_uint), &zero, 0, NULL, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clEnqueueWriteBuffer to zero branch buffer counter %d.", err_to_str(ret), i - 2);
return ERR_OCL_API;
}
}
if((ret = clEnqueueWriteBuffer(ctx->CommandQueues, ctx->OutputBuffer, CL_FALSE, sizeof(cl_uint) * 0xFF, sizeof(cl_uint), &zero, 0, NULL, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clEnqueueReadBuffer to fetch results.", err_to_str(ret));
return ERR_OCL_API;
}
clFinish(ctx->CommandQueues);
size_t Nonce[2] = {ctx->Nonce, 1}, gthreads[2] = { g_thd, 8 }, lthreads[2] = { w_size, 8 };
if((ret = clEnqueueNDRangeKernel(ctx->CommandQueues, ctx->Kernels[0], 2, Nonce, gthreads, lthreads, 0, NULL, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clEnqueueNDRangeKernel for kernel %d.", err_to_str(ret), 0);
return ERR_OCL_API;
}
/*for(int i = 1; i < 3; ++i)
{
if((ret = clEnqueueNDRangeKernel(*ctx->CommandQueues, ctx->Kernels[i], 1, &ctx->Nonce, &g_thd, &w_size, 0, NULL, NULL)) != CL_SUCCESS)
{
Log(LOG_CRITICAL, "Error %s when calling clEnqueueNDRangeKernel for kernel %d.", err_to_str(ret), i);
return(ERR_OCL_API);
}
}*/
if((ret = clEnqueueNDRangeKernel(ctx->CommandQueues, ctx->Kernels[1], 1, &ctx->Nonce, &g_thd, &w_size, 0, NULL, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clEnqueueNDRangeKernel for kernel %d.", err_to_str(ret), 1);
return ERR_OCL_API;
}
if((ret = clEnqueueNDRangeKernel(ctx->CommandQueues, ctx->Kernels[2], 2, Nonce, gthreads, lthreads, 0, NULL, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clEnqueueNDRangeKernel for kernel %d.", err_to_str(ret), 2);
return ERR_OCL_API;
}
if((ret = clEnqueueReadBuffer(ctx->CommandQueues, ctx->ExtraBuffers[2], CL_FALSE, sizeof(cl_uint) * g_thd, sizeof(cl_uint), BranchNonces, 0, NULL, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clEnqueueReadBuffer to fetch results.", err_to_str(ret));
return ERR_OCL_API;
}
if((ret = clEnqueueReadBuffer(ctx->CommandQueues, ctx->ExtraBuffers[3], CL_FALSE, sizeof(cl_uint) * g_thd, sizeof(cl_uint), BranchNonces + 1, 0, NULL, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clEnqueueReadBuffer to fetch results.", err_to_str(ret));
return ERR_OCL_API;
}
if((ret = clEnqueueReadBuffer(ctx->CommandQueues, ctx->ExtraBuffers[4], CL_FALSE, sizeof(cl_uint) * g_thd, sizeof(cl_uint), BranchNonces + 2, 0, NULL, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clEnqueueReadBuffer to fetch results.", err_to_str(ret));
return ERR_OCL_API;
}
if((ret = clEnqueueReadBuffer(ctx->CommandQueues, ctx->ExtraBuffers[5], CL_FALSE, sizeof(cl_uint) * g_thd, sizeof(cl_uint), BranchNonces + 3, 0, NULL, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clEnqueueReadBuffer to fetch results.", err_to_str(ret));
return ERR_OCL_API;
}
clFinish(ctx->CommandQueues);
for(int i = 0; i < 4; ++i)
{
if(BranchNonces[i])
{
// Threads
if((clSetKernelArg(ctx->Kernels[i + 3], 4, sizeof(cl_ulong), BranchNonces + i)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clSetKernelArg for kernel %d, argument %d.", err_to_str(ret), i + 3, 4);
return(ERR_OCL_API);
}
BranchNonces[i] = ((size_t)ceil( (double)BranchNonces[i] / (double)w_size) ) * w_size;
if((ret = clEnqueueNDRangeKernel(ctx->CommandQueues, ctx->Kernels[i + 3], 1, &ctx->Nonce, BranchNonces + i, &w_size, 0, NULL, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clEnqueueNDRangeKernel for kernel %d.", err_to_str(ret), i + 3);
return ERR_OCL_API;
}
}
}
if((ret = clEnqueueReadBuffer(ctx->CommandQueues, ctx->OutputBuffer, CL_TRUE, 0, sizeof(cl_uint) * 0x100, HashOutput, 0, NULL, NULL)) != CL_SUCCESS)
{
printer::inst()->print_msg(L1,"Error %s when calling clEnqueueReadBuffer to fetch results.", err_to_str(ret));
return ERR_OCL_API;
}
clFinish(ctx->CommandQueues);
ctx->Nonce += g_thd;
return ERR_SUCCESS;
}
+51
View File
@@ -0,0 +1,51 @@
#pragma once
#include "xmrstak/misc/console.hpp"
#if defined(__APPLE__)
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#endif
#include <stdint.h>
#include <vector>
#define ERR_SUCCESS (0)
#define ERR_OCL_API (2)
#define ERR_STUPID_PARAMS (1)
struct GpuContext
{
/*Input vars*/
size_t deviceIdx;
size_t rawIntensity;
size_t workSize;
/*Output vars*/
cl_device_id DeviceID;
cl_command_queue CommandQueues;
cl_mem InputBuffer;
cl_mem OutputBuffer;
cl_mem ExtraBuffers[6];
cl_program Program;
cl_kernel Kernels[7];
size_t freeMem;
int computeUnits;
std::string name;
size_t Nonce;
};
uint32_t getNumPlatforms();
int getAMDPlatformIdx();
std::vector<GpuContext> getAMDDevices(int index);
size_t InitOpenCL(GpuContext* ctx, size_t num_gpus, size_t platform_idx);
size_t XMRSetJob(GpuContext* ctx, uint8_t* input, size_t input_len, uint32_t target);
size_t XMRRunJob(GpuContext* ctx, cl_uint* HashOutput);
@@ -0,0 +1,93 @@
R"===(
/*
* blake256 kernel implementation.
*
* ==========================(LICENSE BEGIN)============================
* Copyright (c) 2014 djm34
* Copyright (c) 2014 tpruvot
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* ===========================(LICENSE END)=============================
*
* @author djm34
*/
__constant static const int sigma[16][16] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }
};
__constant static const sph_u32 c_IV256[8] = {
0x6A09E667, 0xBB67AE85,
0x3C6EF372, 0xA54FF53A,
0x510E527F, 0x9B05688C,
0x1F83D9AB, 0x5BE0CD19
};
/* Second part (64-80) msg never change, store it */
__constant static const sph_u32 c_Padding[16] = {
0, 0, 0, 0,
0x80000000, 0, 0, 0,
0, 0, 0, 0,
0, 1, 0, 640,
};
__constant static const sph_u32 c_u256[16] = {
0x243F6A88, 0x85A308D3,
0x13198A2E, 0x03707344,
0xA4093822, 0x299F31D0,
0x082EFA98, 0xEC4E6C89,
0x452821E6, 0x38D01377,
0xBE5466CF, 0x34E90C6C,
0xC0AC29B7, 0xC97C50DD,
0x3F84D5B5, 0xB5470917
};
#define GS(a,b,c,d,x) { \
const sph_u32 idx1 = sigma[r][x]; \
const sph_u32 idx2 = sigma[r][x+1]; \
v[a] += (m[idx1] ^ c_u256[idx2]) + v[b]; \
v[d] ^= v[a]; \
v[d] = rotate(v[d], 16U); \
v[c] += v[d]; \
v[b] ^= v[c]; \
v[b] = rotate(v[b], 20U); \
\
v[a] += (m[idx2] ^ c_u256[idx1]) + v[b]; \
v[d] ^= v[a]; \
v[d] = rotate(v[d], 24U); \
v[c] += v[d]; \
v[b] ^= v[c]; \
v[b] = rotate(v[b], 25U); \
}
)==="
@@ -0,0 +1,860 @@
R"===(
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef cl_amd_media_ops
#pragma OPENCL EXTENSION cl_amd_media_ops : enable
#else
/* taken from https://www.khronos.org/registry/OpenCL/extensions/amd/cl_amd_media_ops.txt
* Build-in Function
* uintn amd_bitalign (uintn src0, uintn src1, uintn src2)
* Description
* dst.s0 = (uint) (((((long)src0.s0) << 32) | (long)src1.s0) >> (src2.s0 & 31))
* similar operation applied to other components of the vectors.
*
* The implemented function is modified because the last is in our case always a scalar.
* We can ignore the bitwise AND operation.
*/
inline uint2 amd_bitalign( const uint2 src0, const uint2 src1, const uint src2)
{
uint2 result;
result.s0 = (uint) (((((long)src0.s0) << 32) | (long)src1.s0) >> (src2));
result.s1 = (uint) (((((long)src0.s1) << 32) | (long)src1.s1) >> (src2));
return result;
}
#endif
#ifdef cl_amd_media_ops2
#pragma OPENCL EXTENSION cl_amd_media_ops2 : enable
#else
/* taken from: https://www.khronos.org/registry/OpenCL/extensions/amd/cl_amd_media_ops2.txt
* Built-in Function:
* uintn amd_bfe (uintn src0, uintn src1, uintn src2)
* Description
* NOTE: operator >> below represent logical right shift
* offset = src1.s0 & 31;
* width = src2.s0 & 31;
* if width = 0
* dst.s0 = 0;
* else if (offset + width) < 32
* dst.s0 = (src0.s0 << (32 - offset - width)) >> (32 - width);
* else
* dst.s0 = src0.s0 >> offset;
* similar operation applied to other components of the vectors
*/
inline int amd_bfe(const uint src0, const uint offset, const uint width)
{
/* casts are removed because we can implement everything as uint
* int offset = src1;
* int width = src2;
* remove check for edge case, this function is always called with
* `width==8`
* @code
* if ( width == 0 )
* return 0;
* @endcode
*/
if ( (offset + width) < 32u )
return (src0 << (32u - offset - width)) >> (32u - width);
return src0 >> offset;
}
#endif
//#include "opencl/wolf-aes.cl"
XMRSTAK_INCLUDE_WOLF_AES
//#include "opencl/wolf-skein.cl"
XMRSTAK_INCLUDE_WOLF_SKEIN
//#include "opencl/jh.cl"
XMRSTAK_INCLUDE_JH
//#include "opencl/blake256.cl"
XMRSTAK_INCLUDE_BLAKE256
//#include "opencl/groestl256.cl"
XMRSTAK_INCLUDE_GROESTL256
static const __constant ulong keccakf_rndc[24] =
{
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
};
static const __constant uchar sbox[256] =
{
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
};
void keccakf1600(ulong *s)
{
for(int i = 0; i < 24; ++i)
{
ulong bc[5], tmp1, tmp2;
bc[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20] ^ rotate(s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22], 1UL);
bc[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21] ^ rotate(s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23], 1UL);
bc[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22] ^ rotate(s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24], 1UL);
bc[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23] ^ rotate(s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20], 1UL);
bc[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24] ^ rotate(s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21], 1UL);
tmp1 = s[1] ^ bc[0];
s[0] ^= bc[4];
s[1] = rotate(s[6] ^ bc[0], 44UL);
s[6] = rotate(s[9] ^ bc[3], 20UL);
s[9] = rotate(s[22] ^ bc[1], 61UL);
s[22] = rotate(s[14] ^ bc[3], 39UL);
s[14] = rotate(s[20] ^ bc[4], 18UL);
s[20] = rotate(s[2] ^ bc[1], 62UL);
s[2] = rotate(s[12] ^ bc[1], 43UL);
s[12] = rotate(s[13] ^ bc[2], 25UL);
s[13] = rotate(s[19] ^ bc[3], 8UL);
s[19] = rotate(s[23] ^ bc[2], 56UL);
s[23] = rotate(s[15] ^ bc[4], 41UL);
s[15] = rotate(s[4] ^ bc[3], 27UL);
s[4] = rotate(s[24] ^ bc[3], 14UL);
s[24] = rotate(s[21] ^ bc[0], 2UL);
s[21] = rotate(s[8] ^ bc[2], 55UL);
s[8] = rotate(s[16] ^ bc[0], 35UL);
s[16] = rotate(s[5] ^ bc[4], 36UL);
s[5] = rotate(s[3] ^ bc[2], 28UL);
s[3] = rotate(s[18] ^ bc[2], 21UL);
s[18] = rotate(s[17] ^ bc[1], 15UL);
s[17] = rotate(s[11] ^ bc[0], 10UL);
s[11] = rotate(s[7] ^ bc[1], 6UL);
s[7] = rotate(s[10] ^ bc[4], 3UL);
s[10] = rotate(tmp1, 1UL);
tmp1 = s[0]; tmp2 = s[1]; s[0] = bitselect(s[0] ^ s[2], s[0], s[1]); s[1] = bitselect(s[1] ^ s[3], s[1], s[2]); s[2] = bitselect(s[2] ^ s[4], s[2], s[3]); s[3] = bitselect(s[3] ^ tmp1, s[3], s[4]); s[4] = bitselect(s[4] ^ tmp2, s[4], tmp1);
tmp1 = s[5]; tmp2 = s[6]; s[5] = bitselect(s[5] ^ s[7], s[5], s[6]); s[6] = bitselect(s[6] ^ s[8], s[6], s[7]); s[7] = bitselect(s[7] ^ s[9], s[7], s[8]); s[8] = bitselect(s[8] ^ tmp1, s[8], s[9]); s[9] = bitselect(s[9] ^ tmp2, s[9], tmp1);
tmp1 = s[10]; tmp2 = s[11]; s[10] = bitselect(s[10] ^ s[12], s[10], s[11]); s[11] = bitselect(s[11] ^ s[13], s[11], s[12]); s[12] = bitselect(s[12] ^ s[14], s[12], s[13]); s[13] = bitselect(s[13] ^ tmp1, s[13], s[14]); s[14] = bitselect(s[14] ^ tmp2, s[14], tmp1);
tmp1 = s[15]; tmp2 = s[16]; s[15] = bitselect(s[15] ^ s[17], s[15], s[16]); s[16] = bitselect(s[16] ^ s[18], s[16], s[17]); s[17] = bitselect(s[17] ^ s[19], s[17], s[18]); s[18] = bitselect(s[18] ^ tmp1, s[18], s[19]); s[19] = bitselect(s[19] ^ tmp2, s[19], tmp1);
tmp1 = s[20]; tmp2 = s[21]; s[20] = bitselect(s[20] ^ s[22], s[20], s[21]); s[21] = bitselect(s[21] ^ s[23], s[21], s[22]); s[22] = bitselect(s[22] ^ s[24], s[22], s[23]); s[23] = bitselect(s[23] ^ tmp1, s[23], s[24]); s[24] = bitselect(s[24] ^ tmp2, s[24], tmp1);
s[0] ^= keccakf_rndc[i];
}
}
static const __constant uint keccakf_rotc[24] =
{
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
};
static const __constant uint keccakf_piln[24] =
{
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
};
void keccakf1600_1(ulong *st)
{
int i, round;
ulong t, bc[5];
#pragma unroll 1
for(round = 0; round < 24; ++round)
{
// Theta
bc[0] = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20];
bc[1] = st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21];
bc[2] = st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22];
bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
#pragma unroll 1
for (i = 0; i < 5; ++i) {
t = bc[(i + 4) % 5] ^ rotate(bc[(i + 1) % 5], 1UL);
st[i ] ^= t;
st[i + 5] ^= t;
st[i + 10] ^= t;
st[i + 15] ^= t;
st[i + 20] ^= t;
}
// Rho Pi
t = st[1];
#pragma unroll
for (i = 0; i < 24; ++i) {
bc[0] = st[keccakf_piln[i]];
st[keccakf_piln[i]] = rotate(t, (ulong)keccakf_rotc[i]);
t = bc[0];
}
//ulong tmp1 = st[0]; ulong tmp2 = st[1]; st[0] = bitselect(st[0] ^ st[2], st[0], st[1]); st[1] = bitselect(st[1] ^ st[3], st[1], st[2]); st[2] = bitselect(st[2] ^ st[4], st[2], st[3]); st[3] = bitselect(st[3] ^ tmp1, st[3], st[4]); st[4] = bitselect(st[4] ^ tmp2, st[4], tmp1);
//tmp1 = st[5]; tmp2 = st[6]; st[5] = bitselect(st[5] ^ st[7], st[5], st[6]); st[6] = bitselect(st[6] ^ st[8], st[6], st[7]); st[7] = bitselect(st[7] ^ st[9], st[7], st[8]); st[8] = bitselect(st[8] ^ tmp1, st[8], st[9]); st[9] = bitselect(st[9] ^ tmp2, st[9], tmp1);
//tmp1 = st[10]; tmp2 = st[11]; st[10] = bitselect(st[10] ^ st[12], st[10], st[11]); st[11] = bitselect(st[11] ^ st[13], st[11], st[12]); st[12] = bitselect(st[12] ^ st[14], st[12], st[13]); st[13] = bitselect(st[13] ^ tmp1, st[13], st[14]); st[14] = bitselect(st[14] ^ tmp2, st[14], tmp1);
//tmp1 = st[15]; tmp2 = st[16]; st[15] = bitselect(st[15] ^ st[17], st[15], st[16]); st[16] = bitselect(st[16] ^ st[18], st[16], st[17]); st[17] = bitselect(st[17] ^ st[19], st[17], st[18]); st[18] = bitselect(st[18] ^ tmp1, st[18], st[19]); st[19] = bitselect(st[19] ^ tmp2, st[19], tmp1);
//tmp1 = st[20]; tmp2 = st[21]; st[20] = bitselect(st[20] ^ st[22], st[20], st[21]); st[21] = bitselect(st[21] ^ st[23], st[21], st[22]); st[22] = bitselect(st[22] ^ st[24], st[22], st[23]); st[23] = bitselect(st[23] ^ tmp1, st[23], st[24]); st[24] = bitselect(st[24] ^ tmp2, st[24], tmp1);
#pragma unroll 1
for(int i = 0; i < 25; i += 5)
{
ulong tmp[5];
#pragma unroll 1
for(int x = 0; x < 5; ++x)
tmp[x] = bitselect(st[i + x] ^ st[i + ((x + 2) % 5)], st[i + x], st[i + ((x + 1) % 5)]);
#pragma unroll 1
for(int x = 0; x < 5; ++x) st[i + x] = tmp[x];
}
// Iota
st[0] ^= keccakf_rndc[round];
}
}
)==="
R"===(
void keccakf1600_2(ulong *st)
{
int i, round;
ulong t, bc[5];
#pragma unroll 1
for(round = 0; round < 24; ++round)
{
// Theta
//bc[0] = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20];
//bc[1] = st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21];
//bc[2] = st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22];
//bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
//bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
/*
#pragma unroll
for (i = 0; i < 5; ++i) {
t = bc[(i + 4) % 5] ^ rotate(bc[(i + 1) % 5], 1UL);
st[i ] ^= t;
st[i + 5] ^= t;
st[i + 10] ^= t;
st[i + 15] ^= t;
st[i + 20] ^= t;
}
*/
bc[0] = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20] ^ rotate(st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22], 1UL);
bc[1] = st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21] ^ rotate(st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23], 1UL);
bc[2] = st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22] ^ rotate(st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24], 1UL);
bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23] ^ rotate(st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20], 1UL);
bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24] ^ rotate(st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21], 1UL);
st[0] ^= bc[4];
st[5] ^= bc[4];
st[10] ^= bc[4];
st[15] ^= bc[4];
st[20] ^= bc[4];
st[1] ^= bc[0];
st[6] ^= bc[0];
st[11] ^= bc[0];
st[16] ^= bc[0];
st[21] ^= bc[0];
st[2] ^= bc[1];
st[7] ^= bc[1];
st[12] ^= bc[1];
st[17] ^= bc[1];
st[22] ^= bc[1];
st[3] ^= bc[2];
st[8] ^= bc[2];
st[13] ^= bc[2];
st[18] ^= bc[2];
st[23] ^= bc[2];
st[4] ^= bc[3];
st[9] ^= bc[3];
st[14] ^= bc[3];
st[19] ^= bc[3];
st[24] ^= bc[3];
// Rho Pi
t = st[1];
#pragma unroll
for (i = 0; i < 24; ++i) {
bc[0] = st[keccakf_piln[i]];
st[keccakf_piln[i]] = rotate(t, (ulong)keccakf_rotc[i]);
t = bc[0];
}
/*ulong tmp1 = st[1] ^ bc[0];
st[0] ^= bc[4];
st[1] = rotate(st[6] ^ bc[0], 44UL);
st[6] = rotate(st[9] ^ bc[3], 20UL);
st[9] = rotate(st[22] ^ bc[1], 61UL);
st[22] = rotate(st[14] ^ bc[3], 39UL);
st[14] = rotate(st[20] ^ bc[4], 18UL);
st[20] = rotate(st[2] ^ bc[1], 62UL);
st[2] = rotate(st[12] ^ bc[1], 43UL);
st[12] = rotate(st[13] ^ bc[2], 25UL);
st[13] = rotate(st[19] ^ bc[3], 8UL);
st[19] = rotate(st[23] ^ bc[2], 56UL);
st[23] = rotate(st[15] ^ bc[4], 41UL);
st[15] = rotate(st[4] ^ bc[3], 27UL);
st[4] = rotate(st[24] ^ bc[3], 14UL);
st[24] = rotate(st[21] ^ bc[0], 2UL);
st[21] = rotate(st[8] ^ bc[2], 55UL);
st[8] = rotate(st[16] ^ bc[0], 35UL);
st[16] = rotate(st[5] ^ bc[4], 36UL);
st[5] = rotate(st[3] ^ bc[2], 28UL);
st[3] = rotate(st[18] ^ bc[2], 21UL);
st[18] = rotate(st[17] ^ bc[1], 15UL);
st[17] = rotate(st[11] ^ bc[0], 10UL);
st[11] = rotate(st[7] ^ bc[1], 6UL);
st[7] = rotate(st[10] ^ bc[4], 3UL);
st[10] = rotate(tmp1, 1UL);
*/
//ulong tmp1 = st[0]; ulong tmp2 = st[1]; st[0] = bitselect(st[0] ^ st[2], st[0], st[1]); st[1] = bitselect(st[1] ^ st[3], st[1], st[2]); st[2] = bitselect(st[2] ^ st[4], st[2], st[3]); st[3] = bitselect(st[3] ^ tmp1, st[3], st[4]); st[4] = bitselect(st[4] ^ tmp2, st[4], tmp1);
//tmp1 = st[5]; tmp2 = st[6]; st[5] = bitselect(st[5] ^ st[7], st[5], st[6]); st[6] = bitselect(st[6] ^ st[8], st[6], st[7]); st[7] = bitselect(st[7] ^ st[9], st[7], st[8]); st[8] = bitselect(st[8] ^ tmp1, st[8], st[9]); st[9] = bitselect(st[9] ^ tmp2, st[9], tmp1);
//tmp1 = st[10]; tmp2 = st[11]; st[10] = bitselect(st[10] ^ st[12], st[10], st[11]); st[11] = bitselect(st[11] ^ st[13], st[11], st[12]); st[12] = bitselect(st[12] ^ st[14], st[12], st[13]); st[13] = bitselect(st[13] ^ tmp1, st[13], st[14]); st[14] = bitselect(st[14] ^ tmp2, st[14], tmp1);
//tmp1 = st[15]; tmp2 = st[16]; st[15] = bitselect(st[15] ^ st[17], st[15], st[16]); st[16] = bitselect(st[16] ^ st[18], st[16], st[17]); st[17] = bitselect(st[17] ^ st[19], st[17], st[18]); st[18] = bitselect(st[18] ^ tmp1, st[18], st[19]); st[19] = bitselect(st[19] ^ tmp2, st[19], tmp1);
//tmp1 = st[20]; tmp2 = st[21]; st[20] = bitselect(st[20] ^ st[22], st[20], st[21]); st[21] = bitselect(st[21] ^ st[23], st[21], st[22]); st[22] = bitselect(st[22] ^ st[24], st[22], st[23]); st[23] = bitselect(st[23] ^ tmp1, st[23], st[24]); st[24] = bitselect(st[24] ^ tmp2, st[24], tmp1);
#pragma unroll
for(int i = 0; i < 25; i += 5)
{
ulong tmp1 = st[i], tmp2 = st[i + 1];
st[i] = bitselect(st[i] ^ st[i + 2], st[i], st[i + 1]);
st[i + 1] = bitselect(st[i + 1] ^ st[i + 3], st[i + 1], st[i + 2]);
st[i + 2] = bitselect(st[i + 2] ^ st[i + 4], st[i + 2], st[i + 3]);
st[i + 3] = bitselect(st[i + 3] ^ tmp1, st[i + 3], st[i + 4]);
st[i + 4] = bitselect(st[i + 4] ^ tmp2, st[i + 4], tmp1);
}
// Iota
st[0] ^= keccakf_rndc[round];
}
}
)==="
R"===(
void CNKeccak(ulong *output, ulong *input)
{
ulong st[25];
// Copy 72 bytes
for(int i = 0; i < 9; ++i) st[i] = input[i];
// Last four and '1' bit for padding
//st[9] = as_ulong((uint2)(((uint *)input)[18], 0x00000001U));
st[9] = (input[9] & 0x00000000FFFFFFFFUL) | 0x0000000100000000UL;
for(int i = 10; i < 25; ++i) st[i] = 0x00UL;
// Last bit of padding
st[16] = 0x8000000000000000UL;
keccakf1600_1(st);
for(int i = 0; i < 25; ++i) output[i] = st[i];
}
static const __constant uchar rcon[8] = { 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40 };
#define BYTE(x, y) (amd_bfe((x), (y) << 3U, 8U))
#define SubWord(inw) ((sbox[BYTE(inw, 3)] << 24) | (sbox[BYTE(inw, 2)] << 16) | (sbox[BYTE(inw, 1)] << 8) | sbox[BYTE(inw, 0)])
void AESExpandKey256(uint *keybuf)
{
//#pragma unroll 4
for(uint c = 8, i = 1; c < 60; ++c)
{
// For 256-bit keys, an sbox permutation is done every other 4th uint generated, AND every 8th
uint t = ((!(c & 7)) || ((c & 7) == 4)) ? SubWord(keybuf[c - 1]) : keybuf[c - 1];
// If the uint we're generating has an index that is a multiple of 8, rotate and XOR with the round constant,
// then XOR this with previously generated uint. If it's 4 after a multiple of 8, only the sbox permutation
// is done, followed by the XOR. If neither are true, only the XOR with the previously generated uint is done.
keybuf[c] = keybuf[c - 8] ^ ((!(c & 7)) ? rotate(t, 24U) ^ as_uint((uchar4)(rcon[i++], 0U, 0U, 0U)) : t);
}
}
#define IDX(x) (x)
__attribute__((reqd_work_group_size(WORKSIZE, 8, 1)))
__kernel void cn0(__global ulong *input, __global uint4 *Scratchpad, __global ulong *states)
{
ulong State[25];
uint ExpandedKey1[256];
__local uint AES0[256], AES1[256], AES2[256], AES3[256];
uint4 text;
states += (25 * (get_global_id(0) - get_global_offset(0)));
Scratchpad += ((get_global_id(0) - get_global_offset(0))) * (0x80000 >> 2);
for(int i = get_local_id(0); i < 256; i += WORKSIZE)
{
const uint tmp = AES0_C[i];
AES0[i] = tmp;
AES1[i] = rotate(tmp, 8U);
AES2[i] = rotate(tmp, 16U);
AES3[i] = rotate(tmp, 24U);
}
barrier(CLK_LOCAL_MEM_FENCE);
((ulong8 *)State)[0] = vload8(0, input);
State[8] = input[8];
State[9] = input[9];
State[10] = input[10];
((uint *)State)[9] &= 0x00FFFFFFU;
((uint *)State)[9] |= ((get_global_id(0)) & 0xFF) << 24;
((uint *)State)[10] &= 0xFF000000U;
((uint *)State)[10] |= ((get_global_id(0) >> 8));
for(int i = 11; i < 25; ++i) State[i] = 0x00UL;
// Last bit of padding
State[16] = 0x8000000000000000UL;
keccakf1600_2(State);
mem_fence(CLK_GLOBAL_MEM_FENCE);
#pragma unroll
for(int i = 0; i < 25; ++i) states[i] = State[i];
text = vload4(get_local_id(1) + 4, (__global uint *)(states));
#pragma unroll
for(int i = 0; i < 4; ++i) ((ulong *)ExpandedKey1)[i] = states[i];
AESExpandKey256(ExpandedKey1);
mem_fence(CLK_LOCAL_MEM_FENCE);
#pragma unroll 2
for(int i = 0; i < 0x4000; ++i)
{
#pragma unroll
for(int j = 0; j < 10; ++j)
text = AES_Round(AES0, AES1, AES2, AES3, text, ((uint4 *)ExpandedKey1)[j]);
Scratchpad[IDX((i << 3) + get_local_id(1))] = text;
}
mem_fence(CLK_GLOBAL_MEM_FENCE);
}
__attribute__((reqd_work_group_size(WORKSIZE, 1, 1)))
__kernel void cn1(__global uint4 *Scratchpad, __global ulong *states)
{
ulong a[2], b[2];
__local uint AES0[256], AES1[256], AES2[256], AES3[256];
Scratchpad += ((get_global_id(0) - get_global_offset(0))) * (0x80000 >> 2);
states += (25 * (get_global_id(0) - get_global_offset(0)));
for(int i = get_local_id(0); i < 256; i += WORKSIZE)
{
const uint tmp = AES0_C[i];
AES0[i] = tmp;
AES1[i] = rotate(tmp, 8U);
AES2[i] = rotate(tmp, 16U);
AES3[i] = rotate(tmp, 24U);
}
barrier(CLK_LOCAL_MEM_FENCE);
a[0] = states[0] ^ states[4];
b[0] = states[2] ^ states[6];
a[1] = states[1] ^ states[5];
b[1] = states[3] ^ states[7];
uint4 b_x = ((uint4 *)b)[0];
mem_fence(CLK_LOCAL_MEM_FENCE);
#pragma unroll 8
for(int i = 0; i < 0x80000; ++i)
{
ulong c[2];
((uint4 *)c)[0] = Scratchpad[IDX((a[0] & 0x1FFFF0) >> 4)];
((uint4 *)c)[0] = AES_Round(AES0, AES1, AES2, AES3, ((uint4 *)c)[0], ((uint4 *)a)[0]);
//b_x ^= ((uint4 *)c)[0];
Scratchpad[IDX((a[0] & 0x1FFFF0) >> 4)] = b_x ^ ((uint4 *)c)[0];
uint4 tmp;
tmp = Scratchpad[IDX((c[0] & 0x1FFFF0) >> 4)];
a[1] += c[0] * as_ulong2(tmp).s0;
a[0] += mul_hi(c[0], as_ulong2(tmp).s0);
Scratchpad[IDX((c[0] & 0x1FFFF0) >> 4)] = ((uint4 *)a)[0];
((uint4 *)a)[0] ^= tmp;
b_x = ((uint4 *)c)[0];
}
mem_fence(CLK_GLOBAL_MEM_FENCE);
}
__attribute__((reqd_work_group_size(WORKSIZE, 8, 1)))
__kernel void cn2(__global uint4 *Scratchpad, __global ulong *states, __global uint *Branch0, __global uint *Branch1, __global uint *Branch2, __global uint *Branch3)
{
__local uint AES0[256], AES1[256], AES2[256], AES3[256];
uint ExpandedKey2[256];
ulong State[25];
uint4 text;
Scratchpad += ((get_global_id(0) - get_global_offset(0))) * (0x80000 >> 2);
states += (25 * (get_global_id(0) - get_global_offset(0)));
for(int i = get_local_id(0); i < 256; i += WORKSIZE)
{
const uint tmp = AES0_C[i];
AES0[i] = tmp;
AES1[i] = rotate(tmp, 8U);
AES2[i] = rotate(tmp, 16U);
AES3[i] = rotate(tmp, 24U);
}
barrier(CLK_LOCAL_MEM_FENCE);
#if defined(__Tahiti__) || defined(__Pitcairn__)
for(int i = 0; i < 4; ++i) ((ulong *)ExpandedKey2)[i] = states[i + 4];
text = vload4(get_local_id(1) + 4, (__global uint *)states);
#else
text = vload4(get_local_id(1) + 4, (__global uint *)states);
((uint8 *)ExpandedKey2)[0] = vload8(1, (__global uint *)states);
#endif
AESExpandKey256(ExpandedKey2);
barrier(CLK_LOCAL_MEM_FENCE);
#pragma unroll 2
for(int i = 0; i < 0x4000; ++i)
{
text ^= Scratchpad[IDX((i << 3) + get_local_id(1))];
#pragma unroll
for(int j = 0; j < 10; ++j)
text = AES_Round(AES0, AES1, AES2, AES3, text, ((uint4 *)ExpandedKey2)[j]);
}
vstore2(as_ulong2(text), get_local_id(1) + 4, states);
barrier(CLK_GLOBAL_MEM_FENCE);
if(!get_local_id(1))
{
for(int i = 0; i < 25; ++i) State[i] = states[i];
keccakf1600_2(State);
for(int i = 0; i < 25; ++i) states[i] = State[i];
switch(State[0] & 3)
{
case 0:
Branch0[atomic_inc(Branch0 + get_global_size(0))] = get_global_id(0) - get_global_offset(0);
break;
case 1:
Branch1[atomic_inc(Branch1 + get_global_size(0))] = get_global_id(0) - get_global_offset(0);
break;
case 2:
Branch2[atomic_inc(Branch2 + get_global_size(0))] = get_global_id(0) - get_global_offset(0);
break;
case 3:
Branch3[atomic_inc(Branch3 + get_global_size(0))] = get_global_id(0) - get_global_offset(0);
break;
}
}
mem_fence(CLK_GLOBAL_MEM_FENCE);
}
)==="
R"===(
#define VSWAP8(x) (((x) >> 56) | (((x) >> 40) & 0x000000000000FF00UL) | (((x) >> 24) & 0x0000000000FF0000UL) \
| (((x) >> 8) & 0x00000000FF000000UL) | (((x) << 8) & 0x000000FF00000000UL) \
| (((x) << 24) & 0x0000FF0000000000UL) | (((x) << 40) & 0x00FF000000000000UL) | (((x) << 56) & 0xFF00000000000000UL))
#define VSWAP4(x) ((((x) >> 24) & 0xFFU) | (((x) >> 8) & 0xFF00U) | (((x) << 8) & 0xFF0000U) | (((x) << 24) & 0xFF000000U))
__kernel void Skein(__global ulong *states, __global uint *BranchBuf, __global uint *output, uint Target, ulong Threads)
{
const ulong idx = get_global_id(0) - get_global_offset(0);
if(idx >= Threads) return;
states += 25 * BranchBuf[idx];
// skein
ulong8 h = vload8(0, SKEIN512_256_IV);
// Type field begins with final bit, first bit, then six bits of type; the last 96
// bits are input processed (including in the block to be processed with that tweak)
// The output transform is only one run of UBI, since we need only 256 bits of output
// The tweak for the output transform is Type = Output with the Final bit set
// T[0] for the output is 8, and I don't know why - should be message size...
ulong t[3] = { 0x00UL, 0x7000000000000000UL, 0x00UL };
ulong8 p, m;
for(uint i = 0; i < 4; ++i)
{
if(i < 3) t[0] += 0x40UL;
else t[0] += 0x08UL;
t[2] = t[0] ^ t[1];
m = (i < 3) ? vload8(i, states) : (ulong8)(states[24], 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
const ulong h8 = h.s0 ^ h.s1 ^ h.s2 ^ h.s3 ^ h.s4 ^ h.s5 ^ h.s6 ^ h.s7 ^ SKEIN_KS_PARITY;
p = Skein512Block(m, h, h8, t);
h = m ^ p;
if(i < 2) t[1] = 0x3000000000000000UL;
else t[1] = 0xB000000000000000UL;
}
t[0] = 0x08UL;
t[1] = 0xFF00000000000000UL;
t[2] = t[0] ^ t[1];
p = (ulong8)(0);
const ulong h8 = h.s0 ^ h.s1 ^ h.s2 ^ h.s3 ^ h.s4 ^ h.s5 ^ h.s6 ^ h.s7 ^ SKEIN_KS_PARITY;
p = Skein512Block(p, h, h8, t);
//vstore8(p, 0, output);
if(as_uint16(p).s7 <= Target) output[atomic_inc(output + 0xFF)] = BranchBuf[idx] + get_global_offset(0);
mem_fence(CLK_GLOBAL_MEM_FENCE);
}
#define SWAP8(x) as_ulong(as_uchar8(x).s76543210)
__kernel void JH(__global ulong *states, __global uint *BranchBuf, __global uint *output, uint Target, ulong Threads)
{
const uint idx = get_global_id(0) - get_global_offset(0);
if(idx >= Threads) return;
states += 25 * BranchBuf[idx];
sph_u64 h0h = 0xEBD3202C41A398EBUL, h0l = 0xC145B29C7BBECD92UL, h1h = 0xFAC7D4609151931CUL, h1l = 0x038A507ED6820026UL, h2h = 0x45B92677269E23A4UL, h2l = 0x77941AD4481AFBE0UL, h3h = 0x7A176B0226ABB5CDUL, h3l = 0xA82FFF0F4224F056UL;
sph_u64 h4h = 0x754D2E7F8996A371UL, h4l = 0x62E27DF70849141DUL, h5h = 0x948F2476F7957627UL, h5l = 0x6C29804757B6D587UL, h6h = 0x6C0D8EAC2D275E5CUL, h6l = 0x0F7A0557C6508451UL, h7h = 0xEA12247067D3E47BUL, h7l = 0x69D71CD313ABE389UL;
sph_u64 tmp;
for(int i = 0; i < 5; ++i)
{
ulong input[8];
if(i < 3)
{
for(int x = 0; x < 8; ++x) input[x] = (states[(i << 3) + x]);
}
else if(i == 3)
{
input[0] = (states[24]);
input[1] = 0x80UL;
for(int x = 2; x < 8; ++x) input[x] = 0x00UL;
}
else
{
input[7] = 0x4006000000000000UL;
for(int x = 0; x < 7; ++x) input[x] = 0x00UL;
}
h0h ^= input[0];
h0l ^= input[1];
h1h ^= input[2];
h1l ^= input[3];
h2h ^= input[4];
h2l ^= input[5];
h3h ^= input[6];
h3l ^= input[7];
E8;
h4h ^= input[0];
h4l ^= input[1];
h5h ^= input[2];
h5l ^= input[3];
h6h ^= input[4];
h6l ^= input[5];
h7h ^= input[6];
h7l ^= input[7];
}
//output[0] = h6h;
//output[1] = h6l;
//output[2] = h7h;
//output[3] = h7l;
if(as_uint2(h7l).s1 <= Target) output[atomic_inc(output + 0xFF)] = BranchBuf[idx] + get_global_offset(0);
}
#define SWAP4(x) as_uint(as_uchar4(x).s3210)
__kernel void Blake(__global ulong *states, __global uint *BranchBuf, __global uint *output, uint Target, ulong Threads)
{
const uint idx = get_global_id(0) - get_global_offset(0);
if(idx >= Threads) return;
states += 25 * BranchBuf[idx];
unsigned int m[16];
unsigned int v[16];
uint h[8];
((uint8 *)h)[0] = vload8(0U, c_IV256);
for(uint i = 0, bitlen = 0; i < 4; ++i)
{
if(i < 3)
{
((uint16 *)m)[0] = vload16(i, (__global uint *)states);
for(int i = 0; i < 16; ++i) m[i] = SWAP4(m[i]);
bitlen += 512;
}
else
{
m[0] = SWAP4(((__global uint *)states)[48]);
m[1] = SWAP4(((__global uint *)states)[49]);
m[2] = 0x80000000U;
for(int i = 3; i < 13; ++i) m[i] = 0x00U;
m[13] = 1U;
m[14] = 0U;
m[15] = 0x640;
bitlen += 64;
}
((uint16 *)v)[0].lo = ((uint8 *)h)[0];
((uint16 *)v)[0].hi = vload8(0U, c_u256);
//v[12] ^= (i < 3) ? (i + 1) << 9 : 1600U;
//v[13] ^= (i < 3) ? (i + 1) << 9 : 1600U;
v[12] ^= bitlen;
v[13] ^= bitlen;
for(int r = 0; r < 14; r++)
{
GS(0, 4, 0x8, 0xC, 0x0);
GS(1, 5, 0x9, 0xD, 0x2);
GS(2, 6, 0xA, 0xE, 0x4);
GS(3, 7, 0xB, 0xF, 0x6);
GS(0, 5, 0xA, 0xF, 0x8);
GS(1, 6, 0xB, 0xC, 0xA);
GS(2, 7, 0x8, 0xD, 0xC);
GS(3, 4, 0x9, 0xE, 0xE);
}
((uint8 *)h)[0] ^= ((uint8 *)v)[0] ^ ((uint8 *)v)[1];
}
for(int i = 0; i < 8; ++i) h[i] = SWAP4(h[i]);
//for(int i = 0; i < 4; ++i) output[i] = ((ulong *)h)[i];
if(h[7] <= Target) output[atomic_inc(output + 0xFF)] = BranchBuf[idx] + get_global_offset(0);
}
__kernel void Groestl(__global ulong *states, __global uint *BranchBuf, __global uint *output, uint Target, ulong Threads)
{
const uint idx = get_global_id(0) - get_global_offset(0);
if(idx >= Threads) return;
states += 25 * BranchBuf[idx];
ulong State[8];
for(int i = 0; i < 7; ++i) State[i] = 0UL;
State[7] = 0x0001000000000000UL;
for(uint i = 0; i < 4; ++i)
{
ulong H[8], M[8];
if(i < 3)
{
((ulong8 *)M)[0] = vload8(i, states);
}
else
{
M[0] = states[24];
M[1] = 0x80UL;
for(int x = 2; x < 7; ++x) M[x] = 0UL;
M[7] = 0x0400000000000000UL;
}
for(int x = 0; x < 8; ++x) H[x] = M[x] ^ State[x];
PERM_SMALL_P(H);
PERM_SMALL_Q(M);
for(int x = 0; x < 8; ++x) State[x] ^= H[x] ^ M[x];
}
ulong tmp[8];
for(int i = 0; i < 8; ++i) tmp[i] = State[i];
PERM_SMALL_P(State);
for(int i = 0; i < 8; ++i) State[i] ^= tmp[i];
//for(int i = 0; i < 4; ++i) output[i] = State[i + 4];
if(as_uint2(State[7]).s1 <= Target) output[atomic_inc(output + 0xFF)] = BranchBuf[idx] + get_global_offset(0);
}
)==="
@@ -0,0 +1,295 @@
R"===(
/* $Id: groestl.c 260 2011-07-21 01:02:38Z tp $ */
/*
* Groestl256
*
* ==========================(LICENSE BEGIN)============================
* Copyright (c) 2014 djm34
* Copyright (c) 2007-2010 Projet RNRT SAPHIR
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* ===========================(LICENSE END)=============================
*
* @author Thomas Pornin <thomas.pornin@cryptolog.com>
*/
#define SPH_C64(x) x
#define SPH_ROTL64(x, y) rotate((x), (ulong)(y))
#define C64e(x) ((SPH_C64(x) >> 56) \
| ((SPH_C64(x) >> 40) & SPH_C64(0x000000000000FF00)) \
| ((SPH_C64(x) >> 24) & SPH_C64(0x0000000000FF0000)) \
| ((SPH_C64(x) >> 8) & SPH_C64(0x00000000FF000000)) \
| ((SPH_C64(x) << 8) & SPH_C64(0x000000FF00000000)) \
| ((SPH_C64(x) << 24) & SPH_C64(0x0000FF0000000000)) \
| ((SPH_C64(x) << 40) & SPH_C64(0x00FF000000000000)) \
| ((SPH_C64(x) << 56) & SPH_C64(0xFF00000000000000)))
#define B64_0(x) ((x) & 0xFF)
#define B64_1(x) (((x) >> 8) & 0xFF)
#define B64_2(x) (((x) >> 16) & 0xFF)
#define B64_3(x) (((x) >> 24) & 0xFF)
#define B64_4(x) (((x) >> 32) & 0xFF)
#define B64_5(x) (((x) >> 40) & 0xFF)
#define B64_6(x) (((x) >> 48) & 0xFF)
#define B64_7(x) ((x) >> 56)
#define R64 SPH_ROTL64
#define PC64(j, r) ((sph_u64)((j) + (r)))
#define QC64(j, r) (((sph_u64)(r) << 56) ^ (~((sph_u64)(j) << 56)))
static const __constant ulong T0_G[] =
{
0xc6a597f4a5f432c6UL, 0xf884eb9784976ff8UL, 0xee99c7b099b05eeeUL, 0xf68df78c8d8c7af6UL,
0xff0de5170d17e8ffUL, 0xd6bdb7dcbddc0ad6UL, 0xdeb1a7c8b1c816deUL, 0x915439fc54fc6d91UL,
0x6050c0f050f09060UL, 0x0203040503050702UL, 0xcea987e0a9e02eceUL, 0x567dac877d87d156UL,
0xe719d52b192bcce7UL, 0xb56271a662a613b5UL, 0x4de69a31e6317c4dUL, 0xec9ac3b59ab559ecUL,
0x8f4505cf45cf408fUL, 0x1f9d3ebc9dbca31fUL, 0x894009c040c04989UL, 0xfa87ef92879268faUL,
0xef15c53f153fd0efUL, 0xb2eb7f26eb2694b2UL, 0x8ec90740c940ce8eUL, 0xfb0bed1d0b1de6fbUL,
0x41ec822fec2f6e41UL, 0xb3677da967a91ab3UL, 0x5ffdbe1cfd1c435fUL, 0x45ea8a25ea256045UL,
0x23bf46dabfdaf923UL, 0x53f7a602f7025153UL, 0xe496d3a196a145e4UL, 0x9b5b2ded5bed769bUL,
0x75c2ea5dc25d2875UL, 0xe11cd9241c24c5e1UL, 0x3dae7ae9aee9d43dUL, 0x4c6a98be6abef24cUL,
0x6c5ad8ee5aee826cUL, 0x7e41fcc341c3bd7eUL, 0xf502f1060206f3f5UL, 0x834f1dd14fd15283UL,
0x685cd0e45ce48c68UL, 0x51f4a207f4075651UL, 0xd134b95c345c8dd1UL, 0xf908e9180818e1f9UL,
0xe293dfae93ae4ce2UL, 0xab734d9573953eabUL, 0x6253c4f553f59762UL, 0x2a3f54413f416b2aUL,
0x080c10140c141c08UL, 0x955231f652f66395UL, 0x46658caf65afe946UL, 0x9d5e21e25ee27f9dUL,
0x3028607828784830UL, 0x37a16ef8a1f8cf37UL, 0x0a0f14110f111b0aUL, 0x2fb55ec4b5c4eb2fUL,
0x0e091c1b091b150eUL, 0x2436485a365a7e24UL, 0x1b9b36b69bb6ad1bUL, 0xdf3da5473d4798dfUL,
0xcd26816a266aa7cdUL, 0x4e699cbb69bbf54eUL, 0x7fcdfe4ccd4c337fUL, 0xea9fcfba9fba50eaUL,
0x121b242d1b2d3f12UL, 0x1d9e3ab99eb9a41dUL, 0x5874b09c749cc458UL, 0x342e68722e724634UL,
0x362d6c772d774136UL, 0xdcb2a3cdb2cd11dcUL, 0xb4ee7329ee299db4UL, 0x5bfbb616fb164d5bUL,
0xa4f65301f601a5a4UL, 0x764decd74dd7a176UL, 0xb76175a361a314b7UL, 0x7dcefa49ce49347dUL,
0x527ba48d7b8ddf52UL, 0xdd3ea1423e429fddUL, 0x5e71bc937193cd5eUL, 0x139726a297a2b113UL,
0xa6f55704f504a2a6UL, 0xb96869b868b801b9UL, 0x0000000000000000UL, 0xc12c99742c74b5c1UL,
0x406080a060a0e040UL, 0xe31fdd211f21c2e3UL, 0x79c8f243c8433a79UL, 0xb6ed772ced2c9ab6UL,
0xd4beb3d9bed90dd4UL, 0x8d4601ca46ca478dUL, 0x67d9ce70d9701767UL, 0x724be4dd4bddaf72UL,
0x94de3379de79ed94UL, 0x98d42b67d467ff98UL, 0xb0e87b23e82393b0UL, 0x854a11de4ade5b85UL,
0xbb6b6dbd6bbd06bbUL, 0xc52a917e2a7ebbc5UL, 0x4fe59e34e5347b4fUL, 0xed16c13a163ad7edUL,
0x86c51754c554d286UL, 0x9ad72f62d762f89aUL, 0x6655ccff55ff9966UL, 0x119422a794a7b611UL,
0x8acf0f4acf4ac08aUL, 0xe910c9301030d9e9UL, 0x0406080a060a0e04UL, 0xfe81e798819866feUL,
0xa0f05b0bf00baba0UL, 0x7844f0cc44ccb478UL, 0x25ba4ad5bad5f025UL, 0x4be3963ee33e754bUL,
0xa2f35f0ef30eaca2UL, 0x5dfeba19fe19445dUL, 0x80c01b5bc05bdb80UL, 0x058a0a858a858005UL,
0x3fad7eecadecd33fUL, 0x21bc42dfbcdffe21UL, 0x7048e0d848d8a870UL, 0xf104f90c040cfdf1UL,
0x63dfc67adf7a1963UL, 0x77c1ee58c1582f77UL, 0xaf75459f759f30afUL, 0x426384a563a5e742UL,
0x2030405030507020UL, 0xe51ad12e1a2ecbe5UL, 0xfd0ee1120e12effdUL, 0xbf6d65b76db708bfUL,
0x814c19d44cd45581UL, 0x1814303c143c2418UL, 0x26354c5f355f7926UL, 0xc32f9d712f71b2c3UL,
0xbee16738e13886beUL, 0x35a26afda2fdc835UL, 0x88cc0b4fcc4fc788UL, 0x2e395c4b394b652eUL,
0x93573df957f96a93UL, 0x55f2aa0df20d5855UL, 0xfc82e39d829d61fcUL, 0x7a47f4c947c9b37aUL,
0xc8ac8befacef27c8UL, 0xbae76f32e73288baUL, 0x322b647d2b7d4f32UL, 0xe695d7a495a442e6UL,
0xc0a09bfba0fb3bc0UL, 0x199832b398b3aa19UL, 0x9ed12768d168f69eUL, 0xa37f5d817f8122a3UL,
0x446688aa66aaee44UL, 0x547ea8827e82d654UL, 0x3bab76e6abe6dd3bUL, 0x0b83169e839e950bUL,
0x8cca0345ca45c98cUL, 0xc729957b297bbcc7UL, 0x6bd3d66ed36e056bUL, 0x283c50443c446c28UL,
0xa779558b798b2ca7UL, 0xbce2633de23d81bcUL, 0x161d2c271d273116UL, 0xad76419a769a37adUL,
0xdb3bad4d3b4d96dbUL, 0x6456c8fa56fa9e64UL, 0x744ee8d24ed2a674UL, 0x141e28221e223614UL,
0x92db3f76db76e492UL, 0x0c0a181e0a1e120cUL, 0x486c90b46cb4fc48UL, 0xb8e46b37e4378fb8UL,
0x9f5d25e75de7789fUL, 0xbd6e61b26eb20fbdUL, 0x43ef862aef2a6943UL, 0xc4a693f1a6f135c4UL,
0x39a872e3a8e3da39UL, 0x31a462f7a4f7c631UL, 0xd337bd5937598ad3UL, 0xf28bff868b8674f2UL,
0xd532b156325683d5UL, 0x8b430dc543c54e8bUL, 0x6e59dceb59eb856eUL, 0xdab7afc2b7c218daUL,
0x018c028f8c8f8e01UL, 0xb16479ac64ac1db1UL, 0x9cd2236dd26df19cUL, 0x49e0923be03b7249UL,
0xd8b4abc7b4c71fd8UL, 0xacfa4315fa15b9acUL, 0xf307fd090709faf3UL, 0xcf25856f256fa0cfUL,
0xcaaf8feaafea20caUL, 0xf48ef3898e897df4UL, 0x47e98e20e9206747UL, 0x1018202818283810UL,
0x6fd5de64d5640b6fUL, 0xf088fb83888373f0UL, 0x4a6f94b16fb1fb4aUL, 0x5c72b8967296ca5cUL,
0x3824706c246c5438UL, 0x57f1ae08f1085f57UL, 0x73c7e652c7522173UL, 0x975135f351f36497UL,
0xcb238d652365aecbUL, 0xa17c59847c8425a1UL, 0xe89ccbbf9cbf57e8UL, 0x3e217c6321635d3eUL,
0x96dd377cdd7cea96UL, 0x61dcc27fdc7f1e61UL, 0x0d861a9186919c0dUL, 0x0f851e9485949b0fUL,
0xe090dbab90ab4be0UL, 0x7c42f8c642c6ba7cUL, 0x71c4e257c4572671UL, 0xccaa83e5aae529ccUL,
0x90d83b73d873e390UL, 0x06050c0f050f0906UL, 0xf701f5030103f4f7UL, 0x1c12383612362a1cUL,
0xc2a39ffea3fe3cc2UL, 0x6a5fd4e15fe18b6aUL, 0xaef94710f910beaeUL, 0x69d0d26bd06b0269UL,
0x17912ea891a8bf17UL, 0x995829e858e87199UL, 0x3a2774692769533aUL, 0x27b94ed0b9d0f727UL,
0xd938a948384891d9UL, 0xeb13cd351335deebUL, 0x2bb356ceb3cee52bUL, 0x2233445533557722UL,
0xd2bbbfd6bbd604d2UL, 0xa9704990709039a9UL, 0x07890e8089808707UL, 0x33a766f2a7f2c133UL,
0x2db65ac1b6c1ec2dUL, 0x3c22786622665a3cUL, 0x15922aad92adb815UL, 0xc92089602060a9c9UL,
0x874915db49db5c87UL, 0xaaff4f1aff1ab0aaUL, 0x5078a0887888d850UL, 0xa57a518e7a8e2ba5UL,
0x038f068a8f8a8903UL, 0x59f8b213f8134a59UL, 0x0980129b809b9209UL, 0x1a1734391739231aUL,
0x65daca75da751065UL, 0xd731b553315384d7UL, 0x84c61351c651d584UL, 0xd0b8bbd3b8d303d0UL,
0x82c31f5ec35edc82UL, 0x29b052cbb0cbe229UL, 0x5a77b4997799c35aUL, 0x1e113c3311332d1eUL,
0x7bcbf646cb463d7bUL, 0xa8fc4b1ffc1fb7a8UL, 0x6dd6da61d6610c6dUL, 0x2c3a584e3a4e622cUL
};
)==="
R"===(
static const __constant ulong T4_G[] =
{
0xA5F432C6C6A597F4UL, 0x84976FF8F884EB97UL, 0x99B05EEEEE99C7B0UL, 0x8D8C7AF6F68DF78CUL,
0x0D17E8FFFF0DE517UL, 0xBDDC0AD6D6BDB7DCUL, 0xB1C816DEDEB1A7C8UL, 0x54FC6D91915439FCUL,
0x50F090606050C0F0UL, 0x0305070202030405UL, 0xA9E02ECECEA987E0UL, 0x7D87D156567DAC87UL,
0x192BCCE7E719D52BUL, 0x62A613B5B56271A6UL, 0xE6317C4D4DE69A31UL, 0x9AB559ECEC9AC3B5UL,
0x45CF408F8F4505CFUL, 0x9DBCA31F1F9D3EBCUL, 0x40C04989894009C0UL, 0x879268FAFA87EF92UL,
0x153FD0EFEF15C53FUL, 0xEB2694B2B2EB7F26UL, 0xC940CE8E8EC90740UL, 0x0B1DE6FBFB0BED1DUL,
0xEC2F6E4141EC822FUL, 0x67A91AB3B3677DA9UL, 0xFD1C435F5FFDBE1CUL, 0xEA25604545EA8A25UL,
0xBFDAF92323BF46DAUL, 0xF702515353F7A602UL, 0x96A145E4E496D3A1UL, 0x5BED769B9B5B2DEDUL,
0xC25D287575C2EA5DUL, 0x1C24C5E1E11CD924UL, 0xAEE9D43D3DAE7AE9UL, 0x6ABEF24C4C6A98BEUL,
0x5AEE826C6C5AD8EEUL, 0x41C3BD7E7E41FCC3UL, 0x0206F3F5F502F106UL, 0x4FD15283834F1DD1UL,
0x5CE48C68685CD0E4UL, 0xF407565151F4A207UL, 0x345C8DD1D134B95CUL, 0x0818E1F9F908E918UL,
0x93AE4CE2E293DFAEUL, 0x73953EABAB734D95UL, 0x53F597626253C4F5UL, 0x3F416B2A2A3F5441UL,
0x0C141C08080C1014UL, 0x52F66395955231F6UL, 0x65AFE94646658CAFUL, 0x5EE27F9D9D5E21E2UL,
0x2878483030286078UL, 0xA1F8CF3737A16EF8UL, 0x0F111B0A0A0F1411UL, 0xB5C4EB2F2FB55EC4UL,
0x091B150E0E091C1BUL, 0x365A7E242436485AUL, 0x9BB6AD1B1B9B36B6UL, 0x3D4798DFDF3DA547UL,
0x266AA7CDCD26816AUL, 0x69BBF54E4E699CBBUL, 0xCD4C337F7FCDFE4CUL, 0x9FBA50EAEA9FCFBAUL,
0x1B2D3F12121B242DUL, 0x9EB9A41D1D9E3AB9UL, 0x749CC4585874B09CUL, 0x2E724634342E6872UL,
0x2D774136362D6C77UL, 0xB2CD11DCDCB2A3CDUL, 0xEE299DB4B4EE7329UL, 0xFB164D5B5BFBB616UL,
0xF601A5A4A4F65301UL, 0x4DD7A176764DECD7UL, 0x61A314B7B76175A3UL, 0xCE49347D7DCEFA49UL,
0x7B8DDF52527BA48DUL, 0x3E429FDDDD3EA142UL, 0x7193CD5E5E71BC93UL, 0x97A2B113139726A2UL,
0xF504A2A6A6F55704UL, 0x68B801B9B96869B8UL, 0x0000000000000000UL, 0x2C74B5C1C12C9974UL,
0x60A0E040406080A0UL, 0x1F21C2E3E31FDD21UL, 0xC8433A7979C8F243UL, 0xED2C9AB6B6ED772CUL,
0xBED90DD4D4BEB3D9UL, 0x46CA478D8D4601CAUL, 0xD970176767D9CE70UL, 0x4BDDAF72724BE4DDUL,
0xDE79ED9494DE3379UL, 0xD467FF9898D42B67UL, 0xE82393B0B0E87B23UL, 0x4ADE5B85854A11DEUL,
0x6BBD06BBBB6B6DBDUL, 0x2A7EBBC5C52A917EUL, 0xE5347B4F4FE59E34UL, 0x163AD7EDED16C13AUL,
0xC554D28686C51754UL, 0xD762F89A9AD72F62UL, 0x55FF99666655CCFFUL, 0x94A7B611119422A7UL,
0xCF4AC08A8ACF0F4AUL, 0x1030D9E9E910C930UL, 0x060A0E040406080AUL, 0x819866FEFE81E798UL,
0xF00BABA0A0F05B0BUL, 0x44CCB4787844F0CCUL, 0xBAD5F02525BA4AD5UL, 0xE33E754B4BE3963EUL,
0xF30EACA2A2F35F0EUL, 0xFE19445D5DFEBA19UL, 0xC05BDB8080C01B5BUL, 0x8A858005058A0A85UL,
0xADECD33F3FAD7EECUL, 0xBCDFFE2121BC42DFUL, 0x48D8A8707048E0D8UL, 0x040CFDF1F104F90CUL,
0xDF7A196363DFC67AUL, 0xC1582F7777C1EE58UL, 0x759F30AFAF75459FUL, 0x63A5E742426384A5UL,
0x3050702020304050UL, 0x1A2ECBE5E51AD12EUL, 0x0E12EFFDFD0EE112UL, 0x6DB708BFBF6D65B7UL,
0x4CD45581814C19D4UL, 0x143C24181814303CUL, 0x355F792626354C5FUL, 0x2F71B2C3C32F9D71UL,
0xE13886BEBEE16738UL, 0xA2FDC83535A26AFDUL, 0xCC4FC78888CC0B4FUL, 0x394B652E2E395C4BUL,
0x57F96A9393573DF9UL, 0xF20D585555F2AA0DUL, 0x829D61FCFC82E39DUL, 0x47C9B37A7A47F4C9UL,
0xACEF27C8C8AC8BEFUL, 0xE73288BABAE76F32UL, 0x2B7D4F32322B647DUL, 0x95A442E6E695D7A4UL,
0xA0FB3BC0C0A09BFBUL, 0x98B3AA19199832B3UL, 0xD168F69E9ED12768UL, 0x7F8122A3A37F5D81UL,
0x66AAEE44446688AAUL, 0x7E82D654547EA882UL, 0xABE6DD3B3BAB76E6UL, 0x839E950B0B83169EUL,
0xCA45C98C8CCA0345UL, 0x297BBCC7C729957BUL, 0xD36E056B6BD3D66EUL, 0x3C446C28283C5044UL,
0x798B2CA7A779558BUL, 0xE23D81BCBCE2633DUL, 0x1D273116161D2C27UL, 0x769A37ADAD76419AUL,
0x3B4D96DBDB3BAD4DUL, 0x56FA9E646456C8FAUL, 0x4ED2A674744EE8D2UL, 0x1E223614141E2822UL,
0xDB76E49292DB3F76UL, 0x0A1E120C0C0A181EUL, 0x6CB4FC48486C90B4UL, 0xE4378FB8B8E46B37UL,
0x5DE7789F9F5D25E7UL, 0x6EB20FBDBD6E61B2UL, 0xEF2A694343EF862AUL, 0xA6F135C4C4A693F1UL,
0xA8E3DA3939A872E3UL, 0xA4F7C63131A462F7UL, 0x37598AD3D337BD59UL, 0x8B8674F2F28BFF86UL,
0x325683D5D532B156UL, 0x43C54E8B8B430DC5UL, 0x59EB856E6E59DCEBUL, 0xB7C218DADAB7AFC2UL,
0x8C8F8E01018C028FUL, 0x64AC1DB1B16479ACUL, 0xD26DF19C9CD2236DUL, 0xE03B724949E0923BUL,
0xB4C71FD8D8B4ABC7UL, 0xFA15B9ACACFA4315UL, 0x0709FAF3F307FD09UL, 0x256FA0CFCF25856FUL,
0xAFEA20CACAAF8FEAUL, 0x8E897DF4F48EF389UL, 0xE920674747E98E20UL, 0x1828381010182028UL,
0xD5640B6F6FD5DE64UL, 0x888373F0F088FB83UL, 0x6FB1FB4A4A6F94B1UL, 0x7296CA5C5C72B896UL,
0x246C54383824706CUL, 0xF1085F5757F1AE08UL, 0xC752217373C7E652UL, 0x51F36497975135F3UL,
0x2365AECBCB238D65UL, 0x7C8425A1A17C5984UL, 0x9CBF57E8E89CCBBFUL, 0x21635D3E3E217C63UL,
0xDD7CEA9696DD377CUL, 0xDC7F1E6161DCC27FUL, 0x86919C0D0D861A91UL, 0x85949B0F0F851E94UL,
0x90AB4BE0E090DBABUL, 0x42C6BA7C7C42F8C6UL, 0xC457267171C4E257UL, 0xAAE529CCCCAA83E5UL,
0xD873E39090D83B73UL, 0x050F090606050C0FUL, 0x0103F4F7F701F503UL, 0x12362A1C1C123836UL,
0xA3FE3CC2C2A39FFEUL, 0x5FE18B6A6A5FD4E1UL, 0xF910BEAEAEF94710UL, 0xD06B026969D0D26BUL,
0x91A8BF1717912EA8UL, 0x58E87199995829E8UL, 0x2769533A3A277469UL, 0xB9D0F72727B94ED0UL,
0x384891D9D938A948UL, 0x1335DEEBEB13CD35UL, 0xB3CEE52B2BB356CEUL, 0x3355772222334455UL,
0xBBD604D2D2BBBFD6UL, 0x709039A9A9704990UL, 0x8980870707890E80UL, 0xA7F2C13333A766F2UL,
0xB6C1EC2D2DB65AC1UL, 0x22665A3C3C227866UL, 0x92ADB81515922AADUL, 0x2060A9C9C9208960UL,
0x49DB5C87874915DBUL, 0xFF1AB0AAAAFF4F1AUL, 0x7888D8505078A088UL, 0x7A8E2BA5A57A518EUL,
0x8F8A8903038F068AUL, 0xF8134A5959F8B213UL, 0x809B92090980129BUL, 0x1739231A1A173439UL,
0xDA75106565DACA75UL, 0x315384D7D731B553UL, 0xC651D58484C61351UL, 0xB8D303D0D0B8BBD3UL,
0xC35EDC8282C31F5EUL, 0xB0CBE22929B052CBUL, 0x7799C35A5A77B499UL, 0x11332D1E1E113C33UL,
0xCB463D7B7BCBF646UL, 0xFC1FB7A8A8FC4B1FUL, 0xD6610C6D6DD6DA61UL, 0x3A4E622C2C3A584EUL
};
#define RSTT(d, a, b0, b1, b2, b3, b4, b5, b6, b7) do { \
t[d] = T0_G[B64_0(a[b0])] \
^ R64(T0_G[B64_1(a[b1])], 8) \
^ R64(T0_G[B64_2(a[b2])], 16) \
^ R64(T0_G[B64_3(a[b3])], 24) \
^ T4_G[B64_4(a[b4])] \
^ R64(T4_G[B64_5(a[b5])], 8) \
^ R64(T4_G[B64_6(a[b6])], 16) \
^ R64(T4_G[B64_7(a[b7])], 24); \
} while (0)
#define ROUND_SMALL_P(a, r) do { \
ulong t[8]; \
a[0] ^= PC64(0x00, r); \
a[1] ^= PC64(0x10, r); \
a[2] ^= PC64(0x20, r); \
a[3] ^= PC64(0x30, r); \
a[4] ^= PC64(0x40, r); \
a[5] ^= PC64(0x50, r); \
a[6] ^= PC64(0x60, r); \
a[7] ^= PC64(0x70, r); \
RSTT(0, a, 0, 1, 2, 3, 4, 5, 6, 7); \
RSTT(1, a, 1, 2, 3, 4, 5, 6, 7, 0); \
RSTT(2, a, 2, 3, 4, 5, 6, 7, 0, 1); \
RSTT(3, a, 3, 4, 5, 6, 7, 0, 1, 2); \
RSTT(4, a, 4, 5, 6, 7, 0, 1, 2, 3); \
RSTT(5, a, 5, 6, 7, 0, 1, 2, 3, 4); \
RSTT(6, a, 6, 7, 0, 1, 2, 3, 4, 5); \
RSTT(7, a, 7, 0, 1, 2, 3, 4, 5, 6); \
a[0] = t[0]; \
a[1] = t[1]; \
a[2] = t[2]; \
a[3] = t[3]; \
a[4] = t[4]; \
a[5] = t[5]; \
a[6] = t[6]; \
a[7] = t[7]; \
} while (0)
#define ROUND_SMALL_Pf(a,r) do { \
a[0] ^= PC64(0x00, r); \
a[1] ^= PC64(0x10, r); \
a[2] ^= PC64(0x20, r); \
a[3] ^= PC64(0x30, r); \
a[4] ^= PC64(0x40, r); \
a[5] ^= PC64(0x50, r); \
a[6] ^= PC64(0x60, r); \
a[7] ^= PC64(0x70, r); \
RSTT(7, a, 7, 0, 1, 2, 3, 4, 5, 6); \
a[7] = t[7]; \
} while (0)
#define ROUND_SMALL_Q(a, r) do { \
ulong t[8]; \
a[0] ^= QC64(0x00, r); \
a[1] ^= QC64(0x10, r); \
a[2] ^= QC64(0x20, r); \
a[3] ^= QC64(0x30, r); \
a[4] ^= QC64(0x40, r); \
a[5] ^= QC64(0x50, r); \
a[6] ^= QC64(0x60, r); \
a[7] ^= QC64(0x70, r); \
RSTT(0, a, 1, 3, 5, 7, 0, 2, 4, 6); \
RSTT(1, a, 2, 4, 6, 0, 1, 3, 5, 7); \
RSTT(2, a, 3, 5, 7, 1, 2, 4, 6, 0); \
RSTT(3, a, 4, 6, 0, 2, 3, 5, 7, 1); \
RSTT(4, a, 5, 7, 1, 3, 4, 6, 0, 2); \
RSTT(5, a, 6, 0, 2, 4, 5, 7, 1, 3); \
RSTT(6, a, 7, 1, 3, 5, 6, 0, 2, 4); \
RSTT(7, a, 0, 2, 4, 6, 7, 1, 3, 5); \
a[0] = t[0]; \
a[1] = t[1]; \
a[2] = t[2]; \
a[3] = t[3]; \
a[4] = t[4]; \
a[5] = t[5]; \
a[6] = t[6]; \
a[7] = t[7]; \
} while (0)
#define PERM_SMALL_P(a) do { \
for (int r = 0; r < 10; r ++) \
ROUND_SMALL_P(a, r); \
} while (0)
#define PERM_SMALL_Pf(a) do { \
for (int r = 0; r < 9; r ++) { \
ROUND_SMALL_P(a, r);} \
ROUND_SMALL_Pf(a,9); \
} while (0)
#define PERM_SMALL_Q(a) do { \
for (int r = 0; r < 10; r ++) \
ROUND_SMALL_Q(a, r); \
} while (0)
)==="
+274
View File
@@ -0,0 +1,274 @@
R"===(
/* $Id: jh.c 255 2011-06-07 19:50:20Z tp $ */
/*
* JH implementation.
*
* ==========================(LICENSE BEGIN)============================
*
* Copyright (c) 2007-2010 Projet RNRT SAPHIR
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* ===========================(LICENSE END)=============================
*
* @author Thomas Pornin <thomas.pornin@cryptolog.com>
*/
#define SPH_JH_64 1
#define SPH_LITTLE_ENDIAN 1
#define SPH_C32(x) x
#define SPH_C64(x) x
typedef uint sph_u32;
typedef ulong sph_u64;
/*
* The internal bitslice representation may use either big-endian or
* little-endian (true bitslice operations do not care about the bit
* ordering, and the bit-swapping linear operations in JH happen to
* be invariant through endianness-swapping). The constants must be
* defined according to the chosen endianness; we use some
* byte-swapping macros for that.
*/
#if SPH_LITTLE_ENDIAN
#define C32e(x) ((SPH_C32(x) >> 24) \
| ((SPH_C32(x) >> 8) & SPH_C32(0x0000FF00)) \
| ((SPH_C32(x) << 8) & SPH_C32(0x00FF0000)) \
| ((SPH_C32(x) << 24) & SPH_C32(0xFF000000)))
#define dec32e_aligned sph_dec32le_aligned
#define enc32e sph_enc32le
#define C64e(x) ((SPH_C64(x) >> 56) \
| ((SPH_C64(x) >> 40) & SPH_C64(0x000000000000FF00)) \
| ((SPH_C64(x) >> 24) & SPH_C64(0x0000000000FF0000)) \
| ((SPH_C64(x) >> 8) & SPH_C64(0x00000000FF000000)) \
| ((SPH_C64(x) << 8) & SPH_C64(0x000000FF00000000)) \
| ((SPH_C64(x) << 24) & SPH_C64(0x0000FF0000000000)) \
| ((SPH_C64(x) << 40) & SPH_C64(0x00FF000000000000)) \
| ((SPH_C64(x) << 56) & SPH_C64(0xFF00000000000000)))
#define dec64e_aligned sph_dec64le_aligned
#define enc64e sph_enc64le
#else
#define C32e(x) SPH_C32(x)
#define dec32e_aligned sph_dec32be_aligned
#define enc32e sph_enc32be
#define C64e(x) SPH_C64(x)
#define dec64e_aligned sph_dec64be_aligned
#define enc64e sph_enc64be
#endif
#define Sb(x0, x1, x2, x3, c) do { \
x3 = ~x3; \
x0 ^= (c) & ~x2; \
tmp = (c) ^ (x0 & x1); \
x0 ^= x2 & x3; \
x3 ^= ~x1 & x2; \
x1 ^= x0 & x2; \
x2 ^= x0 & ~x3; \
x0 ^= x1 | x3; \
x3 ^= x1 & x2; \
x1 ^= tmp & x0; \
x2 ^= tmp; \
} while (0)
#define Lb(x0, x1, x2, x3, x4, x5, x6, x7) do { \
x4 ^= x1; \
x5 ^= x2; \
x6 ^= x3 ^ x0; \
x7 ^= x0; \
x0 ^= x5; \
x1 ^= x6; \
x2 ^= x7 ^ x4; \
x3 ^= x4; \
} while (0)
static const __constant ulong C[] =
{
0x67F815DFA2DED572UL, 0x571523B70A15847BUL, 0xF6875A4D90D6AB81UL, 0x402BD1C3C54F9F4EUL,
0x9CFA455CE03A98EAUL, 0x9A99B26699D2C503UL, 0x8A53BBF2B4960266UL, 0x31A2DB881A1456B5UL,
0xDB0E199A5C5AA303UL, 0x1044C1870AB23F40UL, 0x1D959E848019051CUL, 0xDCCDE75EADEB336FUL,
0x416BBF029213BA10UL, 0xD027BBF7156578DCUL, 0x5078AA3739812C0AUL, 0xD3910041D2BF1A3FUL,
0x907ECCF60D5A2D42UL, 0xCE97C0929C9F62DDUL, 0xAC442BC70BA75C18UL, 0x23FCC663D665DFD1UL,
0x1AB8E09E036C6E97UL, 0xA8EC6C447E450521UL, 0xFA618E5DBB03F1EEUL, 0x97818394B29796FDUL,
0x2F3003DB37858E4AUL, 0x956A9FFB2D8D672AUL, 0x6C69B8F88173FE8AUL, 0x14427FC04672C78AUL,
0xC45EC7BD8F15F4C5UL, 0x80BB118FA76F4475UL, 0xBC88E4AEB775DE52UL, 0xF4A3A6981E00B882UL,
0x1563A3A9338FF48EUL, 0x89F9B7D524565FAAUL, 0xFDE05A7C20EDF1B6UL, 0x362C42065AE9CA36UL,
0x3D98FE4E433529CEUL, 0xA74B9A7374F93A53UL, 0x86814E6F591FF5D0UL, 0x9F5AD8AF81AD9D0EUL,
0x6A6234EE670605A7UL, 0x2717B96EBE280B8BUL, 0x3F1080C626077447UL, 0x7B487EC66F7EA0E0UL,
0xC0A4F84AA50A550DUL, 0x9EF18E979FE7E391UL, 0xD48D605081727686UL, 0x62B0E5F3415A9E7EUL,
0x7A205440EC1F9FFCUL, 0x84C9F4CE001AE4E3UL, 0xD895FA9DF594D74FUL, 0xA554C324117E2E55UL,
0x286EFEBD2872DF5BUL, 0xB2C4A50FE27FF578UL, 0x2ED349EEEF7C8905UL, 0x7F5928EB85937E44UL,
0x4A3124B337695F70UL, 0x65E4D61DF128865EUL, 0xE720B95104771BC7UL, 0x8A87D423E843FE74UL,
0xF2947692A3E8297DUL, 0xC1D9309B097ACBDDUL, 0xE01BDC5BFB301B1DUL, 0xBF829CF24F4924DAUL,
0xFFBF70B431BAE7A4UL, 0x48BCF8DE0544320DUL, 0x39D3BB5332FCAE3BUL, 0xA08B29E0C1C39F45UL,
0x0F09AEF7FD05C9E5UL, 0x34F1904212347094UL, 0x95ED44E301B771A2UL, 0x4A982F4F368E3BE9UL,
0x15F66CA0631D4088UL, 0xFFAF52874B44C147UL, 0x30C60AE2F14ABB7EUL, 0xE68C6ECCC5B67046UL,
0x00CA4FBD56A4D5A4UL, 0xAE183EC84B849DDAUL, 0xADD1643045CE5773UL, 0x67255C1468CEA6E8UL,
0x16E10ECBF28CDAA3UL, 0x9A99949A5806E933UL, 0x7B846FC220B2601FUL, 0x1885D1A07FACCED1UL,
0xD319DD8DA15B5932UL, 0x46B4A5AAC01C9A50UL, 0xBA6B04E467633D9FUL, 0x7EEE560BAB19CAF6UL,
0x742128A9EA79B11FUL, 0xEE51363B35F7BDE9UL, 0x76D350755AAC571DUL, 0x01707DA3FEC2463AUL,
0x42D8A498AFC135F7UL, 0x79676B9E20ECED78UL, 0xA8DB3AEA15638341UL, 0x832C83324D3BC3FAUL,
0xF347271C1F3B40A7UL, 0x9A762DB734F04059UL, 0xFD4F21D26C4E3EE7UL, 0xEF5957DC398DFDB8UL,
0xDAEB492B490C9B8DUL, 0x0D70F36849D7A25BUL, 0x84558D7AD0AE3B7DUL, 0x658EF8E4F0E9A5F5UL,
0x533B1036F4A2B8A0UL, 0x5AEC3E759E07A80CUL, 0x4F88E85692946891UL, 0x4CBCBAF8555CB05BUL,
0x7B9487F3993BBBE3UL, 0x5D1C6B72D6F4DA75UL, 0x6DB334DC28ACAE64UL, 0x71DB28B850A5346CUL,
0x2A518D10F2E261F8UL, 0xFC75DD593364DBE3UL, 0xA23FCE43F1BCAC1CUL, 0xB043E8023CD1BB67UL,
0x75A12988CA5B0A33UL, 0x5C5316B44D19347FUL, 0x1E4D790EC3943B92UL, 0x3FAFEEB6D7757479UL,
0x21391ABEF7D4A8EAUL, 0x5127234C097EF45CUL, 0xD23C32BA5324A326UL, 0xADD5A66D4A17A344UL,
0x08C9F2AFA63E1DB5UL, 0x563C6B91983D5983UL, 0x4D608672A17CF84CUL, 0xF6C76E08CC3EE246UL,
0x5E76BCB1B333982FUL, 0x2AE6C4EFA566D62BUL, 0x36D4C1BEE8B6F406UL, 0x6321EFBC1582EE74UL,
0x69C953F40D4EC1FDUL, 0x26585806C45A7DA7UL, 0x16FAE0061614C17EUL, 0x3F9D63283DAF907EUL,
0x0CD29B00E3F2C9D2UL, 0x300CD4B730CEAA5FUL, 0x9832E0F216512A74UL, 0x9AF8CEE3D830EB0DUL,
0x9279F1B57B9EC54BUL, 0xD36886046EE651FFUL, 0x316796E6574D239BUL, 0x05750A17F3A6E6CCUL,
0xCE6C3213D98176B1UL, 0x62A205F88452173CUL, 0x47154778B3CB2BF4UL, 0x486A9323825446FFUL,
0x65655E4E0758DF38UL, 0x8E5086FC897CFCF2UL, 0x86CA0BD0442E7031UL, 0x4E477830A20940F0UL,
0x8338F7D139EEA065UL, 0xBD3A2CE437E95EF7UL, 0x6FF8130126B29721UL, 0xE7DE9FEFD1ED44A3UL,
0xD992257615DFA08BUL, 0xBE42DC12F6F7853CUL, 0x7EB027AB7CECA7D8UL, 0xDEA83EAADA7D8D53UL,
0xD86902BD93CE25AAUL, 0xF908731AFD43F65AUL, 0xA5194A17DAEF5FC0UL, 0x6A21FD4C33664D97UL,
0x701541DB3198B435UL, 0x9B54CDEDBB0F1EEAUL, 0x72409751A163D09AUL, 0xE26F4791BF9D75F6UL
};
#define Ceven_hi(r) (C[((r) << 2) + 0])
#define Ceven_lo(r) (C[((r) << 2) + 1])
#define Codd_hi(r) (C[((r) << 2) + 2])
#define Codd_lo(r) (C[((r) << 2) + 3])
#define S(x0, x1, x2, x3, cb, r) do { \
Sb(x0 ## h, x1 ## h, x2 ## h, x3 ## h, cb ## hi(r)); \
Sb(x0 ## l, x1 ## l, x2 ## l, x3 ## l, cb ## lo(r)); \
} while (0)
#define L(x0, x1, x2, x3, x4, x5, x6, x7) do { \
Lb(x0 ## h, x1 ## h, x2 ## h, x3 ## h, \
x4 ## h, x5 ## h, x6 ## h, x7 ## h); \
Lb(x0 ## l, x1 ## l, x2 ## l, x3 ## l, \
x4 ## l, x5 ## l, x6 ## l, x7 ## l); \
} while (0)
#define Wz(x, c, n) do { \
sph_u64 t = (x ## h & (c)) << (n); \
x ## h = ((x ## h >> (n)) & (c)) | t; \
t = (x ## l & (c)) << (n); \
x ## l = ((x ## l >> (n)) & (c)) | t; \
} while (0)
#define W0(x) Wz(x, SPH_C64(0x5555555555555555), 1)
#define W1(x) Wz(x, SPH_C64(0x3333333333333333), 2)
#define W2(x) Wz(x, SPH_C64(0x0F0F0F0F0F0F0F0F), 4)
#define W3(x) Wz(x, SPH_C64(0x00FF00FF00FF00FF), 8)
#define W4(x) Wz(x, SPH_C64(0x0000FFFF0000FFFF), 16)
#define W5(x) Wz(x, SPH_C64(0x00000000FFFFFFFF), 32)
#define W6(x) do { \
sph_u64 t = x ## h; \
x ## h = x ## l; \
x ## l = t; \
} while (0)
#define SL(ro) SLu(r + ro, ro)
#define SLu(r, ro) do { \
S(h0, h2, h4, h6, Ceven_, r); \
S(h1, h3, h5, h7, Codd_, r); \
L(h0, h2, h4, h6, h1, h3, h5, h7); \
W ## ro(h1); \
W ## ro(h3); \
W ## ro(h5); \
W ## ro(h7); \
} while (0)
#if SPH_SMALL_FOOTPRINT_JH
/*
* The "small footprint" 64-bit version just uses a partially unrolled
* loop.
*/
#define E8 do { \
unsigned r; \
for (r = 0; r < 42; r += 7) { \
SL(0); \
SL(1); \
SL(2); \
SL(3); \
SL(4); \
SL(5); \
SL(6); \
} \
} while (0)
#else
/*
* On a "true 64-bit" architecture, we can unroll at will.
*/
#define E8 do { \
SLu( 0, 0); \
SLu( 1, 1); \
SLu( 2, 2); \
SLu( 3, 3); \
SLu( 4, 4); \
SLu( 5, 5); \
SLu( 6, 6); \
SLu( 7, 0); \
SLu( 8, 1); \
SLu( 9, 2); \
SLu(10, 3); \
SLu(11, 4); \
SLu(12, 5); \
SLu(13, 6); \
SLu(14, 0); \
SLu(15, 1); \
SLu(16, 2); \
SLu(17, 3); \
SLu(18, 4); \
SLu(19, 5); \
SLu(20, 6); \
SLu(21, 0); \
SLu(22, 1); \
SLu(23, 2); \
SLu(24, 3); \
SLu(25, 4); \
SLu(26, 5); \
SLu(27, 6); \
SLu(28, 0); \
SLu(29, 1); \
SLu(30, 2); \
SLu(31, 3); \
SLu(32, 4); \
SLu(33, 5); \
SLu(34, 6); \
SLu(35, 0); \
SLu(36, 1); \
SLu(37, 2); \
SLu(38, 3); \
SLu(39, 4); \
SLu(40, 5); \
SLu(41, 6); \
} while (0)
#endif
)==="
@@ -0,0 +1,90 @@
R"===(
#ifndef WOLF_AES_CL
#define WOLF_AES_CL
// AES table - the other three are generated on the fly
static const __constant uint AES0_C[256] =
{
0xA56363C6U, 0x847C7CF8U, 0x997777EEU, 0x8D7B7BF6U,
0x0DF2F2FFU, 0xBD6B6BD6U, 0xB16F6FDEU, 0x54C5C591U,
0x50303060U, 0x03010102U, 0xA96767CEU, 0x7D2B2B56U,
0x19FEFEE7U, 0x62D7D7B5U, 0xE6ABAB4DU, 0x9A7676ECU,
0x45CACA8FU, 0x9D82821FU, 0x40C9C989U, 0x877D7DFAU,
0x15FAFAEFU, 0xEB5959B2U, 0xC947478EU, 0x0BF0F0FBU,
0xECADAD41U, 0x67D4D4B3U, 0xFDA2A25FU, 0xEAAFAF45U,
0xBF9C9C23U, 0xF7A4A453U, 0x967272E4U, 0x5BC0C09BU,
0xC2B7B775U, 0x1CFDFDE1U, 0xAE93933DU, 0x6A26264CU,
0x5A36366CU, 0x413F3F7EU, 0x02F7F7F5U, 0x4FCCCC83U,
0x5C343468U, 0xF4A5A551U, 0x34E5E5D1U, 0x08F1F1F9U,
0x937171E2U, 0x73D8D8ABU, 0x53313162U, 0x3F15152AU,
0x0C040408U, 0x52C7C795U, 0x65232346U, 0x5EC3C39DU,
0x28181830U, 0xA1969637U, 0x0F05050AU, 0xB59A9A2FU,
0x0907070EU, 0x36121224U, 0x9B80801BU, 0x3DE2E2DFU,
0x26EBEBCDU, 0x6927274EU, 0xCDB2B27FU, 0x9F7575EAU,
0x1B090912U, 0x9E83831DU, 0x742C2C58U, 0x2E1A1A34U,
0x2D1B1B36U, 0xB26E6EDCU, 0xEE5A5AB4U, 0xFBA0A05BU,
0xF65252A4U, 0x4D3B3B76U, 0x61D6D6B7U, 0xCEB3B37DU,
0x7B292952U, 0x3EE3E3DDU, 0x712F2F5EU, 0x97848413U,
0xF55353A6U, 0x68D1D1B9U, 0x00000000U, 0x2CEDEDC1U,
0x60202040U, 0x1FFCFCE3U, 0xC8B1B179U, 0xED5B5BB6U,
0xBE6A6AD4U, 0x46CBCB8DU, 0xD9BEBE67U, 0x4B393972U,
0xDE4A4A94U, 0xD44C4C98U, 0xE85858B0U, 0x4ACFCF85U,
0x6BD0D0BBU, 0x2AEFEFC5U, 0xE5AAAA4FU, 0x16FBFBEDU,
0xC5434386U, 0xD74D4D9AU, 0x55333366U, 0x94858511U,
0xCF45458AU, 0x10F9F9E9U, 0x06020204U, 0x817F7FFEU,
0xF05050A0U, 0x443C3C78U, 0xBA9F9F25U, 0xE3A8A84BU,
0xF35151A2U, 0xFEA3A35DU, 0xC0404080U, 0x8A8F8F05U,
0xAD92923FU, 0xBC9D9D21U, 0x48383870U, 0x04F5F5F1U,
0xDFBCBC63U, 0xC1B6B677U, 0x75DADAAFU, 0x63212142U,
0x30101020U, 0x1AFFFFE5U, 0x0EF3F3FDU, 0x6DD2D2BFU,
0x4CCDCD81U, 0x140C0C18U, 0x35131326U, 0x2FECECC3U,
0xE15F5FBEU, 0xA2979735U, 0xCC444488U, 0x3917172EU,
0x57C4C493U, 0xF2A7A755U, 0x827E7EFCU, 0x473D3D7AU,
0xAC6464C8U, 0xE75D5DBAU, 0x2B191932U, 0x957373E6U,
0xA06060C0U, 0x98818119U, 0xD14F4F9EU, 0x7FDCDCA3U,
0x66222244U, 0x7E2A2A54U, 0xAB90903BU, 0x8388880BU,
0xCA46468CU, 0x29EEEEC7U, 0xD3B8B86BU, 0x3C141428U,
0x79DEDEA7U, 0xE25E5EBCU, 0x1D0B0B16U, 0x76DBDBADU,
0x3BE0E0DBU, 0x56323264U, 0x4E3A3A74U, 0x1E0A0A14U,
0xDB494992U, 0x0A06060CU, 0x6C242448U, 0xE45C5CB8U,
0x5DC2C29FU, 0x6ED3D3BDU, 0xEFACAC43U, 0xA66262C4U,
0xA8919139U, 0xA4959531U, 0x37E4E4D3U, 0x8B7979F2U,
0x32E7E7D5U, 0x43C8C88BU, 0x5937376EU, 0xB76D6DDAU,
0x8C8D8D01U, 0x64D5D5B1U, 0xD24E4E9CU, 0xE0A9A949U,
0xB46C6CD8U, 0xFA5656ACU, 0x07F4F4F3U, 0x25EAEACFU,
0xAF6565CAU, 0x8E7A7AF4U, 0xE9AEAE47U, 0x18080810U,
0xD5BABA6FU, 0x887878F0U, 0x6F25254AU, 0x722E2E5CU,
0x241C1C38U, 0xF1A6A657U, 0xC7B4B473U, 0x51C6C697U,
0x23E8E8CBU, 0x7CDDDDA1U, 0x9C7474E8U, 0x211F1F3EU,
0xDD4B4B96U, 0xDCBDBD61U, 0x868B8B0DU, 0x858A8A0FU,
0x907070E0U, 0x423E3E7CU, 0xC4B5B571U, 0xAA6666CCU,
0xD8484890U, 0x05030306U, 0x01F6F6F7U, 0x120E0E1CU,
0xA36161C2U, 0x5F35356AU, 0xF95757AEU, 0xD0B9B969U,
0x91868617U, 0x58C1C199U, 0x271D1D3AU, 0xB99E9E27U,
0x38E1E1D9U, 0x13F8F8EBU, 0xB398982BU, 0x33111122U,
0xBB6969D2U, 0x70D9D9A9U, 0x898E8E07U, 0xA7949433U,
0xB69B9B2DU, 0x221E1E3CU, 0x92878715U, 0x20E9E9C9U,
0x49CECE87U, 0xFF5555AAU, 0x78282850U, 0x7ADFDFA5U,
0x8F8C8C03U, 0xF8A1A159U, 0x80898909U, 0x170D0D1AU,
0xDABFBF65U, 0x31E6E6D7U, 0xC6424284U, 0xB86868D0U,
0xC3414182U, 0xB0999929U, 0x772D2D5AU, 0x110F0F1EU,
0xCBB0B07BU, 0xFC5454A8U, 0xD6BBBB6DU, 0x3A16162CU
};
#define BYTE(x, y) (amd_bfe((x), (y) << 3U, 8U))
uint4 AES_Round(const __local uint *AES0, const __local uint *AES1, const __local uint *AES2, const __local uint *AES3, const uint4 X, const uint4 key)
{
uint4 Y;
Y.s0 = AES0[BYTE(X.s0, 0)] ^ AES1[BYTE(X.s1, 1)] ^ AES2[BYTE(X.s2, 2)] ^ AES3[BYTE(X.s3, 3)];
Y.s1 = AES0[BYTE(X.s1, 0)] ^ AES1[BYTE(X.s2, 1)] ^ AES2[BYTE(X.s3, 2)] ^ AES3[BYTE(X.s0, 3)];
Y.s2 = AES0[BYTE(X.s2, 0)] ^ AES1[BYTE(X.s3, 1)] ^ AES2[BYTE(X.s0, 2)] ^ AES3[BYTE(X.s1, 3)];
Y.s3 = AES0[BYTE(X.s3, 0)] ^ AES1[BYTE(X.s0, 1)] ^ AES2[BYTE(X.s1, 2)] ^ AES3[BYTE(X.s2, 3)];
Y ^= key;
return(Y);
}
#endif
)==="
@@ -0,0 +1,114 @@
R"===(
#ifndef WOLF_SKEIN_CL
#define WOLF_SKEIN_CL
// Vectorized Skein implementation macros and functions by Wolf
#define SKEIN_KS_PARITY 0x1BD11BDAA9FC1A22
static const __constant ulong SKEIN256_IV[8] =
{
0xCCD044A12FDB3E13UL, 0xE83590301A79A9EBUL,
0x55AEA0614F816E6FUL, 0x2A2767A4AE9B94DBUL,
0xEC06025E74DD7683UL, 0xE7A436CDC4746251UL,
0xC36FBAF9393AD185UL, 0x3EEDBA1833EDFC13UL
};
static const __constant ulong SKEIN512_256_IV[8] =
{
0xCCD044A12FDB3E13UL, 0xE83590301A79A9EBUL,
0x55AEA0614F816E6FUL, 0x2A2767A4AE9B94DBUL,
0xEC06025E74DD7683UL, 0xE7A436CDC4746251UL,
0xC36FBAF9393AD185UL, 0x3EEDBA1833EDFC13UL
};
#define SKEIN_INJECT_KEY(p, s) do { \
p += h; \
p.s5 += t[s % 3]; \
p.s6 += t[(s + 1) % 3]; \
p.s7 += s; \
} while(0)
ulong SKEIN_ROT(const uint2 x, const uint y)
{
if(y < 32) return(as_ulong(amd_bitalign(x, x.s10, 32 - y)));
else return(as_ulong(amd_bitalign(x.s10, x, 32 - (y - 32))));
}
void SkeinMix8(ulong4 *pv0, ulong4 *pv1, const uint rc0, const uint rc1, const uint rc2, const uint rc3)
{
*pv0 += *pv1;
(*pv1).s0 = SKEIN_ROT(as_uint2((*pv1).s0), rc0);
(*pv1).s1 = SKEIN_ROT(as_uint2((*pv1).s1), rc1);
(*pv1).s2 = SKEIN_ROT(as_uint2((*pv1).s2), rc2);
(*pv1).s3 = SKEIN_ROT(as_uint2((*pv1).s3), rc3);
*pv1 ^= *pv0;
}
ulong8 SkeinEvenRound(ulong8 p, const ulong8 h, const ulong *t, const uint s)
{
SKEIN_INJECT_KEY(p, s);
ulong4 pv0 = p.even, pv1 = p.odd;
SkeinMix8(&pv0, &pv1, 46, 36, 19, 37);
pv0 = shuffle(pv0, (ulong4)(1, 2, 3, 0));
pv1 = shuffle(pv1, (ulong4)(0, 3, 2, 1));
SkeinMix8(&pv0, &pv1, 33, 27, 14, 42);
pv0 = shuffle(pv0, (ulong4)(1, 2, 3, 0));
pv1 = shuffle(pv1, (ulong4)(0, 3, 2, 1));
SkeinMix8(&pv0, &pv1, 17, 49, 36, 39);
pv0 = shuffle(pv0, (ulong4)(1, 2, 3, 0));
pv1 = shuffle(pv1, (ulong4)(0, 3, 2, 1));
SkeinMix8(&pv0, &pv1, 44, 9, 54, 56);
return(shuffle2(pv0, pv1, (ulong8)(1, 4, 2, 7, 3, 6, 0, 5)));
}
ulong8 SkeinOddRound(ulong8 p, const ulong8 h, const ulong *t, const uint s)
{
SKEIN_INJECT_KEY(p, s);
ulong4 pv0 = p.even, pv1 = p.odd;
SkeinMix8(&pv0, &pv1, 39, 30, 34, 24);
pv0 = shuffle(pv0, (ulong4)(1, 2, 3, 0));
pv1 = shuffle(pv1, (ulong4)(0, 3, 2, 1));
SkeinMix8(&pv0, &pv1, 13, 50, 10, 17);
pv0 = shuffle(pv0, (ulong4)(1, 2, 3, 0));
pv1 = shuffle(pv1, (ulong4)(0, 3, 2, 1));
SkeinMix8(&pv0, &pv1, 25, 29, 39, 43);
pv0 = shuffle(pv0, (ulong4)(1, 2, 3, 0));
pv1 = shuffle(pv1, (ulong4)(0, 3, 2, 1));
SkeinMix8(&pv0, &pv1, 8, 35, 56, 22);
return(shuffle2(pv0, pv1, (ulong8)(1, 4, 2, 7, 3, 6, 0, 5)));
}
ulong8 Skein512Block(ulong8 p, ulong8 h, ulong h8, const ulong *t)
{
#pragma unroll
for(int i = 0; i < 18; ++i)
{
p = SkeinEvenRound(p, h, t, i);
++i;
ulong tmp = h.s0;
h = shuffle(h, (ulong8)(1, 2, 3, 4, 5, 6, 7, 0));
h.s7 = h8;
h8 = tmp;
p = SkeinOddRound(p, h, t, i);
tmp = h.s0;
h = shuffle(h, (ulong8)(1, 2, 3, 4, 5, 6, 7, 0));
h.s7 = h8;
h8 = tmp;
}
SKEIN_INJECT_KEY(p, 18);
return(p);
}
#endif
)==="
+111
View File
@@ -0,0 +1,111 @@
#pragma once
#include "amd_gpu/gpu.hpp"
#include "autoAdjust.hpp"
#include "jconf.hpp"
#include "xmrstak/misc/console.hpp"
#include "xmrstak/misc/configEditor.hpp"
#include "xmrstak/params.hpp"
#include <vector>
#include <cstdio>
#include <sstream>
#include <string>
#include <iostream>
#include <algorithm>
#if defined(__APPLE__)
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#endif
namespace xmrstak
{
namespace amd
{
class autoAdjust
{
public:
autoAdjust()
{
}
/** print the adjusted values if needed
*
* Routine exit the application and print the adjusted values if needed else
* nothing is happened.
*/
bool printConfig()
{
int platformIndex = getAMDPlatformIdx();
if(platformIndex == -1)
{
printer::inst()->print_msg(L0,"WARNING: No AMD OpenCL platform found. Possible driver issues or wrong vendor driver.");
return false;
}
devVec = getAMDDevices(0);
int deviceCount = devVec.size();
if(deviceCount == 0)
return false;
generateThreadConfig(platformIndex);
return true;
}
private:
void generateThreadConfig(const int platformIndex)
{
// load the template of the backend config into a char variable
const char *tpl =
#include "./config.tpl"
;
configEditor configTpl{};
configTpl.set( std::string(tpl) );
std::string conf;
int i = 0;
for(auto& ctx : devVec)
{
// keep 64MiB memory free (value is randomly chosen)
size_t availableMem = ctx.freeMem - (64u * 1024 * 1024);
// 224byte extra memory is used per thread for meta data
size_t perThread = (size_t(1u)<<21) + 224u;
size_t max_intensity = availableMem / perThread;
// 1000 is a magic selected limit \todo select max intensity depending of the gpu type
size_t intensity = std::min( size_t(1000u) , max_intensity );
conf += std::string(" // gpu: ") + ctx.name + "\n";
// set 8 threads per block (this is a good value for the most gpus)
conf += std::string(" { \"index\" : ") + std::to_string(ctx.deviceIdx) + ",\n" +
" \"intensity\" : " + std::to_string(intensity) + ", \"worksize\" : " + std::to_string(8) + ",\n" +
" \"affine_to_cpu\" : false, \n"
" },\n";
++i;
}
configTpl.replace("PLATFORMINDEX",std::to_string(platformIndex));
configTpl.replace("NUMGPUS",std::to_string(devVec.size()));
configTpl.replace("GPUCONFIG",conf);
configTpl.write(params::inst().configFileAMD);
printer::inst()->print_msg(L0, "AMD: GPU configuration stored in file '%s'", params::inst().configFileAMD.c_str());
}
std::vector<GpuContext> devVec;
};
} // namespace amd
} // namepsace xmrstak
+29
View File
@@ -0,0 +1,29 @@
R"===(
/*
* Number of GPUs that you have in your system. Each GPU will get its own CPU thread.
*/
"gpu_thread_num" : NUMGPUS,
/*
* GPU configuration. You should play around with intensity and worksize as the fastest settings will vary.
* index - GPU index number usually starts from 0
* intensity - Number of parallel GPU threads (nothing to do with CPU threads)
* worksize - Number of local GPU threads (nothing to do with CPU threads)
* affine_to_cpu - This will affine the thread to a CPU. This can make a GPU miner play along nicer with a CPU miner.
* "gpu_threads_conf" :
* [
* { "index" : 0, "intensity" : 1000, "worksize" : 8, "affine_to_cpu" : false },
* ],
*/
"gpu_threads_conf" : [
GPUCONFIG
],
/*
* Platform index. This will be 0 unless you have different OpenCL platform - eg. AMD and Intel.
*/
"platform_index" : PLATFORMINDEX,
)==="
+259
View File
@@ -0,0 +1,259 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with OpenSSL (or a modified version of that library), containing parts
* covered by the terms of OpenSSL License and SSLeay License, the licensors
* of this Program grant you additional permission to convey the resulting work.
*
*/
#include "jconf.hpp"
#include "xmrstak/misc/jext.hpp"
#include "xmrstak/misc/console.hpp"
#ifdef _WIN32
#define strcasecmp _stricmp
#include <intrin.h>
#else
#include <cpuid.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
namespace xmrstak
{
namespace amd
{
using namespace rapidjson;
/*
* This enum needs to match index in oConfigValues, otherwise we will get a runtime error
*/
enum configEnum { iGpuThreadNum, aGpuThreadsConf, iPlatformIdx };
struct configVal {
configEnum iName;
const char* sName;
Type iType;
};
//Same order as in configEnum, as per comment above
configVal oConfigValues[] = {
{ iGpuThreadNum, "gpu_thread_num", kNumberType },
{ aGpuThreadsConf, "gpu_threads_conf", kArrayType },
{ iPlatformIdx, "platform_index", kNumberType }
};
constexpr size_t iConfigCnt = (sizeof(oConfigValues)/sizeof(oConfigValues[0]));
inline bool checkType(Type have, Type want)
{
if(want == have)
return true;
else if(want == kTrueType && have == kFalseType)
return true;
else if(want == kFalseType && have == kTrueType)
return true;
else
return false;
}
struct jconf::opaque_private
{
Document jsonDoc;
const Value* configValues[iConfigCnt]; //Compile time constant
opaque_private()
{
}
};
jconf* jconf::oInst = nullptr;
jconf::jconf()
{
prv = new opaque_private();
}
bool jconf::GetThreadConfig(size_t id, thd_cfg &cfg)
{
if(id >= prv->configValues[aGpuThreadsConf]->Size())
return false;
const Value& oThdConf = prv->configValues[aGpuThreadsConf]->GetArray()[id];
if(!oThdConf.IsObject())
return false;
const Value *idx, *intensity, *w_size, *aff;
idx = GetObjectMember(oThdConf, "index");
intensity = GetObjectMember(oThdConf, "intensity");
w_size = GetObjectMember(oThdConf, "worksize");
aff = GetObjectMember(oThdConf, "affine_to_cpu");
if(idx == nullptr || intensity == nullptr || w_size == nullptr || aff == nullptr)
return false;
if(!idx->IsUint64() || !intensity->IsUint64() || !w_size->IsUint64())
return false;
if(!aff->IsUint64() && !aff->IsBool())
return false;
cfg.index = idx->GetUint64();
cfg.intensity = intensity->GetUint64();
cfg.w_size = w_size->GetUint64();
if(aff->IsNumber())
cfg.cpu_aff = aff->GetInt64();
else
cfg.cpu_aff = -1;
return true;
}
size_t jconf::GetPlatformIdx()
{
return prv->configValues[iPlatformIdx]->GetUint64();
}
size_t jconf::GetThreadCount()
{
return prv->configValues[aGpuThreadsConf]->Size();
}
bool jconf::parse_config(const char* sFilename)
{
FILE * pFile;
char * buffer;
size_t flen;
pFile = fopen(sFilename, "rb");
if (pFile == NULL)
{
printer::inst()->print_msg(L0, "Failed to open config file %s.", sFilename);
return false;
}
fseek(pFile,0,SEEK_END);
flen = ftell(pFile);
rewind(pFile);
if(flen >= 64*1024)
{
fclose(pFile);
printer::inst()->print_msg(L0, "Oversized config file - %s.", sFilename);
return false;
}
if(flen <= 16)
{
printer::inst()->print_msg(L0, "File is empty or too short - %s.", sFilename);
return false;
}
buffer = (char*)malloc(flen + 3);
if(fread(buffer+1, flen, 1, pFile) != 1)
{
free(buffer);
fclose(pFile);
printer::inst()->print_msg(L0, "Read error while reading %s.", sFilename);
return false;
}
fclose(pFile);
//Replace Unicode BOM with spaces - we always use UTF-8
unsigned char* ubuffer = (unsigned char*)buffer;
if(ubuffer[1] == 0xEF && ubuffer[2] == 0xBB && ubuffer[3] == 0xBF)
{
buffer[1] = ' ';
buffer[2] = ' ';
buffer[3] = ' ';
}
buffer[0] = '{';
buffer[flen] = '}';
buffer[flen + 1] = '\0';
prv->jsonDoc.Parse<kParseCommentsFlag|kParseTrailingCommasFlag>(buffer, flen+2);
free(buffer);
if(prv->jsonDoc.HasParseError())
{
printer::inst()->print_msg(L0, "JSON config parse error(offset %llu): %s",
int_port(prv->jsonDoc.GetErrorOffset()), GetParseError_En(prv->jsonDoc.GetParseError()));
return false;
}
if(!prv->jsonDoc.IsObject())
{ //This should never happen as we created the root ourselves
printer::inst()->print_msg(L0, "Invalid config file. No root?\n");
return false;
}
for(size_t i = 0; i < iConfigCnt; i++)
{
if(oConfigValues[i].iName != i)
{
printer::inst()->print_msg(L0, "Code error. oConfigValues are not in order.");
return false;
}
prv->configValues[i] = GetObjectMember(prv->jsonDoc, oConfigValues[i].sName);
if(prv->configValues[i] == nullptr)
{
printer::inst()->print_msg(L0, "Invalid config file. Missing value \"%s\".", oConfigValues[i].sName);
return false;
}
if(!checkType(prv->configValues[i]->GetType(), oConfigValues[i].iType))
{
printer::inst()->print_msg(L0, "Invalid config file. Value \"%s\" has unexpected type.", oConfigValues[i].sName);
return false;
}
}
size_t n_thd = prv->configValues[aGpuThreadsConf]->Size();
if(prv->configValues[iGpuThreadNum]->GetUint64() != n_thd)
{
printer::inst()->print_msg(L0,
"Invalid config file. Your GPU config array has %llu members, while you want to use %llu threads.",
int_port(n_thd), int_port(prv->configValues[iGpuThreadNum]->GetUint64()));
return false;
}
thd_cfg c;
for(size_t i=0; i < n_thd; i++)
{
if(!GetThreadConfig(i, c))
{
printer::inst()->print_msg(L0, "Thread %llu has invalid config.", int_port(i));
return false;
}
}
return true;
}
} // namespace amd
} // namespace xmrstak
+46
View File
@@ -0,0 +1,46 @@
#pragma once
#include "xmrstak/params.hpp"
#include <stdlib.h>
#include <string>
namespace xmrstak
{
namespace amd
{
class jconf
{
public:
static jconf* inst()
{
if (oInst == nullptr) oInst = new jconf;
return oInst;
};
bool parse_config(const char* sFilename = params::inst().configFileAMD.c_str());
struct thd_cfg {
size_t index;
size_t intensity;
size_t w_size;
long long cpu_aff;
};
size_t GetThreadCount();
bool GetThreadConfig(size_t id, thd_cfg &cfg);
size_t GetPlatformIdx();
private:
jconf();
static jconf* oInst;
struct opaque_private;
opaque_private* prv;
};
} // namespace amd
} // namespace xmrstak
+234
View File
@@ -0,0 +1,234 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with OpenSSL (or a modified version of that library), containing parts
* covered by the terms of OpenSSL License and SSLeay License, the licensors
* of this Program grant you additional permission to convey the resulting work.
*
*/
#include "minethd.hpp"
#include "autoAdjust.hpp"
#include "amd_gpu/gpu.hpp"
#include "xmrstak/backend/cpu/crypto/cryptonight_aesni.h"
#include "xmrstak/backend/cpu/crypto/cryptonight.h"
#include "xmrstak/misc/configEditor.hpp"
#include "xmrstak/misc/console.hpp"
#include "xmrstak/backend/cpu/minethd.hpp"
#include "xmrstak/jconf.hpp"
#include "xmrstak/misc/executor.hpp"
#include "xmrstak/misc/environment.hpp"
#include "xmrstak/params.hpp"
#include <assert.h>
#include <cmath>
#include <chrono>
#include <thread>
#include <vector>
namespace xmrstak
{
namespace amd
{
minethd::minethd(miner_work& pWork, size_t iNo, GpuContext* ctx)
{
oWork = pWork;
bQuit = 0;
iThreadNo = (uint8_t)iNo;
iJobNo = 0;
iHashCount = 0;
iTimestamp = 0;
pGpuCtx = ctx;
oWorkThd = std::thread(&minethd::work_main, this);
}
extern "C" {
#ifdef WIN32
__declspec(dllexport)
#endif
std::vector<iBackend*>* xmrstak_start_backend(uint32_t threadOffset, miner_work& pWork, environment& env)
{
environment::inst() = env;
return amd::minethd::thread_starter(threadOffset, pWork);
}
} // extern "C"
bool minethd::init_gpus()
{
size_t i, n = jconf::inst()->GetThreadCount();
printer::inst()->print_msg(L1, "Compiling code and initializing GPUs. This will take a while...");
vGpuData.resize(n);
jconf::thd_cfg cfg;
for(i = 0; i < n; i++)
{
jconf::inst()->GetThreadConfig(i, cfg);
vGpuData[i].deviceIdx = cfg.index;
vGpuData[i].rawIntensity = cfg.intensity;
vGpuData[i].workSize = cfg.w_size;
}
return InitOpenCL(vGpuData.data(), n, jconf::inst()->GetPlatformIdx()) == ERR_SUCCESS;
}
std::vector<GpuContext> minethd::vGpuData;
std::vector<iBackend*>* minethd::thread_starter(uint32_t threadOffset, miner_work& pWork)
{
std::vector<iBackend*>* pvThreads = new std::vector<iBackend*>();
if(!configEditor::file_exist(params::inst().configFileAMD))
{
autoAdjust adjust;
if(!adjust.printConfig())
return pvThreads;
}
if(!jconf::inst()->parse_config())
{
win_exit();
}
// \ todo get device count and exit if no opencl device
if(!init_gpus())
{
printer::inst()->print_msg(L1, "WARNING: AMD device not found");
return pvThreads;
}
size_t i, n = jconf::inst()->GetThreadCount();
pvThreads->reserve(n);
jconf::thd_cfg cfg;
for (i = 0; i < n; i++)
{
jconf::inst()->GetThreadConfig(i, cfg);
minethd* thd = new minethd(pWork, i + threadOffset, &vGpuData[i]);
if(cfg.cpu_aff >= 0)
{
#if defined(__APPLE__)
printer::inst()->print_msg(L1, "WARNING on MacOS thread affinity is only advisory.");
#endif
cpu::minethd::thd_setaffinity(thd->oWorkThd.native_handle(), cfg.cpu_aff);
}
pvThreads->push_back(thd);
if(cfg.cpu_aff >= 0)
printer::inst()->print_msg(L1, "Starting GPU thread, affinity: %d.", (int)cfg.cpu_aff);
else
printer::inst()->print_msg(L1, "Starting GPU thread, no affinity.");
}
return pvThreads;
}
void minethd::switch_work(miner_work& pWork)
{
// iConsumeCnt is a basic lock-like polling mechanism just in case we happen to push work
// faster than threads can consume them. This should never happen in real life.
// Pool cant physically send jobs faster than every 250ms or so due to net latency.
while (globalStates::inst().iConsumeCnt.load(std::memory_order_seq_cst) < globalStates::inst().iThreadCount)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
globalStates::inst().oGlobalWork = pWork;
globalStates::inst().iConsumeCnt.store(0, std::memory_order_seq_cst);
globalStates::inst().iGlobalJobNo++;
}
void minethd::consume_work()
{
memcpy(&oWork, &globalStates::inst().oGlobalWork, sizeof(miner_work));
iJobNo++;
globalStates::inst().iConsumeCnt++;
}
void minethd::work_main()
{
uint64_t iCount = 0;
cryptonight_ctx* cpu_ctx;
cpu_ctx = cpu::minethd::minethd_alloc_ctx();
cn_hash_fun hash_fun = cpu::minethd::func_selector(::jconf::inst()->HaveHardwareAes(), true /*bNoPrefetch*/);
globalStates::inst().iConsumeCnt++;
while (bQuit == 0)
{
if (oWork.bStall)
{
/* We are stalled here because the executor didn't find a job for us yet,
either because of network latency, or a socket problem. Since we are
raison d'etre of this software it us sensible to just wait until we have something*/
while (globalStates::inst().iGlobalJobNo.load(std::memory_order_relaxed) == iJobNo)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
consume_work();
continue;
}
assert(sizeof(job_result::sJobID) == sizeof(pool_job::sJobID));
pGpuCtx->Nonce = calc_start_nonce(oWork.iResumeCnt);
uint32_t target = oWork.iTarget32;
XMRSetJob(pGpuCtx, oWork.bWorkBlob, oWork.iWorkSize, target);
while(globalStates::inst().iGlobalJobNo.load(std::memory_order_relaxed) == iJobNo)
{
cl_uint results[0x100];
memset(results,0,sizeof(cl_uint)*(0x100));
XMRRunJob(pGpuCtx, results);
for(size_t i = 0; i < results[0xFF]; i++)
{
uint8_t bWorkBlob[112];
uint8_t bResult[32];
memcpy(bWorkBlob, oWork.bWorkBlob, oWork.iWorkSize);
memset(bResult, 0, sizeof(job_result::bResult));
*(uint32_t*)(bWorkBlob + 39) = results[i];
hash_fun(bWorkBlob, oWork.iWorkSize, bResult, cpu_ctx);
if ( (*((uint64_t*)(bResult + 24))) < oWork.iTarget)
executor::inst()->push_event(ex_event(job_result(oWork.sJobID, results[i], bResult), oWork.iPoolId));
else
executor::inst()->log_result_error("AMD Invalid Result");
}
iCount += pGpuCtx->rawIntensity;
using namespace std::chrono;
uint64_t iStamp = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
iHashCount.store(iCount, std::memory_order_relaxed);
iTimestamp.store(iStamp, std::memory_order_relaxed);
std::this_thread::yield();
}
consume_work();
}
}
} // namespace amd
} // namespace xmrstak
+54
View File
@@ -0,0 +1,54 @@
#pragma once
#include "amd_gpu/gpu.hpp"
#include "jconf.hpp"
#include "xmrstak/backend/cpu/crypto/cryptonight.h"
#include "xmrstak/backend/miner_work.hpp"
#include "xmrstak/backend/iBackend.hpp"
#include "xmrstak/misc/environment.hpp"
#include <thread>
#include <atomic>
namespace xmrstak
{
namespace amd
{
class minethd : public iBackend
{
public:
static void switch_work(miner_work& pWork);
static std::vector<iBackend*>* thread_starter(uint32_t threadOffset, miner_work& pWork);
static bool init_gpus();
private:
typedef void (*cn_hash_fun)(const void*, size_t, void*, cryptonight_ctx*);
minethd(miner_work& pWork, size_t iNo, GpuContext* ctx);
void work_main();
void double_work_main();
void consume_work();
uint64_t iJobNo;
static miner_work oGlobalWork;
miner_work oWork;
std::thread oWorkThd;
bool bQuit;
bool bNoPrefetch;
//Mutable ptr to vector below, different for each thread
GpuContext* pGpuCtx;
// WARNING - this vector (but not its contents) must be immutable
// once the threads are started
static std::vector<GpuContext> vGpuData;
};
} // namespace amd
} // namespace xmrstak
+103
View File
@@ -0,0 +1,103 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with OpenSSL (or a modified version of that library), containing parts
* covered by the terms of OpenSSL License and SSLeay License, the licensors
* of this Program grant you additional permission to convey the resulting work.
*
*/
#include "iBackend.hpp"
#include "backendConnector.hpp"
#include "miner_work.hpp"
#include "globalStates.hpp"
#include "plugin.hpp"
#include "xmrstak/misc/environment.hpp"
#include "xmrstak/misc/console.hpp"
#include "xmrstak/params.hpp"
#include "cpu/minethd.hpp"
#ifndef CONF_NO_CUDA
# include "nvidia/minethd.hpp"
#endif
#ifndef CONF_NO_OPENCL
# include "amd/minethd.hpp"
#endif
#include <cstdlib>
#include <assert.h>
#include <cmath>
#include <chrono>
#include <cstring>
#include <thread>
#include <bitset>
namespace xmrstak
{
bool BackendConnector::self_test()
{
return true;
}
std::vector<iBackend*>* BackendConnector::thread_starter(miner_work& pWork)
{
globalStates::inst().iGlobalJobNo = 0;
globalStates::inst().iConsumeCnt = 0;
std::vector<iBackend*>* pvThreads = new std::vector<iBackend*>;
#ifndef CONF_NO_CUDA
if(params::inst().useNVIDIA)
{
plugin nvidiaplugin("NVIDIA", "xmrstak_cuda_backend");
std::vector<iBackend*>* nvidiaThreads = nvidiaplugin.startBackend(static_cast<uint32_t>(pvThreads->size()), pWork, environment::inst());
pvThreads->insert(std::end(*pvThreads), std::begin(*nvidiaThreads), std::end(*nvidiaThreads));
if(nvidiaThreads->size() == 0)
printer::inst()->print_msg(L0, "WARNING: backend NVIDIA disabled.");
}
#endif
#ifndef CONF_NO_OPENCL
if(params::inst().useAMD)
{
plugin amdplugin("AMD", "xmrstak_opencl_backend");
std::vector<iBackend*>* amdThreads = amdplugin.startBackend(static_cast<uint32_t>(pvThreads->size()), pWork, environment::inst());
pvThreads->insert(std::end(*pvThreads), std::begin(*amdThreads), std::end(*amdThreads));
if(amdThreads->size() == 0)
printer::inst()->print_msg(L0, "WARNING: backend AMD disabled.");
}
#endif
#ifndef CONF_NO_CPU
if(params::inst().useCPU)
{
auto cpuThreads = cpu::minethd::thread_starter(static_cast<uint32_t>(pvThreads->size()), pWork);
pvThreads->insert(std::end(*pvThreads), std::begin(cpuThreads), std::end(cpuThreads));
if(cpuThreads.size() == 0)
printer::inst()->print_msg(L0, "WARNING: backend CPU disabled.");
}
#endif
globalStates::inst().iThreadCount = pvThreads->size();
return pvThreads;
}
} // namepsace xmrstak
+21
View File
@@ -0,0 +1,21 @@
#pragma once
#include "iBackend.hpp"
#include "miner_work.hpp"
#include <thread>
#include <vector>
#include <atomic>
#include <mutex>
namespace xmrstak
{
struct BackendConnector
{
static std::vector<iBackend*>* thread_starter(miner_work& pWork);
static bool self_test();
};
} // namepsace xmrstak
+174
View File
@@ -0,0 +1,174 @@
#pragma once
#include "jconf.hpp"
#include "xmrstak/misc/console.hpp"
#include "xmrstak/jconf.hpp"
#include "xmrstak/misc/configEditor.hpp"
#include "xmrstak/params.hpp"
#include <string>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif // _WIN32
namespace xmrstak
{
namespace cpu
{
// Mask bits between h and l and return the value
// This enables us to put in values exactly like in the manual
// For example EBX[31:22] is get_masked(cpu_info[1], 31, 22)
inline int32_t get_masked(int32_t val, int32_t h, int32_t l)
{
val &= (0x7FFFFFFF >> (31-(h-l))) << l;
return val >> l;
}
class autoAdjust
{
public:
autoAdjust()
{
}
bool printConfig()
{
configEditor configTpl{};
// load the template of the backend config into a char variable
const char *tpl =
#include "./config.tpl"
;
configTpl.set( std::string(tpl) );
std::string conf;
if(!detectL3Size() || L3KB_size < 1024 || L3KB_size > 102400)
{
if(L3KB_size < 1024 || L3KB_size > 102400)
printer::inst()->print_msg(L0, "Autoconf failed: L3 size sanity check failed - %u KB.", L3KB_size);
conf += std::string(" { \"low_power_mode\" : false, \"no_prefetch\" : true, \"affine_to_cpu\" : false },\n");
printer::inst()->print_msg(L0, "Autoconf FAILED. Create config for a single thread. Please try to add new ones until the hashrate slows down.");
}
else
{
printer::inst()->print_msg(L0, "Autoconf L3 size detected at %u KB.", L3KB_size);
detectCPUConf();
printer::inst()->print_msg(L0, "Autoconf core count detected as %u on %s.", corecnt,
linux_layout ? "Linux" : "Windows");
uint32_t aff_id = 0;
for(uint32_t i=0; i < corecnt; i++)
{
bool double_mode;
if(L3KB_size <= 0)
break;
double_mode = L3KB_size / 2048 > (int32_t)(corecnt-i);
conf += std::string(" { \"low_power_mode\" : ");
conf += std::string(double_mode ? "true" : "false");
conf += std::string(", \"no_prefetch\" : true, \"affine_to_cpu\" : ");
conf += std::to_string(aff_id);
conf += std::string(" },\n");
if(!linux_layout || old_amd)
{
aff_id += 2;
if(aff_id >= corecnt)
aff_id = 1;
}
else
aff_id++;
if(double_mode)
L3KB_size -= 4096;
else
L3KB_size -= 2048;
}
}
configTpl.replace("CPUCONFIG",conf);
configTpl.write(params::inst().configFileCPU);
printer::inst()->print_msg(L0, "CPU configuration stored in file '%s'", params::inst().configFileCPU.c_str());
return true;
}
private:
bool detectL3Size()
{
int32_t cpu_info[4];
char cpustr[13] = {0};
::jconf::cpuid(0, 0, cpu_info);
memcpy(cpustr, &cpu_info[1], 4);
memcpy(cpustr+4, &cpu_info[3], 4);
memcpy(cpustr+8, &cpu_info[2], 4);
if(strcmp(cpustr, "GenuineIntel") == 0)
{
::jconf::cpuid(4, 3, cpu_info);
if(get_masked(cpu_info[0], 7, 5) != 3)
{
printer::inst()->print_msg(L0, "Autoconf failed: Couln't find L3 cache page.");
return false;
}
L3KB_size = ((get_masked(cpu_info[1], 31, 22) + 1) * (get_masked(cpu_info[1], 21, 12) + 1) *
(get_masked(cpu_info[1], 11, 0) + 1) * (cpu_info[2] + 1)) / 1024;
return true;
}
else if(strcmp(cpustr, "AuthenticAMD") == 0)
{
::jconf::cpuid(0x80000006, 0, cpu_info);
L3KB_size = get_masked(cpu_info[3], 31, 18) * 512;
::jconf::cpuid(1, 0, cpu_info);
if(get_masked(cpu_info[0], 11, 8) < 0x17) //0x17h is Zen
old_amd = true;
return true;
}
else
{
printer::inst()->print_msg(L0, "Autoconf failed: Unknown CPU type: %s.", cpustr);
return false;
}
}
void detectCPUConf()
{
#ifdef _WIN32
SYSTEM_INFO info;
GetSystemInfo(&info);
corecnt = info.dwNumberOfProcessors;
linux_layout = false;
#else
corecnt = sysconf(_SC_NPROCESSORS_ONLN);
linux_layout = true;
#endif // _WIN32
}
int32_t L3KB_size = 0;
uint32_t corecnt;
bool old_amd = false;
bool linux_layout;
};
} // namespace cpu
} // namepsace xmrstak
@@ -1,8 +1,8 @@
#pragma once
#include "console.h"
#include <hwloc.h>
#include <stdio.h>
#include "xmrstak/misc/console.hpp"
#include "xmrstak/misc/configEditor.hpp"
#include "xmrstak/params.hpp"
#ifdef _WIN32
#include <windows.h>
@@ -10,6 +10,17 @@
#include <unistd.h>
#endif // _WIN32
#include <string>
#include <hwloc.h>
#include <stdio.h>
namespace xmrstak
{
namespace cpu
{
class autoAdjust
{
public:
@@ -18,17 +29,22 @@ public:
{
}
void printConfig()
bool printConfig()
{
printer::inst()->print_str("The configuration for 'cpu_threads_conf' in your config file is 'null'.\n");
printer::inst()->print_str("The miner evaluates your system and prints a suggestion for the section `cpu_threads_conf` to the terminal.\n");
printer::inst()->print_str("The values are not optimal, please try to tweak the values based on notes in config.txt.\n");
printer::inst()->print_str("Please copy & paste the block within the asterisks to your config.\n\n");
hwloc_topology_t topology;
hwloc_topology_init(&topology);
hwloc_topology_load(topology);
std::string conf;
configEditor configTpl{};
// load the template of the backend config into a char variable
const char *tpl =
#include "./config.tpl"
;
configTpl.set( std::string(tpl) );
try
{
std::vector<hwloc_obj_t> tlcs;
@@ -43,32 +59,30 @@ public:
for(hwloc_obj_t obj : tlcs)
proccessTopLevelCache(obj);
printer::inst()->print_str("\n**************** Copy&Paste BEGIN ****************\n\n");
printer::inst()->print_str("\"cpu_threads_conf\" :\n[\n");
for(uint32_t id : results)
{
char str[128];
snprintf(str, sizeof(str), " { \"low_power_mode\" : %s, \"no_prefetch\" : true, \"affine_to_cpu\" : %u },\n",
(id & 0x8000000) != 0 ? "true" : "false", id & 0x7FFFFFF);
printer::inst()->print_str(str);
conf += std::string(" { \"low_power_mode\" : ");
conf += std::string((id & 0x8000000) != 0 ? "true" : "false");
conf += std::string(", \"no_prefetch\" : true, \"affine_to_cpu\" : ");
conf += std::to_string(id & 0x7FFFFFF);
conf += std::string(" },\n");
}
printer::inst()->print_str("],\n\n**************** Copy&Paste END ****************\n");
}
catch(const std::runtime_error& err)
{
printer::inst()->print_msg(L0, "Autoconf FAILED: %s", err.what());
printer::inst()->print_str("\nPrinting config for a single thread. Please try to add new ones until the hashrate slows down.\n");
printer::inst()->print_str("\n**************** FAILURE Copy&Paste BEGIN ****************\n\n");
printer::inst()->print_str("\"cpu_threads_conf\" :\n[\n");
printer::inst()->print_str(" { \"low_power_mode\" : false, \"no_prefetch\" : true, \"affine_to_cpu\" : false },\n");
printer::inst()->print_str("],\n\n**************** FAILURE Copy&Paste END ****************\n");
// \todo add fallback to default auto adjust
conf += std::string(" { \"low_power_mode\" : false, \"no_prefetch\" : true, \"affine_to_cpu\" : false },\n");
printer::inst()->print_msg(L0, "Autoconf FAILED: %s. Create config for a single thread.", err.what());
}
configTpl.replace("CPUCONFIG",conf);
configTpl.write(params::inst().configFileCPU);
printer::inst()->print_msg(L0, "CPU configuration stored in file '%s'", params::inst().configFileCPU.c_str());
/* Destroy topology object. */
hwloc_topology_destroy(topology);
return true;
}
private:
@@ -193,3 +207,6 @@ private:
}
}
};
} // namespace cpu
} // namepsace xmrstak
+32
View File
@@ -0,0 +1,32 @@
R"===(
/*
* Thread configuration for each thread. Make sure it matches the number above.
* low_power_mode - This mode will double the cache usage, and double the single thread performance. It will
* consume much less power (as less cores are working), but will max out at around 80-85% of
* the maximum performance.
*
* no_prefetch - Some sytems can gain up to extra 5% here, but sometimes it will have no difference or make
* things slower.
*
* affine_to_cpu - This can be either false (no affinity), or the CPU core number. Note that on hyperthreading
* systems it is better to assign threads to physical cores. On Windows this usually means selecting
* even or odd numbered cpu numbers. For Linux it will be usually the lower CPU numbers, so for a 4
* physical core CPU you should select cpu numbers 0-3.
*
* On the first run the miner will look at your system and suggest a basic configuration that will work,
* you can try to tweak it from there to get the best performance.
*
* A filled out configuration should look like this:
* "cpu_threads_conf" :
* [
* { "low_power_mode" : false, "no_prefetch" : true, "affine_to_cpu" : 0 },
* { "low_power_mode" : false, "no_prefetch" : true, "affine_to_cpu" : 1 },
* ],
*/
"cpu_threads_conf" :
[
CPUCONFIG
],
)==="
@@ -1,6 +1,6 @@
#pragma once
#include "console.h"
#include "xmrstak/misc/console.hpp"
#ifndef CONF_NO_HWLOC
+255
View File
@@ -0,0 +1,255 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with OpenSSL (or a modified version of that library), containing parts
* covered by the terms of OpenSSL License and SSLeay License, the licensors
* of this Program grant you additional permission to convey the resulting work.
*
*/
#include "jconf.hpp"
#include "xmrstak/misc/console.hpp"
#include "xmrstak/misc/jext.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#ifdef _WIN32
#define strcasecmp _stricmp
#include <intrin.h>
#else
#include <cpuid.h>
#endif
namespace xmrstak
{
namespace cpu
{
using namespace rapidjson;
/*
* This enum needs to match index in oConfigValues, otherwise we will get a runtime error
*/
enum configEnum { aCpuThreadsConf, sUseSlowMem };
struct configVal {
configEnum iName;
const char* sName;
Type iType;
};
// Same order as in configEnum, as per comment above
// kNullType means any type
configVal oConfigValues[] = {
{ aCpuThreadsConf, "cpu_threads_conf", kNullType }
};
constexpr size_t iConfigCnt = (sizeof(oConfigValues)/sizeof(oConfigValues[0]));
inline bool checkType(Type have, Type want)
{
if(want == have)
return true;
else if(want == kNullType)
return true;
else if(want == kTrueType && have == kFalseType)
return true;
else if(want == kFalseType && have == kTrueType)
return true;
else
return false;
}
struct jconf::opaque_private
{
Document jsonDoc;
const Value* configValues[iConfigCnt]; //Compile time constant
opaque_private()
{
}
};
jconf* jconf::oInst = nullptr;
jconf::jconf()
{
prv = new opaque_private();
}
bool jconf::GetThreadConfig(size_t id, thd_cfg &cfg)
{
if(!prv->configValues[aCpuThreadsConf]->IsArray())
return false;
if(id >= prv->configValues[aCpuThreadsConf]->Size())
return false;
const Value& oThdConf = prv->configValues[aCpuThreadsConf]->GetArray()[id];
if(!oThdConf.IsObject())
return false;
const Value *mode, *no_prefetch, *aff;
mode = GetObjectMember(oThdConf, "low_power_mode");
no_prefetch = GetObjectMember(oThdConf, "no_prefetch");
aff = GetObjectMember(oThdConf, "affine_to_cpu");
if(mode == nullptr || no_prefetch == nullptr || aff == nullptr)
return false;
if(!mode->IsBool() || !no_prefetch->IsBool())
return false;
if(!aff->IsNumber() && !aff->IsBool())
return false;
if(aff->IsNumber() && aff->GetInt64() < 0)
return false;
cfg.bDoubleMode = mode->GetBool();
cfg.bNoPrefetch = no_prefetch->GetBool();
if(aff->IsNumber())
cfg.iCpuAff = aff->GetInt64();
else
cfg.iCpuAff = -1;
return true;
}
size_t jconf::GetThreadCount()
{
if(prv->configValues[aCpuThreadsConf]->IsArray())
return prv->configValues[aCpuThreadsConf]->Size();
else
return 0;
}
bool jconf::parse_config(const char* sFilename)
{
FILE * pFile;
char * buffer;
size_t flen;
pFile = fopen(sFilename, "rb");
if (pFile == NULL)
{
printer::inst()->print_msg(L0, "Failed to open config file %s.", sFilename);
return false;
}
fseek(pFile,0,SEEK_END);
flen = ftell(pFile);
rewind(pFile);
if(flen >= 64*1024)
{
fclose(pFile);
printer::inst()->print_msg(L0, "Oversized config file - %s.", sFilename);
return false;
}
if(flen <= 16)
{
fclose(pFile);
printer::inst()->print_msg(L0, "File is empty or too short - %s.", sFilename);
return false;
}
buffer = (char*)malloc(flen + 3);
if(fread(buffer+1, flen, 1, pFile) != 1)
{
free(buffer);
fclose(pFile);
printer::inst()->print_msg(L0, "Read error while reading %s.", sFilename);
return false;
}
fclose(pFile);
//Replace Unicode BOM with spaces - we always use UTF-8
unsigned char* ubuffer = (unsigned char*)buffer;
if(ubuffer[1] == 0xEF && ubuffer[2] == 0xBB && ubuffer[3] == 0xBF)
{
buffer[1] = ' ';
buffer[2] = ' ';
buffer[3] = ' ';
}
buffer[0] = '{';
buffer[flen] = '}';
buffer[flen + 1] = '\0';
prv->jsonDoc.Parse<kParseCommentsFlag|kParseTrailingCommasFlag>(buffer, flen+2);
free(buffer);
if(prv->jsonDoc.HasParseError())
{
printer::inst()->print_msg(L0, "JSON config parse error(offset %llu): %s",
int_port(prv->jsonDoc.GetErrorOffset()), GetParseError_En(prv->jsonDoc.GetParseError()));
return false;
}
if(!prv->jsonDoc.IsObject())
{ //This should never happen as we created the root ourselves
printer::inst()->print_msg(L0, "Invalid config file. No root?\n");
return false;
}
for(size_t i = 0; i < iConfigCnt; i++)
{
if(oConfigValues[i].iName != i)
{
printer::inst()->print_msg(L0, "Code error. oConfigValues are not in order.");
return false;
}
prv->configValues[i] = GetObjectMember(prv->jsonDoc, oConfigValues[i].sName);
if(prv->configValues[i] == nullptr)
{
printer::inst()->print_msg(L0, "Invalid config file. Missing value \"%s\".", oConfigValues[i].sName);
return false;
}
if(!checkType(prv->configValues[i]->GetType(), oConfigValues[i].iType))
{
printer::inst()->print_msg(L0, "Invalid config file. Value \"%s\" has unexpected type.", oConfigValues[i].sName);
return false;
}
}
thd_cfg c;
for(size_t i=0; i < GetThreadCount(); i++)
{
if(!GetThreadConfig(i, c))
{
printer::inst()->print_msg(L0, "Thread %llu has invalid config.", int_port(i));
return false;
}
}
return true;
}
} // namespace cpu
} // namepsace xmrstak
+46
View File
@@ -0,0 +1,46 @@
#pragma once
#include "xmrstak/params.hpp"
#include <stdlib.h>
#include <string>
namespace xmrstak
{
namespace cpu
{
class jconf
{
public:
static jconf* inst()
{
if (oInst == nullptr) oInst = new jconf;
return oInst;
};
bool parse_config(const char* sFilename = params::inst().configFileCPU.c_str());
struct thd_cfg {
bool bDoubleMode;
bool bNoPrefetch;
long long iCpuAff;
};
size_t GetThreadCount();
bool GetThreadConfig(size_t id, thd_cfg &cfg);
bool NeedsAutoconf();
private:
jconf();
static jconf* oInst;
struct opaque_private;
opaque_private* prv;
};
} // namespace cpu
} // namepsace xmrstak
+92 -136
View File
@@ -21,21 +21,51 @@
*
*/
#include "crypto/cryptonight_aesni.h"
#include "xmrstak/misc/console.hpp"
#include "xmrstak/backend/iBackend.hpp"
#include "xmrstak/backend//globalStates.hpp"
#include "xmrstak/misc/configEditor.hpp"
#include "xmrstak/params.hpp"
#include "jconf.hpp"
#include "xmrstak/misc/executor.hpp"
#include "minethd.hpp"
#include "xmrstak/jconf.hpp"
#include "hwlocMemory.hpp"
#include "xmrstak/backend/miner_work.hpp"
#ifndef CONF_NO_HWLOC
# include "autoAdjustHwloc.hpp"
#else
# include "autoAdjust.hpp"
#endif
#include <assert.h>
#include <cmath>
#include <chrono>
#include <cstring>
#include <thread>
#include <bitset>
#include "console.h"
#ifdef _WIN32
#include <windows.h>
void thd_setaffinity(std::thread::native_handle_type h, uint64_t cpu_id)
namespace xmrstak
{
namespace cpu
{
void minethd::thd_setaffinity(std::thread::native_handle_type h, uint64_t cpu_id)
{
SetThreadAffinityMask(h, 1ULL << cpu_id);
}
} // namespace cpu
} // namespace xmrstak
#else
#include <pthread.h>
@@ -47,8 +77,12 @@ void thd_setaffinity(std::thread::native_handle_type h, uint64_t cpu_id)
#include <pthread_np.h>
#endif
namespace xmrstak
{
namespace cpu
{
void thd_setaffinity(std::thread::native_handle_type h, uint64_t cpu_id)
void minethd::thd_setaffinity(std::thread::native_handle_type h, uint64_t cpu_id)
{
#if defined(__APPLE__)
thread_port_t mach_thread;
@@ -67,88 +101,17 @@ void thd_setaffinity(std::thread::native_handle_type h, uint64_t cpu_id)
pthread_setaffinity_np(h, sizeof(cpu_set_t), &mn);
#endif
}
} // namespace cpu
} // namespace xmrstak
#endif // _WIN32
#include "executor.h"
#include "minethd.h"
#include "jconf.h"
#include "crypto/cryptonight_aesni.h"
#include "hwlocMemory.hpp"
telemetry::telemetry(size_t iThd)
namespace xmrstak
{
ppHashCounts = new uint64_t*[iThd];
ppTimestamps = new uint64_t*[iThd];
iBucketTop = new uint32_t[iThd];
for (size_t i = 0; i < iThd; i++)
{
ppHashCounts[i] = new uint64_t[iBucketSize];
ppTimestamps[i] = new uint64_t[iBucketSize];
iBucketTop[i] = 0;
memset(ppHashCounts[0], 0, sizeof(uint64_t) * iBucketSize);
memset(ppTimestamps[0], 0, sizeof(uint64_t) * iBucketSize);
}
}
double telemetry::calc_telemetry_data(size_t iLastMilisec, size_t iThread)
namespace cpu
{
using namespace std::chrono;
uint64_t iTimeNow = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
uint64_t iEarliestHashCnt = 0;
uint64_t iEarliestStamp = 0;
uint64_t iLastestStamp = 0;
uint64_t iLastestHashCnt = 0;
bool bHaveFullSet = false;
//Start at 1, buckettop points to next empty
for (size_t i = 1; i < iBucketSize; i++)
{
size_t idx = (iBucketTop[iThread] - i) & iBucketMask; //overflow expected here
if (ppTimestamps[iThread][idx] == 0)
break; //That means we don't have the data yet
if (iLastestStamp == 0)
{
iLastestStamp = ppTimestamps[iThread][idx];
iLastestHashCnt = ppHashCounts[iThread][idx];
}
if (iTimeNow - ppTimestamps[iThread][idx] > iLastMilisec)
{
bHaveFullSet = true;
break; //We are out of the requested time period
}
iEarliestStamp = ppTimestamps[iThread][idx];
iEarliestHashCnt = ppHashCounts[iThread][idx];
}
if (!bHaveFullSet || iEarliestStamp == 0 || iLastestStamp == 0)
return nan("");
//Don't think that can happen, but just in case
if (iLastestStamp - iEarliestStamp == 0)
return nan("");
double fHashes, fTime;
fHashes = iLastestHashCnt - iEarliestHashCnt;
fTime = iLastestStamp - iEarliestStamp;
fTime /= 1000.0;
return fHashes / fTime;
}
void telemetry::push_perf_value(size_t iThd, uint64_t iHashCount, uint64_t iTimestamp)
{
size_t iTop = iBucketTop[iThd];
ppHashCounts[iThd][iTop] = iHashCount;
ppTimestamps[iThd][iTop] = iTimestamp;
iBucketTop[iThd] = (iTop + 1) & iBucketMask;
}
minethd::minethd(miner_work& pWork, size_t iNo, bool double_work, bool no_prefetch, int64_t affinity)
{
@@ -156,8 +119,6 @@ minethd::minethd(miner_work& pWork, size_t iNo, bool double_work, bool no_prefet
bQuit = 0;
iThreadNo = (uint8_t)iNo;
iJobNo = 0;
iHashCount = 0;
iTimestamp = 0;
bNoPrefetch = no_prefetch;
this->affinity = affinity;
@@ -168,31 +129,26 @@ minethd::minethd(miner_work& pWork, size_t iNo, bool double_work, bool no_prefet
oWorkThd = std::thread(&minethd::work_main, this);
}
std::atomic<uint64_t> minethd::iGlobalJobNo;
std::atomic<uint64_t> minethd::iConsumeCnt; //Threads get jobs as they are initialized
minethd::miner_work minethd::oGlobalWork;
uint64_t minethd::iThreadCount = 0;
cryptonight_ctx* minethd_alloc_ctx()
cryptonight_ctx* minethd::minethd_alloc_ctx()
{
cryptonight_ctx* ctx;
alloc_msg msg = { 0 };
switch (jconf::inst()->GetSlowMemSetting())
switch (::jconf::inst()->GetSlowMemSetting())
{
case jconf::never_use:
case ::jconf::never_use:
ctx = cryptonight_alloc_ctx(1, 1, &msg);
if (ctx == NULL)
printer::inst()->print_msg(L0, "MEMORY ALLOC FAILED: %s", msg.warning);
return ctx;
case jconf::no_mlck:
case ::jconf::no_mlck:
ctx = cryptonight_alloc_ctx(1, 0, &msg);
if (ctx == NULL)
printer::inst()->print_msg(L0, "MEMORY ALLOC FAILED: %s", msg.warning);
return ctx;
case jconf::print_warning:
case ::jconf::print_warning:
ctx = cryptonight_alloc_ctx(1, 1, &msg);
if (msg.warning != NULL)
printer::inst()->print_msg(L0, "MEMORY ALLOC FAILED: %s", msg.warning);
@@ -200,10 +156,10 @@ cryptonight_ctx* minethd_alloc_ctx()
ctx = cryptonight_alloc_ctx(0, 0, NULL);
return ctx;
case jconf::always_use:
case ::jconf::always_use:
return cryptonight_alloc_ctx(0, 0, NULL);
case jconf::unknown_value:
case ::jconf::unknown_value:
return NULL; //Shut up compiler
}
@@ -216,27 +172,27 @@ bool minethd::self_test()
size_t res;
bool fatal = false;
switch (jconf::inst()->GetSlowMemSetting())
switch (::jconf::inst()->GetSlowMemSetting())
{
case jconf::never_use:
case ::jconf::never_use:
res = cryptonight_init(1, 1, &msg);
fatal = true;
break;
case jconf::no_mlck:
case ::jconf::no_mlck:
res = cryptonight_init(1, 0, &msg);
fatal = true;
break;
case jconf::print_warning:
case ::jconf::print_warning:
res = cryptonight_init(1, 1, &msg);
break;
case jconf::always_use:
case ::jconf::always_use:
res = cryptonight_init(0, 0, &msg);
break;
case jconf::unknown_value:
case ::jconf::unknown_value:
default:
return false; //Shut up compiler
}
@@ -263,20 +219,20 @@ bool minethd::self_test()
cn_hash_fun hashf;
cn_hash_fun_dbl hashdf;
hashf = func_selector(jconf::inst()->HaveHardwareAes(), false);
hashf = func_selector(::jconf::inst()->HaveHardwareAes(), false);
hashf("This is a test", 14, out, ctx0);
bResult = memcmp(out, "\xa0\x84\xf0\x1d\x14\x37\xa0\x9c\x69\x85\x40\x1b\x60\xd4\x35\x54\xae\x10\x58\x02\xc5\xf5\xd8\xa9\xb3\x25\x36\x49\xc0\xbe\x66\x05", 32) == 0;
hashf = func_selector(jconf::inst()->HaveHardwareAes(), true);
hashf = func_selector(::jconf::inst()->HaveHardwareAes(), true);
hashf("This is a test", 14, out, ctx0);
bResult &= memcmp(out, "\xa0\x84\xf0\x1d\x14\x37\xa0\x9c\x69\x85\x40\x1b\x60\xd4\x35\x54\xae\x10\x58\x02\xc5\xf5\xd8\xa9\xb3\x25\x36\x49\xc0\xbe\x66\x05", 32) == 0;
hashdf = func_dbl_selector(jconf::inst()->HaveHardwareAes(), false);
hashdf = func_dbl_selector(::jconf::inst()->HaveHardwareAes(), false);
hashdf("The quick brown fox jumps over the lazy dogThe quick brown fox jumps over the lazy log", 43, out, ctx0, ctx1);
bResult &= memcmp(out, "\x3e\xbb\x7f\x9f\x7d\x27\x3d\x7c\x31\x8d\x86\x94\x77\x55\x0c\xc8\x00\xcf\xb1\x1b\x0c\xad\xb7\xff\xbd\xf6\xf8\x9f\x3a\x47\x1c\x59"
"\xb4\x77\xd5\x02\xe4\xd8\x48\x7f\x42\xdf\xe3\x8e\xed\x73\x81\x7a\xda\x91\xb7\xe2\x63\xd2\x91\x71\xb6\x5c\x44\x3a\x01\x2a\x41\x22", 64) == 0;
hashdf = func_dbl_selector(jconf::inst()->HaveHardwareAes(), true);
hashdf = func_dbl_selector(::jconf::inst()->HaveHardwareAes(), true);
hashdf("The quick brown fox jumps over the lazy dogThe quick brown fox jumps over the lazy log", 43, out, ctx0, ctx1);
bResult &= memcmp(out, "\x3e\xbb\x7f\x9f\x7d\x27\x3d\x7c\x31\x8d\x86\x94\x77\x55\x0c\xc8\x00\xcf\xb1\x1b\x0c\xad\xb7\xff\xbd\xf6\xf8\x9f\x3a\x47\x1c\x59"
"\xb4\x77\xd5\x02\xe4\xd8\x48\x7f\x42\xdf\xe3\x8e\xed\x73\x81\x7a\xda\x91\xb7\xe2\x63\xd2\x91\x71\xb6\x5c\x44\x3a\x01\x2a\x41\x22", 64) == 0;
@@ -291,24 +247,36 @@ bool minethd::self_test()
return bResult;
}
std::vector<minethd*>* minethd::thread_starter(miner_work& pWork)
std::vector<iBackend*> minethd::thread_starter(uint32_t threadOffset, miner_work& pWork)
{
iGlobalJobNo = 0;
iConsumeCnt = 0;
std::vector<minethd*>* pvThreads = new std::vector<minethd*>;
std::vector<iBackend*> pvThreads;
if(!configEditor::file_exist(params::inst().configFileCPU))
{
autoAdjust adjust;
if(!adjust.printConfig())
return pvThreads;
}
if(!jconf::inst()->parse_config())
{
win_exit();
}
//Launch the requested number of single and double threads, to distribute
//load evenly we need to alternate single and double threads
size_t i, n = jconf::inst()->GetThreadCount();
pvThreads->reserve(n);
pvThreads.reserve(n);
jconf::thd_cfg cfg;
for (i = 0; i < n; i++)
{
jconf::inst()->GetThreadConfig(i, cfg);
minethd* thd = new minethd(pWork, i, cfg.bDoubleMode, cfg.bNoPrefetch, cfg.iCpuAff);
pvThreads->push_back(thd);
// \todo need thread offset
minethd* thd = new minethd(pWork, i + threadOffset, cfg.bDoubleMode, cfg.bNoPrefetch, cfg.iCpuAff);
pvThreads.push_back(thd);
if(cfg.iCpuAff >= 0)
printer::inst()->print_msg(L1, "Starting %s thread, affinity: %d.", cfg.bDoubleMode ? "double" : "single", (int)cfg.iCpuAff);
@@ -316,29 +284,14 @@ std::vector<minethd*>* minethd::thread_starter(miner_work& pWork)
printer::inst()->print_msg(L1, "Starting %s thread, no affinity.", cfg.bDoubleMode ? "double" : "single");
}
iThreadCount = n;
return pvThreads;
}
void minethd::switch_work(miner_work& pWork)
{
// iConsumeCnt is a basic lock-like polling mechanism just in case we happen to push work
// faster than threads can consume them. This should never happen in real life.
// Pool cant physically send jobs faster than every 250ms or so due to net latency.
while (iConsumeCnt.load(std::memory_order_seq_cst) < iThreadCount)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
oGlobalWork = pWork;
iConsumeCnt.store(0, std::memory_order_seq_cst);
iGlobalJobNo++;
}
void minethd::consume_work()
{
memcpy(&oWork, &oGlobalWork, sizeof(miner_work));
memcpy(&oWork, &globalStates::inst().inst().oGlobalWork, sizeof(miner_work));
iJobNo++;
iConsumeCnt++;
globalStates::inst().inst().iConsumeCnt++;
}
minethd::cn_hash_fun minethd::func_selector(bool bHaveAes, bool bNoPrefetch)
@@ -388,12 +341,12 @@ void minethd::work_main()
uint32_t* piNonce;
job_result result;
hash_fun = func_selector(jconf::inst()->HaveHardwareAes(), bNoPrefetch);
hash_fun = func_selector(::jconf::inst()->HaveHardwareAes(), bNoPrefetch);
ctx = minethd_alloc_ctx();
piHashVal = (uint64_t*)(result.bResult + 24);
piNonce = (uint32_t*)(oWork.bWorkBlob + 39);
iConsumeCnt++;
globalStates::inst().inst().iConsumeCnt++;
while (bQuit == 0)
{
@@ -403,7 +356,7 @@ void minethd::work_main()
either because of network latency, or a socket problem. Since we are
raison d'etre of this software it us sensible to just wait until we have something*/
while (iGlobalJobNo.load(std::memory_order_relaxed) == iJobNo)
while (globalStates::inst().inst().iGlobalJobNo.load(std::memory_order_relaxed) == iJobNo)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
consume_work();
@@ -418,7 +371,7 @@ void minethd::work_main()
assert(sizeof(job_result::sJobID) == sizeof(pool_job::sJobID));
memcpy(result.sJobID, oWork.sJobID, sizeof(job_result::sJobID));
while(iGlobalJobNo.load(std::memory_order_relaxed) == iJobNo)
while(globalStates::inst().inst().iGlobalJobNo.load(std::memory_order_relaxed) == iJobNo)
{
if ((iCount & 0xF) == 0) //Store stats every 16 hashes
{
@@ -482,7 +435,7 @@ void minethd::double_work_main()
uint32_t iNonce;
job_result res;
hash_fun = func_dbl_selector(jconf::inst()->HaveHardwareAes(), bNoPrefetch);
hash_fun = func_dbl_selector(::jconf::inst()->HaveHardwareAes(), bNoPrefetch);
ctx0 = minethd_alloc_ctx();
ctx1 = minethd_alloc_ctx();
@@ -491,7 +444,7 @@ void minethd::double_work_main()
piNonce0 = (uint32_t*)(bDoubleWorkBlob + 39);
piNonce1 = nullptr;
iConsumeCnt++;
globalStates::inst().inst().iConsumeCnt++;
while (bQuit == 0)
{
@@ -501,7 +454,7 @@ void minethd::double_work_main()
either because of network latency, or a socket problem. Since we are
raison d'etre of this software it us sensible to just wait until we have something*/
while (iGlobalJobNo.load(std::memory_order_relaxed) == iJobNo)
while (globalStates::inst().inst().iGlobalJobNo.load(std::memory_order_relaxed) == iJobNo)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
consume_work();
@@ -518,7 +471,7 @@ void minethd::double_work_main()
assert(sizeof(job_result::sJobID) == sizeof(pool_job::sJobID));
while (iGlobalJobNo.load(std::memory_order_relaxed) == iJobNo)
while (globalStates::inst().inst().iGlobalJobNo.load(std::memory_order_relaxed) == iJobNo)
{
if ((iCount & 0x7) == 0) //Store stats every 16 hashes
{
@@ -553,3 +506,6 @@ void minethd::double_work_main()
cryptonight_free_ctx(ctx0);
cryptonight_free_ctx(ctx1);
}
} // namespace cpu
} // namepsace xmrstak
+59
View File
@@ -0,0 +1,59 @@
#pragma once
#include "crypto/cryptonight.h"
#include "xmrstak/backend/miner_work.hpp"
#include "xmrstak/backend/iBackend.hpp"
#include <iostream>
#include <thread>
#include <vector>
#include <atomic>
#include <mutex>
namespace xmrstak
{
namespace cpu
{
class minethd : public iBackend
{
public:
static std::vector<iBackend*> thread_starter(uint32_t threadOffset, miner_work& pWork);
static bool self_test();
typedef void (*cn_hash_fun)(const void*, size_t, void*, cryptonight_ctx*);
static cn_hash_fun func_selector(bool bHaveAes, bool bNoPrefetch);
static void thd_setaffinity(std::thread::native_handle_type h, uint64_t cpu_id);
static cryptonight_ctx* minethd_alloc_ctx();
private:
typedef void (*cn_hash_fun_dbl)(const void*, size_t, void*, cryptonight_ctx* __restrict, cryptonight_ctx* __restrict);
static cn_hash_fun_dbl func_dbl_selector(bool bHaveAes, bool bNoPrefetch);
minethd(miner_work& pWork, size_t iNo, bool double_work, bool no_prefetch, int64_t affinity);
void work_main();
void double_work_main();
void consume_work();
uint64_t iJobNo;
static miner_work oGlobalWork;
miner_work oWork;
void pin_thd_affinity();
// Held by the creating context to prevent a race cond with oWorkThd = std::thread(...)
std::mutex work_thd_mtx;
std::thread oWorkThd;
int64_t affinity;
bool bQuit;
bool bNoPrefetch;
};
} // namespace cpu
} // namepsace xmrstak
+51
View File
@@ -0,0 +1,51 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with OpenSSL (or a modified version of that library), containing parts
* covered by the terms of OpenSSL License and SSLeay License, the licensors
* of this Program grant you additional permission to convey the resulting work.
*
*/
#include "miner_work.hpp"
#include "globalStates.hpp"
#include <assert.h>
#include <cmath>
#include <chrono>
#include <cstring>
namespace xmrstak
{
void globalStates::switch_work(miner_work& pWork)
{
// iConsumeCnt is a basic lock-like polling mechanism just in case we happen to push work
// faster than threads can consume them. This should never happen in real life.
// Pool cant physically send jobs faster than every 250ms or so due to net latency.
while (iConsumeCnt.load(std::memory_order_seq_cst) < iThreadCount)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
oGlobalWork = pWork;
iConsumeCnt.store(0, std::memory_order_seq_cst);
iGlobalJobNo++;
}
} // namepsace xmrstak
+38
View File
@@ -0,0 +1,38 @@
#pragma once
#include "miner_work.hpp"
#include "xmrstak/misc/environment.hpp"
#include <atomic>
namespace xmrstak
{
struct globalStates
{
static inline globalStates& inst()
{
auto& env = environment::inst();
if(env.pglobalStates == nullptr)
env.pglobalStates = new globalStates;
return *env.pglobalStates;
}
void switch_work(miner_work& pWork);
miner_work oGlobalWork;
std::atomic<uint64_t> iGlobalJobNo;
std::atomic<uint64_t> iConsumeCnt;
uint64_t iThreadCount;
private:
globalStates() : iThreadCount(0)
{
}
};
} // namepsace xmrstak
+53
View File
@@ -0,0 +1,53 @@
#pragma once
#include "xmrstak/backend/globalStates.hpp"
#include <atomic>
#include <cstdint>
#include <climits>
namespace xmrstak
{
// only allowed for unsigned value \todo add static assert
template<typename T>
T reverseBits(T value)
{
/* init with value (to get LSB) */
T result = value;
/* extra shift needed at end */
int s = sizeof(T) * CHAR_BIT - 1;
for (value >>= 1; value; value >>= 1)
{
result <<= 1;
result |= value & 1;
s--;
}
/* shift when values highest bits are zero */
result <<= s;
return result;
}
struct iBackend
{
inline uint32_t calc_start_nonce(uint32_t resume)
{
return reverseBits<uint32_t>(static_cast<uint32_t>(iThreadNo + globalStates::inst().iThreadCount * resume));
}
// Limited version of the nonce calc above
inline uint32_t calc_nicehash_nonce(uint32_t start, uint32_t resume)
{
return start | ( calc_start_nonce(resume) >> 8u );
}
std::atomic<uint64_t> iHashCount;
std::atomic<uint64_t> iTimestamp;
uint32_t iThreadNo;
iBackend() : iHashCount(0), iTimestamp(0)
{
}
};
} // namepsace xmrstak
+85
View File
@@ -0,0 +1,85 @@
#pragma once
#include <thread>
#include <atomic>
#include <mutex>
#include <cstdint>
#include <iostream>
#include <cassert>
#include <cstring>
namespace xmrstak
{
struct miner_work
{
char sJobID[64];
uint8_t bWorkBlob[112];
uint32_t iWorkSize;
uint32_t iResumeCnt;
uint64_t iTarget;
// \todo remove workaround needed for amd
uint32_t iTarget32;
bool bNiceHash;
bool bStall;
size_t iPoolId;
miner_work() : iWorkSize(0), bNiceHash(false), bStall(true), iPoolId(0) { }
miner_work(const char* sJobID, const uint8_t* bWork, uint32_t iWorkSize, uint32_t iResumeCnt,
uint64_t iTarget, size_t iPoolId) : iWorkSize(iWorkSize), iResumeCnt(iResumeCnt),
iTarget(iTarget), bNiceHash(false), bStall(false), iPoolId(iPoolId)
{
assert(iWorkSize <= sizeof(bWorkBlob));
memcpy(this->sJobID, sJobID, sizeof(miner_work::sJobID));
memcpy(this->bWorkBlob, bWork, iWorkSize);
}
miner_work(miner_work const&) = delete;
miner_work& operator=(miner_work const& from)
{
assert(this != &from);
iWorkSize = from.iWorkSize;
iResumeCnt = from.iResumeCnt;
iTarget = from.iTarget;
iTarget32 = from.iTarget32;
bNiceHash = from.bNiceHash;
bStall = from.bStall;
iPoolId = from.iPoolId;
assert(iWorkSize <= sizeof(bWorkBlob));
memcpy(sJobID, from.sJobID, sizeof(sJobID));
memcpy(bWorkBlob, from.bWorkBlob, iWorkSize);
return *this;
}
miner_work(miner_work&& from) : iWorkSize(from.iWorkSize), iTarget(from.iTarget),iTarget32(from.iTarget32),
bStall(from.bStall), iPoolId(from.iPoolId)
{
assert(iWorkSize <= sizeof(bWorkBlob));
memcpy(sJobID, from.sJobID, sizeof(sJobID));
memcpy(bWorkBlob, from.bWorkBlob, iWorkSize);
}
miner_work& operator=(miner_work&& from)
{
assert(this != &from);
iWorkSize = from.iWorkSize;
iResumeCnt = from.iResumeCnt;
iTarget = from.iTarget;
iTarget32 = from.iTarget32;
bNiceHash = from.bNiceHash;
bStall = from.bStall;
iPoolId = from.iPoolId;
assert(iWorkSize <= sizeof(bWorkBlob));
memcpy(sJobID, from.sJobID, sizeof(sJobID));
memcpy(bWorkBlob, from.bWorkBlob, iWorkSize);
return *this;
}
};
} // namepsace xmrstak
+113
View File
@@ -0,0 +1,113 @@
#pragma once
#include "autoAdjust.hpp"
#include "nvcc_code/cryptonight.hpp"
#include "jconf.hpp"
#include "xmrstak/misc/console.hpp"
#include "xmrstak/misc/configEditor.hpp"
#include "xmrstak/params.hpp"
#include <vector>
#include <cstdio>
#include <sstream>
#include <string>
namespace xmrstak
{
namespace nvidia
{
class autoAdjust
{
public:
autoAdjust()
{
}
/** print the adjusted values if needed
*
* Routine exit the application and print the adjusted values if needed else
* nothing is happened.
*/
bool printConfig()
{
int deviceCount = 0;
if(cuda_get_devicecount(&deviceCount) == 0)
return false;
// evaluate config parameter for if auto adjustment is needed
// evaluate config parameter for if auto adjustment is needed
for(int i = 0; i < deviceCount; i++)
{
nvid_ctx ctx;
ctx.device_id = i;
// -1 trigger auto adjustment
ctx.device_blocks = -1;
ctx.device_threads = -1;
// set all evice option those marked as auto (-1) to a valid value
#ifndef _WIN32
ctx.device_bfactor = 0;
ctx.device_bsleep = 0;
#else
// windows pass, try to avoid that windows kills the miner if the gpu is blocked for 2 seconds
ctx.device_bfactor = 6;
ctx.device_bsleep = 25;
#endif
if( cuda_get_deviceinfo(&ctx) != 1 )
{
printer::inst()->print_msg(L0, "Setup failed for GPU %d. Exitting.\n", i);
std::exit(0);
}
nvidCtxVec.push_back(ctx);
}
generateThreadConfig();
return true;
}
private:
void generateThreadConfig()
{
// load the template of the backend config into a char variable
const char *tpl =
#include "./config.tpl"
;
configEditor configTpl{};
configTpl.set( std::string(tpl) );
constexpr size_t byte2mib = 1024u * 1024u;
std::string conf;
int i = 0;
for(auto& ctx : nvidCtxVec)
{
conf += std::string(" // gpu: ") + ctx.name + " architecture: " + std::to_string(ctx.device_arch[0] * 10 + ctx.device_arch[1]) + "\n";
conf += std::string(" // memory: ") + std::to_string(ctx.free_device_memory / byte2mib) + "/" + std::to_string(ctx.total_device_memory / byte2mib) + " MiB\n";
conf += std::string(" { \"index\" : ") + std::to_string(ctx.device_id) + ",\n" +
" \"threads\" : " + std::to_string(ctx.device_threads) + ", \"blocks\" : " + std::to_string(ctx.device_blocks) + ",\n" +
" \"bfactor\" : " + std::to_string(ctx.device_bfactor) + ", \"bsleep\" : " + std::to_string(ctx.device_bsleep) + ",\n" +
" \"affine_to_cpu\" : false,\n" +
" },\n";
++i;
}
configTpl.replace("GPUCONFIG",conf);
configTpl.write(params::inst().configFileNVIDIA);
printer::inst()->print_msg(L0, "NVIDIA: GPU configuration stored in file '%s'", params::inst().configFileNVIDIA.c_str());
}
std::vector<nvid_ctx> nvidCtxVec;
};
} // namespace nvidia
} // namepsace xmrstak
+28
View File
@@ -0,0 +1,28 @@
R"===(
/*
* GPU configuration. You should play around with threads and blocks as the fastest settings will vary.
* index - GPU index number usually starts from 0.
* threads - Number of GPU threads (nothing to do with CPU threads).
* blocks - Number of GPU blocks (nothing to do with CPU threads).
* bfactor - Enables running the Cryptonight kernel in smaller pieces.
* Increase if you want to reduce GPU lag. Recommended setting on GUI systems - 8
* bsleep - Insert a delay of X microseconds between kernel launches.
* Increase if you want to reduce GPU lag. Recommended setting on GUI systems - 100
* affine_to_cpu - This will affine the thread to a CPU. This can make a GPU miner play along nicer with a CPU miner.
*
* On the first run the miner will look at your system and suggest a basic configuration that will work,
* you can try to tweak it from there to get the best performance.
*
* A filled out configuration should look like this:
* "gpu_threads_conf" :
* [
* { "index" : 0, "threads" : 17, "blocks" : 60, "bfactor" : 0, "bsleep" : 0, "affine_to_cpu" : false},
* ],
*/
"gpu_threads_conf" :
[
GPUCONFIG
],
)==="
+270
View File
@@ -0,0 +1,270 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with OpenSSL (or a modified version of that library), containing parts
* covered by the terms of OpenSSL License and SSLeay License, the licensors
* of this Program grant you additional permission to convey the resulting work.
*
*/
#include "jconf.hpp"
#include "xmrstak/misc/jext.hpp"
#include "xmrstak/misc/console.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#define strcasecmp _stricmp
#include <intrin.h>
#else
#include <cpuid.h>
#endif
namespace xmrstak
{
namespace nvidia
{
using namespace rapidjson;
/*
* This enum needs to match index in oConfigValues, otherwise we will get a runtime error
*/
enum configEnum { aGpuThreadsConf };
struct configVal {
configEnum iName;
const char* sName;
Type iType;
};
// Same order as in configEnum, as per comment above
// kNullType means any type
configVal oConfigValues[] = {
{ aGpuThreadsConf, "gpu_threads_conf", kNullType }
};
inline bool checkType(Type have, Type want)
{
if(want == have)
return true;
else if(want == kNullType)
return true;
else if(want == kTrueType && have == kFalseType)
return true;
else if(want == kFalseType && have == kTrueType)
return true;
else
return false;
}
constexpr size_t iConfigCnt = (sizeof(oConfigValues)/sizeof(oConfigValues[0]));
struct jconf::opaque_private
{
Document jsonDoc;
const Value* configValues[iConfigCnt]; //Compile time constant
opaque_private()
{
}
};
bool jconf::NeedsAutoconf()
{
return !prv->configValues[aGpuThreadsConf]->IsArray();
}
jconf* jconf::oInst = nullptr;
jconf::jconf()
{
prv = new opaque_private();
}
size_t jconf::GetGPUThreadCount()
{
if(prv->configValues[aGpuThreadsConf]->IsArray())
return prv->configValues[aGpuThreadsConf]->Size();
else
return 0;
}
bool jconf::GetGPUThreadConfig(size_t id, thd_cfg &cfg)
{
if(!prv->configValues[aGpuThreadsConf]->IsArray())
return false;
if(id >= prv->configValues[aGpuThreadsConf]->Size())
return false;
const Value& oThdConf = prv->configValues[aGpuThreadsConf]->GetArray()[id];
if(!oThdConf.IsObject())
return false;
const Value *gid, *blocks, *threads, *bfactor, *bsleep, *aff;
gid = GetObjectMember(oThdConf, "index");
blocks = GetObjectMember(oThdConf, "blocks");
threads = GetObjectMember(oThdConf, "threads");
bfactor = GetObjectMember(oThdConf, "bfactor");
bsleep = GetObjectMember(oThdConf, "bsleep");
aff = GetObjectMember(oThdConf, "affine_to_cpu");
if(gid == nullptr || blocks == nullptr || threads == nullptr ||
bfactor == nullptr || bsleep == nullptr || aff == nullptr)
{
return false;
}
if(!gid->IsNumber() || gid->GetInt() < 0)
return false;
if(!blocks->IsNumber() || blocks->GetInt() < 0)
return false;
if(!threads->IsNumber() || threads->GetInt() < 0)
return false;
if(!bfactor->IsNumber() || bfactor->GetInt() < 0)
return false;
if(!bsleep->IsNumber() || bsleep->GetInt() < 0)
return false;
if(!aff->IsUint64() && !aff->IsBool())
return false;
cfg.id = gid->GetInt();
cfg.blocks = blocks->GetInt();
cfg.threads = threads->GetInt();
cfg.bfactor = bfactor->GetInt();
cfg.bsleep = bsleep->GetInt();
if(aff->IsNumber())
cfg.cpu_aff = aff->GetInt();
else
cfg.cpu_aff = -1;
return true;
}
bool jconf::parse_config(const char* sFilename)
{
FILE * pFile;
char * buffer;
size_t flen;
pFile = fopen(sFilename, "rb");
if (pFile == NULL)
{
printer::inst()->print_msg(L0, "Failed to open config file %s.", sFilename);
return false;
}
fseek(pFile,0,SEEK_END);
flen = ftell(pFile);
rewind(pFile);
if(flen >= 64*1024)
{
fclose(pFile);
printer::inst()->print_msg(L0, "Oversized config file - %s.", sFilename);
return false;
}
if(flen <= 16)
{
fclose(pFile);
printer::inst()->print_msg(L0, "File is empty or too short - %s.", sFilename);
return false;
}
buffer = (char*)malloc(flen + 3);
if(fread(buffer+1, flen, 1, pFile) != 1)
{
free(buffer);
fclose(pFile);
printer::inst()->print_msg(L0, "Read error while reading %s.", sFilename);
return false;
}
fclose(pFile);
//Replace Unicode BOM with spaces - we always use UTF-8
unsigned char* ubuffer = (unsigned char*)buffer;
if(ubuffer[1] == 0xEF && ubuffer[2] == 0xBB && ubuffer[3] == 0xBF)
{
buffer[1] = ' ';
buffer[2] = ' ';
buffer[3] = ' ';
}
buffer[0] = '{';
buffer[flen] = '}';
buffer[flen + 1] = '\0';
prv->jsonDoc.Parse<kParseCommentsFlag|kParseTrailingCommasFlag>(buffer, flen+2);
free(buffer);
if(prv->jsonDoc.HasParseError())
{
printer::inst()->print_msg(L0, "JSON config parse error(offset %llu): %s",
int_port(prv->jsonDoc.GetErrorOffset()), GetParseError_En(prv->jsonDoc.GetParseError()));
return false;
}
if(!prv->jsonDoc.IsObject())
{ //This should never happen as we created the root ourselves
printer::inst()->print_msg(L0, "Invalid config file. No root?\n");
return false;
}
for(size_t i = 0; i < iConfigCnt; i++)
{
if(oConfigValues[i].iName != i)
{
printer::inst()->print_msg(L0, "Code error. oConfigValues are not in order. %s",oConfigValues[i].sName);
return false;
}
prv->configValues[i] = GetObjectMember(prv->jsonDoc, oConfigValues[i].sName);
if(prv->configValues[i] == nullptr)
{
printer::inst()->print_msg(L0, "Invalid config file. Missing value \"%s\".", oConfigValues[i].sName);
return false;
}
if(!checkType(prv->configValues[i]->GetType(), oConfigValues[i].iType))
{
printer::inst()->print_msg(L0, "Invalid config file. Value \"%s\" has unexpected type.", oConfigValues[i].sName);
return false;
}
}
return true;
}
} // namespace nvidia
} // namespace xmrstak
+51
View File
@@ -0,0 +1,51 @@
#pragma once
#include <stdlib.h>
#include <string>
#include "xmrstak/params.hpp"
namespace xmrstak
{
namespace nvidia
{
class jconf
{
public:
static jconf* inst()
{
if (oInst == nullptr) oInst = new jconf;
return oInst;
};
bool parse_config(const char* sFilename = params::inst().configFileNVIDIA.c_str());
struct thd_cfg {
uint32_t id;
uint32_t blocks;
uint32_t threads;
uint32_t bfactor;
uint32_t bsleep;
bool bDoubleMode;
bool bNoPrefetch;
int32_t cpu_aff;
long long iCpuAff;
};
size_t GetGPUThreadCount();
bool GetGPUThreadConfig(size_t id, thd_cfg &cfg);
bool NeedsAutoconf();
private:
jconf();
static jconf* oInst;
struct opaque_private;
opaque_private* prv;
};
} // namespace nvidia
} // namepsace xmrstak
+272
View File
@@ -0,0 +1,272 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with OpenSSL (or a modified version of that library), containing parts
* covered by the terms of OpenSSL License and SSLeay License, the licensors
* of this Program grant you additional permission to convey the resulting work.
*
*/
#include "minethd.hpp"
#include "autoAdjust.hpp"
#include "xmrstak/misc/console.hpp"
#include "xmrstak/backend/cpu/crypto/cryptonight_aesni.h"
#include "xmrstak/backend/cpu/crypto/cryptonight.h"
#include "xmrstak/backend/cpu/minethd.hpp"
#include "xmrstak/params.hpp"
#include "xmrstak/misc/executor.hpp"
#include "xmrstak/jconf.hpp"
#include "xmrstak/misc/environment.hpp"
#include <assert.h>
#include <cmath>
#include <chrono>
#include <thread>
#include <bitset>
#include <vector>
#ifndef USE_PRECOMPILED_HEADERS
#ifdef WIN32
#include <direct.h>
#include <windows.h>
#else
#include <sys/types.h>
#include <dlfcn.h>
#endif
#include <iostream>
#endif
namespace xmrstak
{
namespace nvidia
{
#ifdef WIN32
HINSTANCE lib_handle;
#else
void *lib_handle;
#endif
minethd::minethd(miner_work& pWork, size_t iNo, const jconf::thd_cfg& cfg)
{
oWork = pWork;
bQuit = 0;
iThreadNo = (uint8_t)iNo;
iJobNo = 0;
ctx.device_id = (int)cfg.id;
ctx.device_blocks = (int)cfg.blocks;
ctx.device_threads = (int)cfg.threads;
ctx.device_bfactor = (int)cfg.bfactor;
ctx.device_bsleep = (int)cfg.bsleep;
oWorkThd = std::thread(&minethd::work_main, this);
}
bool minethd::self_test()
{
cryptonight_ctx* ctx0;
unsigned char out[32];
bool bResult = true;
ctx0 = new cryptonight_ctx;
if(::jconf::inst()->HaveHardwareAes())
{
//cryptonight_hash_ctx("This is a test", 14, out, ctx0);
bResult = memcmp(out, "\xa0\x84\xf0\x1d\x14\x37\xa0\x9c\x69\x85\x40\x1b\x60\xd4\x35\x54\xae\x10\x58\x02\xc5\xf5\xd8\xa9\xb3\x25\x36\x49\xc0\xbe\x66\x05", 32) == 0;
}
else
{
//cryptonight_hash_ctx_soft("This is a test", 14, out, ctx0);
bResult = memcmp(out, "\xa0\x84\xf0\x1d\x14\x37\xa0\x9c\x69\x85\x40\x1b\x60\xd4\x35\x54\xae\x10\x58\x02\xc5\xf5\xd8\xa9\xb3\x25\x36\x49\xc0\xbe\x66\x05", 32) == 0;
}
delete ctx0;
//if(!bResult)
// printer::inst()->print_msg(L0,
// "Cryptonight hash self-test failed. This might be caused by bad compiler optimizations.");
return bResult;
}
extern "C"
{
#ifdef WIN32
__declspec(dllexport)
#endif
std::vector<iBackend*>* xmrstak_start_backend(uint32_t threadOffset, miner_work& pWork, environment& env)
{
environment::inst() = env;
return nvidia::minethd::thread_starter(threadOffset, pWork);
}
} // extern "C"
std::vector<iBackend*>* minethd::thread_starter(uint32_t threadOffset, miner_work& pWork)
{
std::vector<iBackend*>* pvThreads = new std::vector<iBackend*>();
if(!configEditor::file_exist(params::inst().configFileNVIDIA))
{
autoAdjust adjust;
if(!adjust.printConfig())
return pvThreads;
}
if(!jconf::inst()->parse_config())
{
win_exit();
}
int deviceCount = 0;
if(cuda_get_devicecount(&deviceCount) != 1)
{
std::cout<<"WARNING: NVIDIA no device found"<<std::endl;
return pvThreads;
}
size_t i, n = jconf::inst()->GetGPUThreadCount();
pvThreads->reserve(n);
jconf::thd_cfg cfg;
for (i = 0; i < n; i++)
{
jconf::inst()->GetGPUThreadConfig(i, cfg);
minethd* thd = new minethd(pWork, i + threadOffset, cfg);
if(cfg.cpu_aff >= 0)
{
#if defined(__APPLE__)
printer::inst()->print_msg(L1, "WARNING on MacOS thread affinity is only advisory.");
#endif
cpu::minethd::thd_setaffinity(thd->oWorkThd.native_handle(), cfg.cpu_aff);
}
pvThreads->push_back(thd);
if(cfg.cpu_aff >= 0)
printer::inst()->print_msg(L1, "Starting GPU thread, affinity: %d.", (int)cfg.cpu_aff);
else
printer::inst()->print_msg(L1, "Starting GPU thread, no affinity.");
}
return pvThreads;
}
void minethd::switch_work(miner_work& pWork)
{
// iConsumeCnt is a basic lock-like polling mechanism just in case we happen to push work
// faster than threads can consume them. This should never happen in real life.
// Pool cant physically send jobs faster than every 250ms or so due to net latency.
while (globalStates::inst().iConsumeCnt.load(std::memory_order_seq_cst) < globalStates::inst().iThreadCount)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
globalStates::inst().oGlobalWork = pWork;
globalStates::inst().iConsumeCnt.store(0, std::memory_order_seq_cst);
globalStates::inst().iGlobalJobNo++;
}
void minethd::consume_work()
{
memcpy(&oWork, &globalStates::inst().oGlobalWork, sizeof(miner_work));
iJobNo++;
globalStates::inst().iConsumeCnt++;
}
void minethd::work_main()
{
uint64_t iCount = 0;
uint32_t iNonce;
cryptonight_ctx* cpu_ctx;
cpu_ctx = cpu::minethd::minethd_alloc_ctx();
cn_hash_fun hash_fun = cpu::minethd::func_selector(::jconf::inst()->HaveHardwareAes(), true /*bNoPrefetch*/);
globalStates::inst().iConsumeCnt++;
if(/*cuda_get_deviceinfo(&ctx) != 1 ||*/ cryptonight_extra_cpu_init(&ctx) != 1)
{
printer::inst()->print_msg(L0, "Setup failed for GPU %d. Exitting.\n", (int)iThreadNo);
std::exit(0);
}
while (bQuit == 0)
{
if (oWork.bStall)
{
/* We are stalled here because the executor didn't find a job for us yet,
either because of network latency, or a socket problem. Since we are
raison d'etre of this software it us sensible to just wait until we have something*/
while (globalStates::inst().iGlobalJobNo.load(std::memory_order_relaxed) == iJobNo)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
consume_work();
continue;
}
cryptonight_extra_cpu_set_data(&ctx, oWork.bWorkBlob, oWork.iWorkSize);
iNonce = calc_start_nonce(oWork.iResumeCnt);
assert(sizeof(job_result::sJobID) == sizeof(pool_job::sJobID));
while(globalStates::inst().iGlobalJobNo.load(std::memory_order_relaxed) == iJobNo)
{
uint32_t foundNonce[10];
uint32_t foundCount;
cryptonight_extra_cpu_prepare(&ctx, iNonce);
cryptonight_core_cpu_hash(&ctx);
cryptonight_extra_cpu_final(&ctx, iNonce, oWork.iTarget, &foundCount, foundNonce);
for(size_t i = 0; i < foundCount; i++)
{
uint8_t bWorkBlob[112];
uint8_t bResult[32];
memcpy(bWorkBlob, oWork.bWorkBlob, oWork.iWorkSize);
memset(bResult, 0, sizeof(job_result::bResult));
*(uint32_t*)(bWorkBlob + 39) = foundNonce[i];
hash_fun(bWorkBlob, oWork.iWorkSize, bResult, cpu_ctx);
if ( (*((uint64_t*)(bResult + 24))) < oWork.iTarget)
executor::inst()->push_event(ex_event(job_result(oWork.sJobID, foundNonce[i], bResult), oWork.iPoolId));
else
executor::inst()->log_result_error("NVIDIA Invalid Result");
}
iCount += ctx.device_blocks * ctx.device_threads;
iNonce += ctx.device_blocks * ctx.device_threads;
using namespace std::chrono;
uint64_t iStamp = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
iHashCount.store(iCount, std::memory_order_relaxed);
iTimestamp.store(iStamp, std::memory_order_relaxed);
std::this_thread::yield();
}
consume_work();
}
}
} // namespace xmrstak
} //namespace nvidia
+54
View File
@@ -0,0 +1,54 @@
#pragma once
#include "xmrstak/jconf.hpp"
#include "jconf.hpp"
#include "nvcc_code/cryptonight.hpp"
#include "xmrstak/backend/cpu/crypto/cryptonight.h"
#include "xmrstak/backend/iBackend.hpp"
#include "xmrstak/misc/environment.hpp"
#include <iostream>
#include <thread>
#include <atomic>
#include <vector>
namespace xmrstak
{
namespace nvidia
{
class minethd : public iBackend
{
public:
static void switch_work(miner_work& pWork);
static std::vector<iBackend*>* thread_starter(uint32_t threadOffset, miner_work& pWork);
static bool self_test();
private:
typedef void (*cn_hash_fun)(const void*, size_t, void*, cryptonight_ctx*);
minethd(miner_work& pWork, size_t iNo, const jconf::thd_cfg& cfg);
void work_main();
void consume_work();
static std::atomic<uint64_t> iGlobalJobNo;
static std::atomic<uint64_t> iConsumeCnt;
static uint64_t iThreadCount;
uint64_t iJobNo;
static miner_work oGlobalWork;
miner_work oWork;
std::thread oWorkThd;
nvid_ctx ctx;
bool bQuit;
};
} // namespace nvidia
} // namepsace xmrstak
@@ -0,0 +1,48 @@
#pragma once
#include <stdint.h>
#include <string>
typedef struct {
int device_id;
const char *device_name;
int device_arch[2];
int device_mpcount;
int device_blocks;
int device_threads;
int device_bfactor;
int device_bsleep;
uint32_t *d_input;
uint32_t inputlen;
uint32_t *d_result_count;
uint32_t *d_result_nonce;
uint32_t *d_long_state;
uint32_t *d_ctx_state;
uint32_t *d_ctx_a;
uint32_t *d_ctx_b;
uint32_t *d_ctx_key1;
uint32_t *d_ctx_key2;
uint32_t *d_ctx_text;
std::string name;
size_t free_device_memory;
size_t total_device_memory;
} nvid_ctx;
extern "C" {
/** get device count
*
* @param deviceCount[out] cuda device count
* @return error code: 0 == error is occurred, 1 == no error
*/
int cuda_get_devicecount( int* deviceCount);
int cuda_get_deviceinfo(nvid_ctx *ctx);
int cryptonight_extra_cpu_init(nvid_ctx *ctx);
void cryptonight_extra_cpu_set_data( nvid_ctx* ctx, const void *data, uint32_t len);
void cryptonight_extra_cpu_prepare(nvid_ctx* ctx, uint32_t startNonce);
void cryptonight_core_cpu_hash(nvid_ctx* ctx);
void cryptonight_extra_cpu_final(nvid_ctx* ctx, uint32_t startNonce, uint64_t target, uint32_t* rescount, uint32_t *resnonce);
}
@@ -0,0 +1,305 @@
#pragma once
#include <stdint.h>
#define N_COLS 4
#define WPOLY 0x011b
static __constant__ uint32_t d_t_fn[1024] =
{
0xa56363c6U, 0x847c7cf8U, 0x997777eeU, 0x8d7b7bf6U,
0x0df2f2ffU, 0xbd6b6bd6U, 0xb16f6fdeU, 0x54c5c591U,
0x50303060U, 0x03010102U, 0xa96767ceU, 0x7d2b2b56U,
0x19fefee7U, 0x62d7d7b5U, 0xe6abab4dU, 0x9a7676ecU,
0x45caca8fU, 0x9d82821fU, 0x40c9c989U, 0x877d7dfaU,
0x15fafaefU, 0xeb5959b2U, 0xc947478eU, 0x0bf0f0fbU,
0xecadad41U, 0x67d4d4b3U, 0xfda2a25fU, 0xeaafaf45U,
0xbf9c9c23U, 0xf7a4a453U, 0x967272e4U, 0x5bc0c09bU,
0xc2b7b775U, 0x1cfdfde1U, 0xae93933dU, 0x6a26264cU,
0x5a36366cU, 0x413f3f7eU, 0x02f7f7f5U, 0x4fcccc83U,
0x5c343468U, 0xf4a5a551U, 0x34e5e5d1U, 0x08f1f1f9U,
0x937171e2U, 0x73d8d8abU, 0x53313162U, 0x3f15152aU,
0x0c040408U, 0x52c7c795U, 0x65232346U, 0x5ec3c39dU,
0x28181830U, 0xa1969637U, 0x0f05050aU, 0xb59a9a2fU,
0x0907070eU, 0x36121224U, 0x9b80801bU, 0x3de2e2dfU,
0x26ebebcdU, 0x6927274eU, 0xcdb2b27fU, 0x9f7575eaU,
0x1b090912U, 0x9e83831dU, 0x742c2c58U, 0x2e1a1a34U,
0x2d1b1b36U, 0xb26e6edcU, 0xee5a5ab4U, 0xfba0a05bU,
0xf65252a4U, 0x4d3b3b76U, 0x61d6d6b7U, 0xceb3b37dU,
0x7b292952U, 0x3ee3e3ddU, 0x712f2f5eU, 0x97848413U,
0xf55353a6U, 0x68d1d1b9U, 0x00000000U, 0x2cededc1U,
0x60202040U, 0x1ffcfce3U, 0xc8b1b179U, 0xed5b5bb6U,
0xbe6a6ad4U, 0x46cbcb8dU, 0xd9bebe67U, 0x4b393972U,
0xde4a4a94U, 0xd44c4c98U, 0xe85858b0U, 0x4acfcf85U,
0x6bd0d0bbU, 0x2aefefc5U, 0xe5aaaa4fU, 0x16fbfbedU,
0xc5434386U, 0xd74d4d9aU, 0x55333366U, 0x94858511U,
0xcf45458aU, 0x10f9f9e9U, 0x06020204U, 0x817f7ffeU,
0xf05050a0U, 0x443c3c78U, 0xba9f9f25U, 0xe3a8a84bU,
0xf35151a2U, 0xfea3a35dU, 0xc0404080U, 0x8a8f8f05U,
0xad92923fU, 0xbc9d9d21U, 0x48383870U, 0x04f5f5f1U,
0xdfbcbc63U, 0xc1b6b677U, 0x75dadaafU, 0x63212142U,
0x30101020U, 0x1affffe5U, 0x0ef3f3fdU, 0x6dd2d2bfU,
0x4ccdcd81U, 0x140c0c18U, 0x35131326U, 0x2fececc3U,
0xe15f5fbeU, 0xa2979735U, 0xcc444488U, 0x3917172eU,
0x57c4c493U, 0xf2a7a755U, 0x827e7efcU, 0x473d3d7aU,
0xac6464c8U, 0xe75d5dbaU, 0x2b191932U, 0x957373e6U,
0xa06060c0U, 0x98818119U, 0xd14f4f9eU, 0x7fdcdca3U,
0x66222244U, 0x7e2a2a54U, 0xab90903bU, 0x8388880bU,
0xca46468cU, 0x29eeeec7U, 0xd3b8b86bU, 0x3c141428U,
0x79dedea7U, 0xe25e5ebcU, 0x1d0b0b16U, 0x76dbdbadU,
0x3be0e0dbU, 0x56323264U, 0x4e3a3a74U, 0x1e0a0a14U,
0xdb494992U, 0x0a06060cU, 0x6c242448U, 0xe45c5cb8U,
0x5dc2c29fU, 0x6ed3d3bdU, 0xefacac43U, 0xa66262c4U,
0xa8919139U, 0xa4959531U, 0x37e4e4d3U, 0x8b7979f2U,
0x32e7e7d5U, 0x43c8c88bU, 0x5937376eU, 0xb76d6ddaU,
0x8c8d8d01U, 0x64d5d5b1U, 0xd24e4e9cU, 0xe0a9a949U,
0xb46c6cd8U, 0xfa5656acU, 0x07f4f4f3U, 0x25eaeacfU,
0xaf6565caU, 0x8e7a7af4U, 0xe9aeae47U, 0x18080810U,
0xd5baba6fU, 0x887878f0U, 0x6f25254aU, 0x722e2e5cU,
0x241c1c38U, 0xf1a6a657U, 0xc7b4b473U, 0x51c6c697U,
0x23e8e8cbU, 0x7cdddda1U, 0x9c7474e8U, 0x211f1f3eU,
0xdd4b4b96U, 0xdcbdbd61U, 0x868b8b0dU, 0x858a8a0fU,
0x907070e0U, 0x423e3e7cU, 0xc4b5b571U, 0xaa6666ccU,
0xd8484890U, 0x05030306U, 0x01f6f6f7U, 0x120e0e1cU,
0xa36161c2U, 0x5f35356aU, 0xf95757aeU, 0xd0b9b969U,
0x91868617U, 0x58c1c199U, 0x271d1d3aU, 0xb99e9e27U,
0x38e1e1d9U, 0x13f8f8ebU, 0xb398982bU, 0x33111122U,
0xbb6969d2U, 0x70d9d9a9U, 0x898e8e07U, 0xa7949433U,
0xb69b9b2dU, 0x221e1e3cU, 0x92878715U, 0x20e9e9c9U,
0x49cece87U, 0xff5555aaU, 0x78282850U, 0x7adfdfa5U,
0x8f8c8c03U, 0xf8a1a159U, 0x80898909U, 0x170d0d1aU,
0xdabfbf65U, 0x31e6e6d7U, 0xc6424284U, 0xb86868d0U,
0xc3414182U, 0xb0999929U, 0x772d2d5aU, 0x110f0f1eU,
0xcbb0b07bU, 0xfc5454a8U, 0xd6bbbb6dU, 0x3a16162cU,
0x6363c6a5U, 0x7c7cf884U, 0x7777ee99U, 0x7b7bf68dU,
0xf2f2ff0dU, 0x6b6bd6bdU, 0x6f6fdeb1U, 0xc5c59154U,
0x30306050U, 0x01010203U, 0x6767cea9U, 0x2b2b567dU,
0xfefee719U, 0xd7d7b562U, 0xabab4de6U, 0x7676ec9aU,
0xcaca8f45U, 0x82821f9dU, 0xc9c98940U, 0x7d7dfa87U,
0xfafaef15U, 0x5959b2ebU, 0x47478ec9U, 0xf0f0fb0bU,
0xadad41ecU, 0xd4d4b367U, 0xa2a25ffdU, 0xafaf45eaU,
0x9c9c23bfU, 0xa4a453f7U, 0x7272e496U, 0xc0c09b5bU,
0xb7b775c2U, 0xfdfde11cU, 0x93933daeU, 0x26264c6aU,
0x36366c5aU, 0x3f3f7e41U, 0xf7f7f502U, 0xcccc834fU,
0x3434685cU, 0xa5a551f4U, 0xe5e5d134U, 0xf1f1f908U,
0x7171e293U, 0xd8d8ab73U, 0x31316253U, 0x15152a3fU,
0x0404080cU, 0xc7c79552U, 0x23234665U, 0xc3c39d5eU,
0x18183028U, 0x969637a1U, 0x05050a0fU, 0x9a9a2fb5U,
0x07070e09U, 0x12122436U, 0x80801b9bU, 0xe2e2df3dU,
0xebebcd26U, 0x27274e69U, 0xb2b27fcdU, 0x7575ea9fU,
0x0909121bU, 0x83831d9eU, 0x2c2c5874U, 0x1a1a342eU,
0x1b1b362dU, 0x6e6edcb2U, 0x5a5ab4eeU, 0xa0a05bfbU,
0x5252a4f6U, 0x3b3b764dU, 0xd6d6b761U, 0xb3b37dceU,
0x2929527bU, 0xe3e3dd3eU, 0x2f2f5e71U, 0x84841397U,
0x5353a6f5U, 0xd1d1b968U, 0x00000000U, 0xededc12cU,
0x20204060U, 0xfcfce31fU, 0xb1b179c8U, 0x5b5bb6edU,
0x6a6ad4beU, 0xcbcb8d46U, 0xbebe67d9U, 0x3939724bU,
0x4a4a94deU, 0x4c4c98d4U, 0x5858b0e8U, 0xcfcf854aU,
0xd0d0bb6bU, 0xefefc52aU, 0xaaaa4fe5U, 0xfbfbed16U,
0x434386c5U, 0x4d4d9ad7U, 0x33336655U, 0x85851194U,
0x45458acfU, 0xf9f9e910U, 0x02020406U, 0x7f7ffe81U,
0x5050a0f0U, 0x3c3c7844U, 0x9f9f25baU, 0xa8a84be3U,
0x5151a2f3U, 0xa3a35dfeU, 0x404080c0U, 0x8f8f058aU,
0x92923fadU, 0x9d9d21bcU, 0x38387048U, 0xf5f5f104U,
0xbcbc63dfU, 0xb6b677c1U, 0xdadaaf75U, 0x21214263U,
0x10102030U, 0xffffe51aU, 0xf3f3fd0eU, 0xd2d2bf6dU,
0xcdcd814cU, 0x0c0c1814U, 0x13132635U, 0xececc32fU,
0x5f5fbee1U, 0x979735a2U, 0x444488ccU, 0x17172e39U,
0xc4c49357U, 0xa7a755f2U, 0x7e7efc82U, 0x3d3d7a47U,
0x6464c8acU, 0x5d5dbae7U, 0x1919322bU, 0x7373e695U,
0x6060c0a0U, 0x81811998U, 0x4f4f9ed1U, 0xdcdca37fU,
0x22224466U, 0x2a2a547eU, 0x90903babU, 0x88880b83U,
0x46468ccaU, 0xeeeec729U, 0xb8b86bd3U, 0x1414283cU,
0xdedea779U, 0x5e5ebce2U, 0x0b0b161dU, 0xdbdbad76U,
0xe0e0db3bU, 0x32326456U, 0x3a3a744eU, 0x0a0a141eU,
0x494992dbU, 0x06060c0aU, 0x2424486cU, 0x5c5cb8e4U,
0xc2c29f5dU, 0xd3d3bd6eU, 0xacac43efU, 0x6262c4a6U,
0x919139a8U, 0x959531a4U, 0xe4e4d337U, 0x7979f28bU,
0xe7e7d532U, 0xc8c88b43U, 0x37376e59U, 0x6d6ddab7U,
0x8d8d018cU, 0xd5d5b164U, 0x4e4e9cd2U, 0xa9a949e0U,
0x6c6cd8b4U, 0x5656acfaU, 0xf4f4f307U, 0xeaeacf25U,
0x6565caafU, 0x7a7af48eU, 0xaeae47e9U, 0x08081018U,
0xbaba6fd5U, 0x7878f088U, 0x25254a6fU, 0x2e2e5c72U,
0x1c1c3824U, 0xa6a657f1U, 0xb4b473c7U, 0xc6c69751U,
0xe8e8cb23U, 0xdddda17cU, 0x7474e89cU, 0x1f1f3e21U,
0x4b4b96ddU, 0xbdbd61dcU, 0x8b8b0d86U, 0x8a8a0f85U,
0x7070e090U, 0x3e3e7c42U, 0xb5b571c4U, 0x6666ccaaU,
0x484890d8U, 0x03030605U, 0xf6f6f701U, 0x0e0e1c12U,
0x6161c2a3U, 0x35356a5fU, 0x5757aef9U, 0xb9b969d0U,
0x86861791U, 0xc1c19958U, 0x1d1d3a27U, 0x9e9e27b9U,
0xe1e1d938U, 0xf8f8eb13U, 0x98982bb3U, 0x11112233U,
0x6969d2bbU, 0xd9d9a970U, 0x8e8e0789U, 0x949433a7U,
0x9b9b2db6U, 0x1e1e3c22U, 0x87871592U, 0xe9e9c920U,
0xcece8749U, 0x5555aaffU, 0x28285078U, 0xdfdfa57aU,
0x8c8c038fU, 0xa1a159f8U, 0x89890980U, 0x0d0d1a17U,
0xbfbf65daU, 0xe6e6d731U, 0x424284c6U, 0x6868d0b8U,
0x414182c3U, 0x999929b0U, 0x2d2d5a77U, 0x0f0f1e11U,
0xb0b07bcbU, 0x5454a8fcU, 0xbbbb6dd6U, 0x16162c3aU,
0x63c6a563U, 0x7cf8847cU, 0x77ee9977U, 0x7bf68d7bU,
0xf2ff0df2U, 0x6bd6bd6bU, 0x6fdeb16fU, 0xc59154c5U,
0x30605030U, 0x01020301U, 0x67cea967U, 0x2b567d2bU,
0xfee719feU, 0xd7b562d7U, 0xab4de6abU, 0x76ec9a76U,
0xca8f45caU, 0x821f9d82U, 0xc98940c9U, 0x7dfa877dU,
0xfaef15faU, 0x59b2eb59U, 0x478ec947U, 0xf0fb0bf0U,
0xad41ecadU, 0xd4b367d4U, 0xa25ffda2U, 0xaf45eaafU,
0x9c23bf9cU, 0xa453f7a4U, 0x72e49672U, 0xc09b5bc0U,
0xb775c2b7U, 0xfde11cfdU, 0x933dae93U, 0x264c6a26U,
0x366c5a36U, 0x3f7e413fU, 0xf7f502f7U, 0xcc834fccU,
0x34685c34U, 0xa551f4a5U, 0xe5d134e5U, 0xf1f908f1U,
0x71e29371U, 0xd8ab73d8U, 0x31625331U, 0x152a3f15U,
0x04080c04U, 0xc79552c7U, 0x23466523U, 0xc39d5ec3U,
0x18302818U, 0x9637a196U, 0x050a0f05U, 0x9a2fb59aU,
0x070e0907U, 0x12243612U, 0x801b9b80U, 0xe2df3de2U,
0xebcd26ebU, 0x274e6927U, 0xb27fcdb2U, 0x75ea9f75U,
0x09121b09U, 0x831d9e83U, 0x2c58742cU, 0x1a342e1aU,
0x1b362d1bU, 0x6edcb26eU, 0x5ab4ee5aU, 0xa05bfba0U,
0x52a4f652U, 0x3b764d3bU, 0xd6b761d6U, 0xb37dceb3U,
0x29527b29U, 0xe3dd3ee3U, 0x2f5e712fU, 0x84139784U,
0x53a6f553U, 0xd1b968d1U, 0x00000000U, 0xedc12cedU,
0x20406020U, 0xfce31ffcU, 0xb179c8b1U, 0x5bb6ed5bU,
0x6ad4be6aU, 0xcb8d46cbU, 0xbe67d9beU, 0x39724b39U,
0x4a94de4aU, 0x4c98d44cU, 0x58b0e858U, 0xcf854acfU,
0xd0bb6bd0U, 0xefc52aefU, 0xaa4fe5aaU, 0xfbed16fbU,
0x4386c543U, 0x4d9ad74dU, 0x33665533U, 0x85119485U,
0x458acf45U, 0xf9e910f9U, 0x02040602U, 0x7ffe817fU,
0x50a0f050U, 0x3c78443cU, 0x9f25ba9fU, 0xa84be3a8U,
0x51a2f351U, 0xa35dfea3U, 0x4080c040U, 0x8f058a8fU,
0x923fad92U, 0x9d21bc9dU, 0x38704838U, 0xf5f104f5U,
0xbc63dfbcU, 0xb677c1b6U, 0xdaaf75daU, 0x21426321U,
0x10203010U, 0xffe51affU, 0xf3fd0ef3U, 0xd2bf6dd2U,
0xcd814ccdU, 0x0c18140cU, 0x13263513U, 0xecc32fecU,
0x5fbee15fU, 0x9735a297U, 0x4488cc44U, 0x172e3917U,
0xc49357c4U, 0xa755f2a7U, 0x7efc827eU, 0x3d7a473dU,
0x64c8ac64U, 0x5dbae75dU, 0x19322b19U, 0x73e69573U,
0x60c0a060U, 0x81199881U, 0x4f9ed14fU, 0xdca37fdcU,
0x22446622U, 0x2a547e2aU, 0x903bab90U, 0x880b8388U,
0x468cca46U, 0xeec729eeU, 0xb86bd3b8U, 0x14283c14U,
0xdea779deU, 0x5ebce25eU, 0x0b161d0bU, 0xdbad76dbU,
0xe0db3be0U, 0x32645632U, 0x3a744e3aU, 0x0a141e0aU,
0x4992db49U, 0x060c0a06U, 0x24486c24U, 0x5cb8e45cU,
0xc29f5dc2U, 0xd3bd6ed3U, 0xac43efacU, 0x62c4a662U,
0x9139a891U, 0x9531a495U, 0xe4d337e4U, 0x79f28b79U,
0xe7d532e7U, 0xc88b43c8U, 0x376e5937U, 0x6ddab76dU,
0x8d018c8dU, 0xd5b164d5U, 0x4e9cd24eU, 0xa949e0a9U,
0x6cd8b46cU, 0x56acfa56U, 0xf4f307f4U, 0xeacf25eaU,
0x65caaf65U, 0x7af48e7aU, 0xae47e9aeU, 0x08101808U,
0xba6fd5baU, 0x78f08878U, 0x254a6f25U, 0x2e5c722eU,
0x1c38241cU, 0xa657f1a6U, 0xb473c7b4U, 0xc69751c6U,
0xe8cb23e8U, 0xdda17cddU, 0x74e89c74U, 0x1f3e211fU,
0x4b96dd4bU, 0xbd61dcbdU, 0x8b0d868bU, 0x8a0f858aU,
0x70e09070U, 0x3e7c423eU, 0xb571c4b5U, 0x66ccaa66U,
0x4890d848U, 0x03060503U, 0xf6f701f6U, 0x0e1c120eU,
0x61c2a361U, 0x356a5f35U, 0x57aef957U, 0xb969d0b9U,
0x86179186U, 0xc19958c1U, 0x1d3a271dU, 0x9e27b99eU,
0xe1d938e1U, 0xf8eb13f8U, 0x982bb398U, 0x11223311U,
0x69d2bb69U, 0xd9a970d9U, 0x8e07898eU, 0x9433a794U,
0x9b2db69bU, 0x1e3c221eU, 0x87159287U, 0xe9c920e9U,
0xce8749ceU, 0x55aaff55U, 0x28507828U, 0xdfa57adfU,
0x8c038f8cU, 0xa159f8a1U, 0x89098089U, 0x0d1a170dU,
0xbf65dabfU, 0xe6d731e6U, 0x4284c642U, 0x68d0b868U,
0x4182c341U, 0x9929b099U, 0x2d5a772dU, 0x0f1e110fU,
0xb07bcbb0U, 0x54a8fc54U, 0xbb6dd6bbU, 0x162c3a16U,
0xc6a56363U, 0xf8847c7cU, 0xee997777U, 0xf68d7b7bU,
0xff0df2f2U, 0xd6bd6b6bU, 0xdeb16f6fU, 0x9154c5c5U,
0x60503030U, 0x02030101U, 0xcea96767U, 0x567d2b2bU,
0xe719fefeU, 0xb562d7d7U, 0x4de6ababU, 0xec9a7676U,
0x8f45cacaU, 0x1f9d8282U, 0x8940c9c9U, 0xfa877d7dU,
0xef15fafaU, 0xb2eb5959U, 0x8ec94747U, 0xfb0bf0f0U,
0x41ecadadU, 0xb367d4d4U, 0x5ffda2a2U, 0x45eaafafU,
0x23bf9c9cU, 0x53f7a4a4U, 0xe4967272U, 0x9b5bc0c0U,
0x75c2b7b7U, 0xe11cfdfdU, 0x3dae9393U, 0x4c6a2626U,
0x6c5a3636U, 0x7e413f3fU, 0xf502f7f7U, 0x834fccccU,
0x685c3434U, 0x51f4a5a5U, 0xd134e5e5U, 0xf908f1f1U,
0xe2937171U, 0xab73d8d8U, 0x62533131U, 0x2a3f1515U,
0x080c0404U, 0x9552c7c7U, 0x46652323U, 0x9d5ec3c3U,
0x30281818U, 0x37a19696U, 0x0a0f0505U, 0x2fb59a9aU,
0x0e090707U, 0x24361212U, 0x1b9b8080U, 0xdf3de2e2U,
0xcd26ebebU, 0x4e692727U, 0x7fcdb2b2U, 0xea9f7575U,
0x121b0909U, 0x1d9e8383U, 0x58742c2cU, 0x342e1a1aU,
0x362d1b1bU, 0xdcb26e6eU, 0xb4ee5a5aU, 0x5bfba0a0U,
0xa4f65252U, 0x764d3b3bU, 0xb761d6d6U, 0x7dceb3b3U,
0x527b2929U, 0xdd3ee3e3U, 0x5e712f2fU, 0x13978484U,
0xa6f55353U, 0xb968d1d1U, 0x00000000U, 0xc12cededU,
0x40602020U, 0xe31ffcfcU, 0x79c8b1b1U, 0xb6ed5b5bU,
0xd4be6a6aU, 0x8d46cbcbU, 0x67d9bebeU, 0x724b3939U,
0x94de4a4aU, 0x98d44c4cU, 0xb0e85858U, 0x854acfcfU,
0xbb6bd0d0U, 0xc52aefefU, 0x4fe5aaaaU, 0xed16fbfbU,
0x86c54343U, 0x9ad74d4dU, 0x66553333U, 0x11948585U,
0x8acf4545U, 0xe910f9f9U, 0x04060202U, 0xfe817f7fU,
0xa0f05050U, 0x78443c3cU, 0x25ba9f9fU, 0x4be3a8a8U,
0xa2f35151U, 0x5dfea3a3U, 0x80c04040U, 0x058a8f8fU,
0x3fad9292U, 0x21bc9d9dU, 0x70483838U, 0xf104f5f5U,
0x63dfbcbcU, 0x77c1b6b6U, 0xaf75dadaU, 0x42632121U,
0x20301010U, 0xe51affffU, 0xfd0ef3f3U, 0xbf6dd2d2U,
0x814ccdcdU, 0x18140c0cU, 0x26351313U, 0xc32fececU,
0xbee15f5fU, 0x35a29797U, 0x88cc4444U, 0x2e391717U,
0x9357c4c4U, 0x55f2a7a7U, 0xfc827e7eU, 0x7a473d3dU,
0xc8ac6464U, 0xbae75d5dU, 0x322b1919U, 0xe6957373U,
0xc0a06060U, 0x19988181U, 0x9ed14f4fU, 0xa37fdcdcU,
0x44662222U, 0x547e2a2aU, 0x3bab9090U, 0x0b838888U,
0x8cca4646U, 0xc729eeeeU, 0x6bd3b8b8U, 0x283c1414U,
0xa779dedeU, 0xbce25e5eU, 0x161d0b0bU, 0xad76dbdbU,
0xdb3be0e0U, 0x64563232U, 0x744e3a3aU, 0x141e0a0aU,
0x92db4949U, 0x0c0a0606U, 0x486c2424U, 0xb8e45c5cU,
0x9f5dc2c2U, 0xbd6ed3d3U, 0x43efacacU, 0xc4a66262U,
0x39a89191U, 0x31a49595U, 0xd337e4e4U, 0xf28b7979U,
0xd532e7e7U, 0x8b43c8c8U, 0x6e593737U, 0xdab76d6dU,
0x018c8d8dU, 0xb164d5d5U, 0x9cd24e4eU, 0x49e0a9a9U,
0xd8b46c6cU, 0xacfa5656U, 0xf307f4f4U, 0xcf25eaeaU,
0xcaaf6565U, 0xf48e7a7aU, 0x47e9aeaeU, 0x10180808U,
0x6fd5babaU, 0xf0887878U, 0x4a6f2525U, 0x5c722e2eU,
0x38241c1cU, 0x57f1a6a6U, 0x73c7b4b4U, 0x9751c6c6U,
0xcb23e8e8U, 0xa17cddddU, 0xe89c7474U, 0x3e211f1fU,
0x96dd4b4bU, 0x61dcbdbdU, 0x0d868b8bU, 0x0f858a8aU,
0xe0907070U, 0x7c423e3eU, 0x71c4b5b5U, 0xccaa6666U,
0x90d84848U, 0x06050303U, 0xf701f6f6U, 0x1c120e0eU,
0xc2a36161U, 0x6a5f3535U, 0xaef95757U, 0x69d0b9b9U,
0x17918686U, 0x9958c1c1U, 0x3a271d1dU, 0x27b99e9eU,
0xd938e1e1U, 0xeb13f8f8U, 0x2bb39898U, 0x22331111U,
0xd2bb6969U, 0xa970d9d9U, 0x07898e8eU, 0x33a79494U,
0x2db69b9bU, 0x3c221e1eU, 0x15928787U, 0xc920e9e9U,
0x8749ceceU, 0xaaff5555U, 0x50782828U, 0xa57adfdfU,
0x038f8c8cU, 0x59f8a1a1U, 0x09808989U, 0x1a170d0dU,
0x65dabfbfU, 0xd731e6e6U, 0x84c64242U, 0xd0b86868U,
0x82c34141U, 0x29b09999U, 0x5a772d2dU, 0x1e110f0fU,
0x7bcbb0b0U, 0xa8fc5454U, 0x6dd6bbbbU, 0x2c3a1616U
};
#define t_fn0(x) (sharedMemory[ (x)])
#define t_fn1(x) (sharedMemory[256 + (x)])
#define t_fn2(x) (sharedMemory[512 + (x)])
#define t_fn3(x) (sharedMemory[768 + (x)])
#define round(dummy,y,x,k) \
y[0] = (k)[0] ^ (t_fn0(x[0] & 0xff) ^ t_fn1((x[1] >> 8) & 0xff) ^ t_fn2((x[2] >> 16) & 0xff) ^ t_fn3((x[3] >> 24))); \
y[1] = (k)[1] ^ (t_fn0(x[1] & 0xff) ^ t_fn1((x[2] >> 8) & 0xff) ^ t_fn2((x[3] >> 16) & 0xff) ^ t_fn3((x[0] >> 24))); \
y[2] = (k)[2] ^ (t_fn0(x[2] & 0xff) ^ t_fn1((x[3] >> 8) & 0xff) ^ t_fn2((x[0] >> 16) & 0xff) ^ t_fn3((x[1] >> 24))); \
y[3] = (k)[3] ^ (t_fn0(x[3] & 0xff) ^ t_fn1((x[0] >> 8) & 0xff) ^ t_fn2((x[1] >> 16) & 0xff) ^ t_fn3((x[2] >> 24) ));
__device__ __forceinline__ static void cn_aes_single_round(uint32_t * __restrict__ sharedMemory, const uint32_t * __restrict__ in, uint32_t * __restrict__ out, const uint32_t * __restrict__ expandedKey)
{
round(sharedMemory, out, in, expandedKey);
}
__device__ __forceinline__ static void cn_aes_pseudo_round_mut(const uint32_t * __restrict__ sharedMemory, uint32_t * __restrict__ val, const uint32_t * __restrict__ expandedKey)
{
uint32_t b1[4];
round(sharedMemory, b1, val, expandedKey);
round(sharedMemory, val, b1, expandedKey + 1 * N_COLS);
round(sharedMemory, b1, val, expandedKey + 2 * N_COLS);
round(sharedMemory, val, b1, expandedKey + 3 * N_COLS);
round(sharedMemory, b1, val, expandedKey + 4 * N_COLS);
round(sharedMemory, val, b1, expandedKey + 5 * N_COLS);
round(sharedMemory, b1, val, expandedKey + 6 * N_COLS);
round(sharedMemory, val, b1, expandedKey + 7 * N_COLS);
round(sharedMemory, b1, val, expandedKey + 8 * N_COLS);
round(sharedMemory, val, b1, expandedKey + 9 * N_COLS);
}
__device__ __forceinline__ static void cn_aes_gpu_init(uint32_t *sharedMemory)
{
for(int i = threadIdx.x; i < 1024; i += blockDim.x)
sharedMemory[i] = d_t_fn[i];
}
@@ -0,0 +1,193 @@
#pragma once
typedef struct {
uint32_t h[8], s[4], t[2];
int buflen, nullt;
uint8_t buf[64];
} blake_state;
#define U8TO32(p) \
(((uint32_t)((p)[0]) << 24) | ((uint32_t)((p)[1]) << 16) | \
((uint32_t)((p)[2]) << 8) | ((uint32_t)((p)[3]) ))
#define U32TO8(p, v) \
(p)[0] = (uint8_t)((v) >> 24); (p)[1] = (uint8_t)((v) >> 16); \
(p)[2] = (uint8_t)((v) >> 8); (p)[3] = (uint8_t)((v) );
#define BLAKE_ROT(x,n) ROTR32(x, n)
#define BLAKE_G(a,b,c,d,e) \
v[a] += (m[d_blake_sigma[i][e]] ^ d_blake_cst[d_blake_sigma[i][e+1]]) + v[b]; \
v[d] = BLAKE_ROT(v[d] ^ v[a],16); \
v[c] += v[d]; \
v[b] = BLAKE_ROT(v[b] ^ v[c],12); \
v[a] += (m[d_blake_sigma[i][e+1]] ^ d_blake_cst[d_blake_sigma[i][e]])+v[b]; \
v[d] = BLAKE_ROT(v[d] ^ v[a], 8); \
v[c] += v[d]; \
v[b] = BLAKE_ROT(v[b] ^ v[c], 7);
__constant__ uint8_t d_blake_sigma[14][16] =
{
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
{7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
{9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
{2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
{12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
{13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
{6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
{10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
{7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8}
};
__constant__ uint32_t d_blake_cst[16]
= {
0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917
};
__device__ void cn_blake_compress(blake_state * __restrict__ S, const uint8_t * __restrict__ block)
{
uint32_t v[16], m[16], i;
for (i = 0; i < 16; ++i) m[i] = U8TO32(block + i * 4);
for (i = 0; i < 8; ++i) v[i] = S->h[i];
v[ 8] = S->s[0] ^ 0x243F6A88;
v[ 9] = S->s[1] ^ 0x85A308D3;
v[10] = S->s[2] ^ 0x13198A2E;
v[11] = S->s[3] ^ 0x03707344;
v[12] = 0xA4093822;
v[13] = 0x299F31D0;
v[14] = 0x082EFA98;
v[15] = 0xEC4E6C89;
if (S->nullt == 0)
{
v[12] ^= S->t[0];
v[13] ^= S->t[0];
v[14] ^= S->t[1];
v[15] ^= S->t[1];
}
for (i = 0; i < 14; ++i)
{
BLAKE_G(0, 4, 8, 12, 0);
BLAKE_G(1, 5, 9, 13, 2);
BLAKE_G(2, 6, 10, 14, 4);
BLAKE_G(3, 7, 11, 15, 6);
BLAKE_G(3, 4, 9, 14, 14);
BLAKE_G(2, 7, 8, 13, 12);
BLAKE_G(0, 5, 10, 15, 8);
BLAKE_G(1, 6, 11, 12, 10);
}
for (i = 0; i < 16; ++i) S->h[i % 8] ^= v[i];
for (i = 0; i < 8; ++i) S->h[i] ^= S->s[i % 4];
}
__device__ void cn_blake_update(blake_state * __restrict__ S, const uint8_t * __restrict__ data, uint64_t datalen)
{
int left = S->buflen >> 3;
int fill = 64 - left;
if (left && (((datalen >> 3) & 0x3F) >= (unsigned) fill))
{
memcpy((void *) (S->buf + left), (void *) data, fill);
S->t[0] += 512;
if (S->t[0] == 0) S->t[1]++;
cn_blake_compress(S, S->buf);
data += fill;
datalen -= (fill << 3);
left = 0;
}
while (datalen >= 512)
{
S->t[0] += 512;
if (S->t[0] == 0) S->t[1]++;
cn_blake_compress(S, data);
data += 64;
datalen -= 512;
}
if (datalen > 0)
{
memcpy((void *) (S->buf + left), (void *) data, datalen >> 3);
S->buflen = (left << 3) + datalen;
}
else
{
S->buflen = 0;
}
}
__device__ void cn_blake_final(blake_state * __restrict__ S, uint8_t * __restrict__ digest)
{
const uint8_t padding[] =
{
0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
uint8_t pa = 0x81, pb = 0x01;
uint8_t msglen[8];
uint32_t lo = S->t[0] + S->buflen, hi = S->t[1];
if (lo < (unsigned) S->buflen) hi++;
U32TO8(msglen + 0, hi);
U32TO8(msglen + 4, lo);
if (S->buflen == 440)
{
S->t[0] -= 8;
cn_blake_update(S, &pa, 8);
}
else
{
if (S->buflen < 440)
{
if (S->buflen == 0) S->nullt = 1;
S->t[0] -= 440 - S->buflen;
cn_blake_update(S, padding, 440 - S->buflen);
}
else
{
S->t[0] -= 512 - S->buflen;
cn_blake_update(S, padding, 512 - S->buflen);
S->t[0] -= 440;
cn_blake_update(S, padding + 1, 440);
S->nullt = 1;
}
cn_blake_update(S, &pb, 8);
S->t[0] -= 8;
}
S->t[0] -= 64;
cn_blake_update(S, msglen, 64);
U32TO8(digest + 0, S->h[0]);
U32TO8(digest + 4, S->h[1]);
U32TO8(digest + 8, S->h[2]);
U32TO8(digest + 12, S->h[3]);
U32TO8(digest + 16, S->h[4]);
U32TO8(digest + 20, S->h[5]);
U32TO8(digest + 24, S->h[6]);
U32TO8(digest + 28, S->h[7]);
}
__device__ void cn_blake(const uint8_t * __restrict__ in, uint64_t inlen, uint8_t * __restrict__ out)
{
blake_state bs;
blake_state *S = (blake_state *)&bs;
S->h[0] = 0x6A09E667; S->h[1] = 0xBB67AE85; S->h[2] = 0x3C6EF372;
S->h[3] = 0xA54FF53A; S->h[4] = 0x510E527F; S->h[5] = 0x9B05688C;
S->h[6] = 0x1F83D9AB; S->h[7] = 0x5BE0CD19;
S->t[0] = S->t[1] = S->buflen = S->nullt = 0;
S->s[0] = S->s[1] = S->s[2] = S->s[3] = 0;
cn_blake_update(S, (uint8_t *)in, inlen * 8);
cn_blake_final(S, (uint8_t *)out);
}
@@ -0,0 +1,343 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <cuda.h>
#include <cuda_runtime.h>
#ifdef _WIN32
#include <windows.h>
extern "C" void compat_usleep(uint64_t waitTime)
{
if (waitTime > 0)
{
if (waitTime > 100)
{
// use a waitable timer for larger intervals > 0.1ms
HANDLE timer;
LARGE_INTEGER ft;
ft.QuadPart = -(10*waitTime); // Convert to 100 nanosecond interval, negative value indicates relative time
timer = CreateWaitableTimer(NULL, TRUE, NULL);
SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0);
WaitForSingleObject(timer, INFINITE);
CloseHandle(timer);
}
else
{
// use a polling loop for short intervals <= 100ms
LARGE_INTEGER perfCnt, start, now;
__int64 elapsed;
QueryPerformanceFrequency(&perfCnt);
QueryPerformanceCounter(&start);
do {
SwitchToThread();
QueryPerformanceCounter((LARGE_INTEGER*) &now);
elapsed = (__int64)((now.QuadPart - start.QuadPart) / (float)perfCnt.QuadPart * 1000 * 1000);
} while ( elapsed < waitTime );
}
}
}
#else
#include <unistd.h>
extern "C" void compat_usleep(uint64_t waitTime)
{
usleep(waitTime);
}
#endif
#include "cryptonight.hpp"
#include "cuda_extra.hpp"
#include "cuda_aes.hpp"
#include "cuda_device.hpp"
/* sm_2X is limited to 2GB due to the small TLB
* therefore we never use 64bit indices
*/
#if defined(XMR_STAK_LARGEGRID) && (__CUDA_ARCH__ >= 300)
typedef uint64_t IndexType;
#else
typedef int IndexType;
#endif
__device__ __forceinline__ uint64_t cuda_mul128( uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi )
{
*product_hi = __umul64hi( multiplier, multiplicand );
return (multiplier * multiplicand );
}
template< typename T >
__device__ __forceinline__ T loadGlobal64( T * const addr )
{
T x;
asm volatile( "ld.global.cg.u64 %0, [%1];" : "=l"( x ) : "l"( addr ) );
return x;
}
template< typename T >
__device__ __forceinline__ T loadGlobal32( T * const addr )
{
T x;
asm volatile( "ld.global.cg.u32 %0, [%1];" : "=r"( x ) : "l"( addr ) );
return x;
}
template< typename T >
__device__ __forceinline__ void storeGlobal32( T* addr, T const & val )
{
asm volatile( "st.global.cg.u32 [%0], %1;" : : "l"( addr ), "r"( val ) );
}
__global__ void cryptonight_core_gpu_phase1( int threads, int bfactor, int partidx, uint32_t * __restrict__ long_state, uint32_t * __restrict__ ctx_state, uint32_t * __restrict__ ctx_key1 )
{
__shared__ uint32_t sharedMemory[1024];
cn_aes_gpu_init( sharedMemory );
__syncthreads( );
const int thread = ( blockDim.x * blockIdx.x + threadIdx.x ) >> 3;
const int sub = ( threadIdx.x & 7 ) << 2;
const int batchsize = 0x80000 >> bfactor;
const int start = partidx * batchsize;
const int end = start + batchsize;
if ( thread >= threads )
return;
uint32_t key[40], text[4];
MEMCPY8( key, ctx_key1 + thread * 40, 20 );
if( partidx == 0 )
{
// first round
MEMCPY8( text, ctx_state + thread * 50 + sub + 16, 2 );
}
else
{
// load previous text data
MEMCPY8( text, &long_state[( (uint64_t) thread << 19 ) + sub + start - 32], 2 );
}
__syncthreads( );
for ( int i = start; i < end; i += 32 )
{
cn_aes_pseudo_round_mut( sharedMemory, text, key );
MEMCPY8(&long_state[((uint64_t) thread << 19) + (sub + i)], text, 2);
}
}
/** avoid warning `unused parameter` */
template< typename T >
__forceinline__ __device__ void unusedVar( const T& )
{
}
/** shuffle data for
*
* - this method can be used with all compute architectures
* - for <sm_30 shared memory is needed
*
* @param ptr pointer to shared memory, size must be `threadIdx.x * sizeof(uint32_t)`
* value can be NULL for compute architecture >=sm_30
* @param sub thread number within the group, range [0;4)
* @param value value to share with other threads within the group
* @param src thread number within the group from where the data is read, range [0;4)
*/
__forceinline__ __device__ uint32_t shuffle(volatile uint32_t* ptr,const uint32_t sub,const int val,const uint32_t src)
{
#if( __CUDA_ARCH__ < 300 )
ptr[sub] = val;
return ptr[src&3];
#else
unusedVar( ptr );
unusedVar( sub );
return __shfl( val, src, 4 );
#endif
}
#ifdef XMR_STAK_THREADS
__launch_bounds__( XMR_STAK_THREADS * 4 )
#endif
__global__ void cryptonight_core_gpu_phase2( int threads, int bfactor, int partidx, uint32_t * d_long_state, uint32_t * d_ctx_a, uint32_t * d_ctx_b )
{
__shared__ uint32_t sharedMemory[1024];
cn_aes_gpu_init( sharedMemory );
__syncthreads( );
const int thread = ( blockDim.x * blockIdx.x + threadIdx.x ) >> 2;
const int sub = threadIdx.x & 3;
const int sub2 = sub & 2;
#if( __CUDA_ARCH__ < 300 )
extern __shared__ uint32_t shuffleMem[];
volatile uint32_t* sPtr = (volatile uint32_t*)(shuffleMem + (threadIdx.x& 0xFFFFFFFC));
#else
volatile uint32_t* sPtr = NULL;
#endif
if ( thread >= threads )
return;
int i, k;
uint32_t j;
const int batchsize = ITER >> ( 2 + bfactor );
const int start = partidx * batchsize;
const int end = start + batchsize;
uint32_t * long_state = &d_long_state[(IndexType) thread << 19];
uint32_t * ctx_a = d_ctx_a + thread * 4;
uint32_t * ctx_b = d_ctx_b + thread * 4;
uint32_t a, d[2];
uint32_t t1[2], t2[2], res;
a = ctx_a[sub];
d[1] = ctx_b[sub];
#pragma unroll 2
for ( i = start; i < end; ++i )
{
#pragma unroll 2
for ( int x = 0; x < 2; ++x )
{
j = ( ( shuffle(sPtr,sub, a, 0) & 0x1FFFF0 ) >> 2 ) + sub;
const uint32_t x_0 = loadGlobal32<uint32_t>( long_state + j );
const uint32_t x_1 = shuffle(sPtr,sub, x_0, sub + 1);
const uint32_t x_2 = shuffle(sPtr,sub, x_0, sub + 2);
const uint32_t x_3 = shuffle(sPtr,sub, x_0, sub + 3);
d[x] = a ^
t_fn0( x_0 & 0xff ) ^
t_fn1( (x_1 >> 8) & 0xff ) ^
t_fn2( (x_2 >> 16) & 0xff ) ^
t_fn3( ( x_3 >> 24 ) );
//XOR_BLOCKS_DST(c, b, &long_state[j]);
t1[0] = shuffle(sPtr,sub, d[x], 0);
//long_state[j] = d[0] ^ d[1];
storeGlobal32( long_state + j, d[0] ^ d[1] );
//MUL_SUM_XOR_DST(c, a, &long_state[((uint32_t *)c)[0] & 0x1FFFF0]);
j = ( ( *t1 & 0x1FFFF0 ) >> 2 ) + sub;
uint32_t yy[2];
*( (uint64_t*) yy ) = loadGlobal64<uint64_t>( ( (uint64_t *) long_state )+( j >> 1 ) );
uint32_t zz[2];
zz[0] = shuffle(sPtr,sub, yy[0], 0);
zz[1] = shuffle(sPtr,sub, yy[1], 0);
t1[1] = shuffle(sPtr,sub, d[x], 1);
#pragma unroll
for ( k = 0; k < 2; k++ )
t2[k] = shuffle(sPtr,sub, a, k + sub2);
*( (uint64_t *) t2 ) += sub2 ? ( *( (uint64_t *) t1 ) * *( (uint64_t*) zz ) ) : __umul64hi( *( (uint64_t *) t1 ), *( (uint64_t*) zz ) );
res = *( (uint64_t *) t2 ) >> ( sub & 1 ? 32 : 0 );
storeGlobal32( long_state + j, res );
a = ( sub & 1 ? yy[1] : yy[0] ) ^ res;
}
}
if ( bfactor > 0 )
{
ctx_a[sub] = a;
ctx_b[sub] = d[1];
}
}
__global__ void cryptonight_core_gpu_phase3( int threads, int bfactor, int partidx, const uint32_t * __restrict__ long_state, uint32_t * __restrict__ d_ctx_state, uint32_t * __restrict__ d_ctx_key2 )
{
__shared__ uint32_t sharedMemory[1024];
cn_aes_gpu_init( sharedMemory );
__syncthreads( );
int thread = ( blockDim.x * blockIdx.x + threadIdx.x ) >> 3;
int sub = ( threadIdx.x & 7 ) << 2;
const int batchsize = 0x80000 >> bfactor;
const int start = partidx * batchsize;
const int end = start + batchsize;
if ( thread >= threads )
return;
uint32_t key[40], text[4];
MEMCPY8( key, d_ctx_key2 + thread * 40, 20 );
MEMCPY8( text, d_ctx_state + thread * 50 + sub + 16, 2 );
__syncthreads( );
for ( int i = start; i < end; i += 32 )
{
#pragma unroll
for ( int j = 0; j < 4; ++j )
text[j] ^= long_state[((IndexType) thread << 19) + (sub + i + j)];
cn_aes_pseudo_round_mut( sharedMemory, text, key );
}
MEMCPY8( d_ctx_state + thread * 50 + sub + 16, text, 2 );
}
extern "C" void cryptonight_core_cpu_hash(nvid_ctx* ctx)
{
dim3 grid( ctx->device_blocks );
dim3 block( ctx->device_threads );
dim3 block4( ctx->device_threads << 2 );
dim3 block8( ctx->device_threads << 3 );
int partcount = 1 << ctx->device_bfactor;
/* bfactor for phase 1 and 3
*
* phase 1 and 3 consume less time than phase 2, therefore we begin with the
* kernel splitting if the user defined a `bfactor >= 5`
*/
int bfactorOneThree = ctx->device_bfactor - 4;
if( bfactorOneThree < 0 )
bfactorOneThree = 0;
int partcountOneThree = 1 << bfactorOneThree;
for ( int i = 0; i < partcountOneThree; i++ )
{
CUDA_CHECK_KERNEL(ctx->device_id, cryptonight_core_gpu_phase1<<< grid, block8 >>>( ctx->device_blocks*ctx->device_threads,
bfactorOneThree, i,
ctx->d_long_state, ctx->d_ctx_state, ctx->d_ctx_key1 ));
if ( partcount > 1 && ctx->device_bsleep > 0) compat_usleep( ctx->device_bsleep );
}
if ( partcount > 1 && ctx->device_bsleep > 0) compat_usleep( ctx->device_bsleep );
for ( int i = 0; i < partcount; i++ )
{
CUDA_CHECK_KERNEL(ctx->device_id, cryptonight_core_gpu_phase2<<<
grid,
block4,
block4.x * sizeof(uint32_t) * static_cast< int >( ctx->device_arch[0] < 3 )
>>>(
ctx->device_blocks*ctx->device_threads,
ctx->device_bfactor,
i,
ctx->d_long_state,
ctx->d_ctx_a,
ctx->d_ctx_b
));
if ( partcount > 1 && ctx->device_bsleep > 0) compat_usleep( ctx->device_bsleep );
}
for ( int i = 0; i < partcountOneThree; i++ )
{
CUDA_CHECK_KERNEL(ctx->device_id, cryptonight_core_gpu_phase3<<< grid, block8 >>>( ctx->device_blocks*ctx->device_threads,
bfactorOneThree, i,
ctx->d_long_state,
ctx->d_ctx_state, ctx->d_ctx_key2 ));
}
}
@@ -0,0 +1,30 @@
#pragma once
#include <cuda_runtime.h>
#include <stdexcept>
#include <iostream>
#include <string>
/** execute and check a CUDA api command
*
* @param id gpu id (thread id)
* @param ... CUDA api command
*/
#define CUDA_CHECK(id, ...) { \
cudaError_t error = __VA_ARGS__; \
if(error!=cudaSuccess){ \
std::cerr << "[CUDA] Error gpu " << id << ": <" << __FILE__ << ">:" << __LINE__ << std::endl; \
throw std::runtime_error(std::string("[CUDA] Error: ") + std::string(cudaGetErrorString(error))); \
} \
} \
( (void) 0 )
/** execute and check a CUDA kernel
*
* @param id gpu id (thread id)
* @param ... CUDA kernel call
*/
#define CUDA_CHECK_KERNEL(id, ...) \
__VA_ARGS__; \
CUDA_CHECK(id, cudaGetLastError())
@@ -0,0 +1,367 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <device_functions.hpp>
#include <algorithm>
#ifdef __CUDACC__
__constant__
#else
const
#endif
uint64_t keccakf_rndc[24] ={
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
};
typedef unsigned char BitSequence;
typedef unsigned long long DataLength;
#include "cryptonight.hpp"
#include "cuda_extra.hpp"
#include "cuda_keccak.hpp"
#include "cuda_blake.hpp"
#include "cuda_groestl.hpp"
#include "cuda_jh.hpp"
#include "cuda_skein.hpp"
#include "cuda_device.hpp"
__constant__ uint8_t d_sub_byte[16][16] ={
{0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 },
{0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 },
{0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 },
{0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 },
{0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 },
{0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf },
{0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 },
{0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 },
{0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 },
{0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb },
{0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 },
{0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 },
{0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a },
{0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e },
{0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf },
{0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }
};
__device__ __forceinline__ void cryptonight_aes_set_key( uint32_t * __restrict__ key, const uint32_t * __restrict__ data )
{
int i, j;
uint8_t temp[4];
const uint32_t aes_gf[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
MEMSET4( key, 0, 40 );
MEMCPY4( key, data, 8 );
#pragma unroll
for ( i = 8; i < 40; i++ )
{
*(uint32_t *) temp = key[i - 1];
if ( i % 8 == 0 )
{
*(uint32_t *) temp = ROTR32( *(uint32_t *) temp, 8 );
for ( j = 0; j < 4; j++ )
temp[j] = d_sub_byte[( temp[j] >> 4 ) & 0x0f][temp[j] & 0x0f];
*(uint32_t *) temp ^= aes_gf[i / 8 - 1];
}
else
{
if ( i % 8 == 4 )
{
#pragma unroll
for ( j = 0; j < 4; j++ )
temp[j] = d_sub_byte[( temp[j] >> 4 ) & 0x0f][temp[j] & 0x0f];
}
}
key[i] = key[( i - 8 )] ^ *(uint32_t *) temp;
}
}
__global__ void cryptonight_extra_gpu_prepare( int threads, uint32_t * __restrict__ d_input, uint32_t len, uint32_t startNonce, uint32_t * __restrict__ d_ctx_state, uint32_t * __restrict__ d_ctx_a, uint32_t * __restrict__ d_ctx_b, uint32_t * __restrict__ d_ctx_key1, uint32_t * __restrict__ d_ctx_key2 )
{
int thread = ( blockDim.x * blockIdx.x + threadIdx.x );
if ( thread >= threads )
return;
uint32_t ctx_state[50];
uint32_t ctx_a[4];
uint32_t ctx_b[4];
uint32_t ctx_key1[40];
uint32_t ctx_key2[40];
uint32_t input[21];
memcpy( input, d_input, len );
//*((uint32_t *)(((char *)input) + 39)) = startNonce + thread;
uint32_t nonce = startNonce + thread;
for ( int i = 0; i < sizeof (uint32_t ); ++i )
( ( (char *) input ) + 39 )[i] = ( (char*) ( &nonce ) )[i]; //take care of pointer alignment
cn_keccak( (uint8_t *) input, len, (uint8_t *) ctx_state );
cryptonight_aes_set_key( ctx_key1, ctx_state );
cryptonight_aes_set_key( ctx_key2, ctx_state + 8 );
XOR_BLOCKS_DST( ctx_state, ctx_state + 8, ctx_a );
XOR_BLOCKS_DST( ctx_state + 4, ctx_state + 12, ctx_b );
memcpy( d_ctx_state + thread * 50, ctx_state, 50 * 4 );
memcpy( d_ctx_a + thread * 4, ctx_a, 4 * 4 );
memcpy( d_ctx_b + thread * 4, ctx_b, 4 * 4 );
memcpy( d_ctx_key1 + thread * 40, ctx_key1, 40 * 4 );
memcpy( d_ctx_key2 + thread * 40, ctx_key2, 40 * 4 );
}
__global__ void cryptonight_extra_gpu_final( int threads, uint64_t target, uint32_t* __restrict__ d_res_count, uint32_t * __restrict__ d_res_nonce, uint32_t * __restrict__ d_ctx_state )
{
const int thread = blockDim.x * blockIdx.x + threadIdx.x;
if ( thread >= threads )
return;
int i;
uint32_t * __restrict__ ctx_state = d_ctx_state + thread * 50;
uint64_t hash[4];
uint32_t state[50];
#pragma unroll
for ( i = 0; i < 50; i++ )
state[i] = ctx_state[i];
cn_keccakf2( (uint64_t *) state );
switch ( ( (uint8_t *) state )[0] & 0x03 )
{
case 0:
cn_blake( (const uint8_t *) state, 200, (uint8_t *) hash );
break;
case 1:
cn_groestl( (const BitSequence *) state, 200, (BitSequence *) hash );
break;
case 2:
cn_jh( (const BitSequence *) state, 200, (BitSequence *) hash );
break;
case 3:
cn_skein( (const BitSequence *) state, 200, (BitSequence *) hash );
break;
default:
break;
}
// Note that comparison is equivalent to subtraction - we can't just compare 8 32-bit values
// and expect an accurate result for target > 32-bit without implementing carries
if ( hash[3] < target )
{
uint32_t idx = atomicInc( d_res_count, 0xFFFFFFFF );
if(idx < 10)
d_res_nonce[idx] = thread;
}
}
extern "C" void cryptonight_extra_cpu_set_data( nvid_ctx* ctx, const void *data, uint32_t len )
{
ctx->inputlen = len;
CUDA_CHECK(ctx->device_id, cudaMemcpy( ctx->d_input, data, len, cudaMemcpyHostToDevice ));
}
extern "C" int cryptonight_extra_cpu_init(nvid_ctx* ctx)
{
cudaError_t err;
err = cudaSetDevice(ctx->device_id);
if(err != cudaSuccess)
{
printf("GPU %d: %s", ctx->device_id, cudaGetErrorString(err));
return 0;
}
cudaDeviceReset();
cudaSetDeviceFlags(cudaDeviceScheduleBlockingSync);
cudaDeviceSetCacheConfig(cudaFuncCachePreferL1);
size_t wsize = ctx->device_blocks * ctx->device_threads;
CUDA_CHECK(ctx->device_id, cudaMalloc(&ctx->d_long_state, (size_t)MEMORY * wsize));
CUDA_CHECK(ctx->device_id, cudaMalloc(&ctx->d_ctx_state, 50 * sizeof(uint32_t) * wsize));
CUDA_CHECK(ctx->device_id, cudaMalloc(&ctx->d_ctx_key1, 40 * sizeof(uint32_t) * wsize));
CUDA_CHECK(ctx->device_id, cudaMalloc(&ctx->d_ctx_key2, 40 * sizeof(uint32_t) * wsize));
CUDA_CHECK(ctx->device_id, cudaMalloc(&ctx->d_ctx_text, 32 * sizeof(uint32_t) * wsize));
CUDA_CHECK(ctx->device_id, cudaMalloc(&ctx->d_ctx_a, 4 * sizeof(uint32_t) * wsize));
CUDA_CHECK(ctx->device_id, cudaMalloc(&ctx->d_ctx_b, 4 * sizeof(uint32_t) * wsize));
CUDA_CHECK(ctx->device_id, cudaMalloc(&ctx->d_input, 21 * sizeof (uint32_t ) ));
CUDA_CHECK(ctx->device_id, cudaMalloc(&ctx->d_result_count, sizeof (uint32_t ) ));
CUDA_CHECK(ctx->device_id, cudaMalloc(&ctx->d_result_nonce, 10 * sizeof (uint32_t ) ));
return 1;
}
extern "C" void cryptonight_extra_cpu_prepare(nvid_ctx* ctx, uint32_t startNonce)
{
int threadsperblock = 128;
uint32_t wsize = ctx->device_blocks * ctx->device_threads;
dim3 grid( ( wsize + threadsperblock - 1 ) / threadsperblock );
dim3 block( threadsperblock );
CUDA_CHECK_KERNEL(ctx->device_id, cryptonight_extra_gpu_prepare<<<grid, block >>>( wsize, ctx->d_input, ctx->inputlen, startNonce,
ctx->d_ctx_state, ctx->d_ctx_a, ctx->d_ctx_b, ctx->d_ctx_key1, ctx->d_ctx_key2 ));
}
extern "C" void cryptonight_extra_cpu_final(nvid_ctx* ctx, uint32_t startNonce, uint64_t target, uint32_t* rescount, uint32_t *resnonce)
{
int threadsperblock = 128;
uint32_t wsize = ctx->device_blocks * ctx->device_threads;
dim3 grid( ( wsize + threadsperblock - 1 ) / threadsperblock );
dim3 block( threadsperblock );
CUDA_CHECK(ctx->device_id, cudaMemset( ctx->d_result_nonce, 0xFF, 10 * sizeof (uint32_t ) ));
CUDA_CHECK(ctx->device_id, cudaMemset( ctx->d_result_count, 0, sizeof (uint32_t ) ));
CUDA_CHECK_KERNEL(ctx->device_id, cryptonight_extra_gpu_final<<<grid, block >>>( wsize, target, ctx->d_result_count, ctx->d_result_nonce, ctx->d_ctx_state ));
CUDA_CHECK(ctx->device_id, cudaMemcpy( rescount, ctx->d_result_count, sizeof (uint32_t ), cudaMemcpyDeviceToHost ));
CUDA_CHECK(ctx->device_id, cudaMemcpy( resnonce, ctx->d_result_nonce, 10 * sizeof (uint32_t ), cudaMemcpyDeviceToHost ));
/* There is only a 32bit limit for the counter on the device side
* therefore this value can be greater than 10, in that case limit rescount
* to 10 entries.
*/
if(*rescount > 10)
*rescount = 10;
for(int i=0; i < *rescount; i++)
resnonce[i] += startNonce;
}
extern "C" int cuda_get_devicecount( int* deviceCount)
{
cudaError_t err;
*deviceCount = 0;
err = cudaGetDeviceCount(deviceCount);
if(err != cudaSuccess)
{
if(err == cudaErrorNoDevice)
printf("ERROR: NVIDIA no CUDA device found!\n");
else if(err == cudaErrorInsufficientDriver)
printf("WARNING: NVIDIA Insufficient driver!\n");
else
printf("WARNING: NVIDIA Unable to query number of CUDA devices!\n");
return 0;
}
return 1;
}
extern "C" int cuda_get_deviceinfo(nvid_ctx* ctx)
{
cudaError_t err;
int version;
err = cudaDriverGetVersion(&version);
if(err != cudaSuccess)
{
printf("Unable to query CUDA driver version! Is an nVidia driver installed?\n");
return 0;
}
if(version < CUDART_VERSION)
{
printf("Driver does not support CUDA %d.%d API! Update your nVidia driver!\n", CUDART_VERSION / 1000, (CUDART_VERSION % 1000) / 10);
return 0;
}
int GPU_N;
if(cuda_get_devicecount(&GPU_N) == 0)
{
return 0;
}
if(ctx->device_id >= GPU_N)
{
printf("Invalid device ID!\n");
return 0;
}
cudaDeviceProp props;
err = cudaGetDeviceProperties(&props, ctx->device_id);
if(err != cudaSuccess)
{
printf("\nGPU %d: %s\n%s line %d\n", ctx->device_id, cudaGetErrorString(err), __FILE__, __LINE__);
return 0;
}
ctx->device_name = strdup(props.name);
ctx->device_mpcount = props.multiProcessorCount;
ctx->device_arch[0] = props.major;
ctx->device_arch[1] = props.minor;
ctx->name = std::string(props.name);
// set all evice option those marked as auto (-1) to a valid value
if(ctx->device_blocks == -1)
{
/* good values based of my experience
* - 3 * SMX count >=sm_30
* - 2 * SMX count for <sm_30
*/
ctx->device_blocks = props.multiProcessorCount *
( props.major < 3 ? 2 : 3 );
}
if(ctx->device_threads == -1)
{
/* sm_20 devices can only run 512 threads per cuda block
* `cryptonight_core_gpu_phase1` and `cryptonight_core_gpu_phase3` starts
* `8 * ctx->device_threads` threads per block
*/
ctx->device_threads = 64;
constexpr size_t byte2mib = 1024u * 1024u;
// no limit by default 1TiB
size_t maxMemUsage = byte2mib * byte2mib;
if(props.major < 6)
{
// limit memory usage for GPUs before pascal
maxMemUsage = size_t(2048u) * byte2mib;
}
if(props.major == 2)
{
// limit memory usage for sm 20 GPUs
maxMemUsage = size_t(1024u) * byte2mib;
}
size_t freeMemory = 0;
size_t totalMemory = 0;
CUDA_CHECK(ctx->device_id, cudaMemGetInfo(&freeMemory, &totalMemory));
ctx->total_device_memory = totalMemory;
ctx->free_device_memory = freeMemory;
// keep 64MiB memory free (value is randomly chosen)
// 200byte are meta data memory (result nonce, ...)
size_t availableMem = freeMemory - (64u * 1024 * 1024) - 200u;
size_t limitedMemory = std::min(availableMem, maxMemUsage);
// up to 920bytes extra memory is used per thread for some kernel (lmem/local memory)
// 680bytes are extra meta data memory per hash
size_t perThread = size_t(MEMORY) + 740u + 680u;
size_t max_intensity = limitedMemory / perThread;
ctx->device_threads = max_intensity / ctx->device_blocks;
// use only odd number of threads
ctx->device_threads = ctx->device_threads & 0xFFFFFFFE;
if(props.major == 2 && ctx->device_threads > 64)
{
// Fermi gpus only support 512 threads per block (we need start 4 * configured threads)
ctx->device_threads = 64;
}
}
return 1;
}
@@ -0,0 +1,104 @@
#pragma once
#ifdef __INTELLISENSE__
#define __CUDA_ARCH__ 520
/* avoid red underlining */
struct uint3
{
unsigned int x, y, z;
};
struct uint3 threadIdx;
struct uint3 blockIdx;
struct uint3 blockDim;
#define __funnelshift_r(a,b,c) 1
#define __syncthreads()
#define asm(x)
#define __shfl(a,b,c) 1
#endif
#define MEMORY (1 << 21) // 2 MiB / 2097152 B
#define ITER (1 << 20) // 1048576
#define AES_BLOCK_SIZE 16
#define AES_KEY_SIZE 32
#define INIT_SIZE_BLK 8
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE) // 128 B
#define C32(x) ((uint32_t)(x ## U))
#define T32(x) ((x) & C32(0xFFFFFFFF))
#if __CUDA_ARCH__ >= 350
__forceinline__ __device__ uint64_t cuda_ROTL64(const uint64_t value, const int offset)
{
uint2 result;
if(offset >= 32)
{
asm("shf.l.wrap.b32 %0, %1, %2, %3;" : "=r"(result.x) : "r"(__double2loint(__longlong_as_double(value))), "r"(__double2hiint(__longlong_as_double(value))), "r"(offset));
asm("shf.l.wrap.b32 %0, %1, %2, %3;" : "=r"(result.y) : "r"(__double2hiint(__longlong_as_double(value))), "r"(__double2loint(__longlong_as_double(value))), "r"(offset));
}
else
{
asm("shf.l.wrap.b32 %0, %1, %2, %3;" : "=r"(result.x) : "r"(__double2hiint(__longlong_as_double(value))), "r"(__double2loint(__longlong_as_double(value))), "r"(offset));
asm("shf.l.wrap.b32 %0, %1, %2, %3;" : "=r"(result.y) : "r"(__double2loint(__longlong_as_double(value))), "r"(__double2hiint(__longlong_as_double(value))), "r"(offset));
}
return __double_as_longlong(__hiloint2double(result.y, result.x));
}
#define ROTL64(x, n) (cuda_ROTL64(x, n))
#else
#define ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
#endif
#if __CUDA_ARCH__ < 350
#define ROTL32(x, n) T32(((x) << (n)) | ((x) >> (32 - (n))))
#define ROTR32(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
#else
#define ROTL32(x, n) __funnelshift_l( (x), (x), (n) )
#define ROTR32(x, n) __funnelshift_r( (x), (x), (n) )
#endif
#define MEMSET8(dst,what,cnt) { \
int i_memset8; \
uint64_t *out_memset8 = (uint64_t *)(dst); \
for( i_memset8 = 0; i_memset8 < cnt; i_memset8++ ) \
out_memset8[i_memset8] = (what); }
#define MEMSET4(dst,what,cnt) { \
int i_memset4; \
uint32_t *out_memset4 = (uint32_t *)(dst); \
for( i_memset4 = 0; i_memset4 < cnt; i_memset4++ ) \
out_memset4[i_memset4] = (what); }
#define MEMCPY8(dst,src,cnt) { \
int i_memcpy8; \
uint64_t *in_memcpy8 = (uint64_t *)(src); \
uint64_t *out_memcpy8 = (uint64_t *)(dst); \
for( i_memcpy8 = 0; i_memcpy8 < cnt; i_memcpy8++ ) \
out_memcpy8[i_memcpy8] = in_memcpy8[i_memcpy8]; }
#define MEMCPY4(dst,src,cnt) { \
int i_memcpy4; \
uint32_t *in_memcpy4 = (uint32_t *)(src); \
uint32_t *out_memcpy4 = (uint32_t *)(dst); \
for( i_memcpy4 = 0; i_memcpy4 < cnt; i_memcpy4++ ) \
out_memcpy4[i_memcpy4] = in_memcpy4[i_memcpy4]; }
#define XOR_BLOCKS(a,b) { \
((uint64_t *)a)[0] ^= ((uint64_t *)b)[0]; \
((uint64_t *)a)[1] ^= ((uint64_t *)b)[1]; }
#define XOR_BLOCKS_DST(x,y,z) { \
((uint64_t *)z)[0] = ((uint64_t *)(x))[0] ^ ((uint64_t *)(y))[0]; \
((uint64_t *)z)[1] = ((uint64_t *)(x))[1] ^ ((uint64_t *)(y))[1]; }
#define MUL_SUM_XOR_DST(a,c,dst) { \
const uint64_t dst0 = ((uint64_t *)dst)[0]; \
uint64_t hi, lo = cuda_mul128(((uint64_t *)a)[0], dst0, &hi) + ((uint64_t *)c)[1]; \
hi += ((uint64_t *)c)[0]; \
((uint64_t *)c)[0] = dst0 ^ hi; \
((uint64_t *)dst)[0] = hi; \
((uint64_t *)c)[1] = atomicExch(((unsigned long long int *)dst) + 1, (unsigned long long int)lo) ^ lo; \
}
#define E2I(x) ((size_t)(((*((uint64_t*)(x)) >> 4) & 0x1ffff)))
@@ -0,0 +1,357 @@
#pragma once
#define GROESTL_ROWS 8
#define GROESTL_LENGTHFIELDLEN GROESTL_ROWS
#define GROESTL_COLS512 8
#define GROESTL_SIZE512 (GROESTL_ROWS*GROESTL_COLS512)
#define GROESTL_ROUNDS512 10
#define GROESTL_HASH_BIT_LEN 256
#define GROESTL_ROTL32(v, n) ROTL32(v, n)
#define li_32(h) 0x##h##u
#define GROESTL_EXT_BYTE(var,n) ((uint8_t)((uint32_t)(var) >> (8*n)))
#define u32BIG(a) \
((GROESTL_ROTL32(a,8) & li_32(00FF00FF)) | (GROESTL_ROTL32(a,24) & li_32(FF00FF00)))
typedef struct {
uint32_t chaining[GROESTL_SIZE512/sizeof(uint32_t)]; /* actual state */
uint32_t block_counter1,
block_counter2; /* message block counter(s) */
BitSequence buffer[GROESTL_SIZE512]; /* data buffer */
int buf_ptr; /* data buffer pointer */
int bits_in_last_byte; /* no. of message bits in last byte of data buffer */
} groestlHashState;
__constant__ uint32_t d_groestl_T[512] =
{
0xa5f432c6, 0xc6a597f4, 0x84976ff8, 0xf884eb97, 0x99b05eee, 0xee99c7b0, 0x8d8c7af6, 0xf68df78c, 0xd17e8ff, 0xff0de517, 0xbddc0ad6, 0xd6bdb7dc, 0xb1c816de, 0xdeb1a7c8, 0x54fc6d91, 0x915439fc
, 0x50f09060, 0x6050c0f0, 0x3050702, 0x2030405, 0xa9e02ece, 0xcea987e0, 0x7d87d156, 0x567dac87, 0x192bcce7, 0xe719d52b, 0x62a613b5, 0xb56271a6, 0xe6317c4d, 0x4de69a31, 0x9ab559ec, 0xec9ac3b5
, 0x45cf408f, 0x8f4505cf, 0x9dbca31f, 0x1f9d3ebc, 0x40c04989, 0x894009c0, 0x879268fa, 0xfa87ef92, 0x153fd0ef, 0xef15c53f, 0xeb2694b2, 0xb2eb7f26, 0xc940ce8e, 0x8ec90740, 0xb1de6fb, 0xfb0bed1d
, 0xec2f6e41, 0x41ec822f, 0x67a91ab3, 0xb3677da9, 0xfd1c435f, 0x5ffdbe1c, 0xea256045, 0x45ea8a25, 0xbfdaf923, 0x23bf46da, 0xf7025153, 0x53f7a602, 0x96a145e4, 0xe496d3a1, 0x5bed769b, 0x9b5b2ded
, 0xc25d2875, 0x75c2ea5d, 0x1c24c5e1, 0xe11cd924, 0xaee9d43d, 0x3dae7ae9, 0x6abef24c, 0x4c6a98be, 0x5aee826c, 0x6c5ad8ee, 0x41c3bd7e, 0x7e41fcc3, 0x206f3f5, 0xf502f106, 0x4fd15283, 0x834f1dd1
, 0x5ce48c68, 0x685cd0e4, 0xf4075651, 0x51f4a207, 0x345c8dd1, 0xd134b95c, 0x818e1f9, 0xf908e918, 0x93ae4ce2, 0xe293dfae, 0x73953eab, 0xab734d95, 0x53f59762, 0x6253c4f5, 0x3f416b2a, 0x2a3f5441
, 0xc141c08, 0x80c1014, 0x52f66395, 0x955231f6, 0x65afe946, 0x46658caf, 0x5ee27f9d, 0x9d5e21e2, 0x28784830, 0x30286078, 0xa1f8cf37, 0x37a16ef8, 0xf111b0a, 0xa0f1411, 0xb5c4eb2f, 0x2fb55ec4
, 0x91b150e, 0xe091c1b, 0x365a7e24, 0x2436485a, 0x9bb6ad1b, 0x1b9b36b6, 0x3d4798df, 0xdf3da547, 0x266aa7cd, 0xcd26816a, 0x69bbf54e, 0x4e699cbb, 0xcd4c337f, 0x7fcdfe4c, 0x9fba50ea, 0xea9fcfba
, 0x1b2d3f12, 0x121b242d, 0x9eb9a41d, 0x1d9e3ab9, 0x749cc458, 0x5874b09c, 0x2e724634, 0x342e6872, 0x2d774136, 0x362d6c77, 0xb2cd11dc, 0xdcb2a3cd, 0xee299db4, 0xb4ee7329, 0xfb164d5b, 0x5bfbb616
, 0xf601a5a4, 0xa4f65301, 0x4dd7a176, 0x764decd7, 0x61a314b7, 0xb76175a3, 0xce49347d, 0x7dcefa49, 0x7b8ddf52, 0x527ba48d, 0x3e429fdd, 0xdd3ea142, 0x7193cd5e, 0x5e71bc93, 0x97a2b113, 0x139726a2
, 0xf504a2a6, 0xa6f55704, 0x68b801b9, 0xb96869b8, 0x0, 0x0, 0x2c74b5c1, 0xc12c9974, 0x60a0e040, 0x406080a0, 0x1f21c2e3, 0xe31fdd21, 0xc8433a79, 0x79c8f243, 0xed2c9ab6, 0xb6ed772c
, 0xbed90dd4, 0xd4beb3d9, 0x46ca478d, 0x8d4601ca, 0xd9701767, 0x67d9ce70, 0x4bddaf72, 0x724be4dd, 0xde79ed94, 0x94de3379, 0xd467ff98, 0x98d42b67, 0xe82393b0, 0xb0e87b23, 0x4ade5b85, 0x854a11de
, 0x6bbd06bb, 0xbb6b6dbd, 0x2a7ebbc5, 0xc52a917e, 0xe5347b4f, 0x4fe59e34, 0x163ad7ed, 0xed16c13a, 0xc554d286, 0x86c51754, 0xd762f89a, 0x9ad72f62, 0x55ff9966, 0x6655ccff, 0x94a7b611, 0x119422a7
, 0xcf4ac08a, 0x8acf0f4a, 0x1030d9e9, 0xe910c930, 0x60a0e04, 0x406080a, 0x819866fe, 0xfe81e798, 0xf00baba0, 0xa0f05b0b, 0x44ccb478, 0x7844f0cc, 0xbad5f025, 0x25ba4ad5, 0xe33e754b, 0x4be3963e
, 0xf30eaca2, 0xa2f35f0e, 0xfe19445d, 0x5dfeba19, 0xc05bdb80, 0x80c01b5b, 0x8a858005, 0x58a0a85, 0xadecd33f, 0x3fad7eec, 0xbcdffe21, 0x21bc42df, 0x48d8a870, 0x7048e0d8, 0x40cfdf1, 0xf104f90c
, 0xdf7a1963, 0x63dfc67a, 0xc1582f77, 0x77c1ee58, 0x759f30af, 0xaf75459f, 0x63a5e742, 0x426384a5, 0x30507020, 0x20304050, 0x1a2ecbe5, 0xe51ad12e, 0xe12effd, 0xfd0ee112, 0x6db708bf, 0xbf6d65b7
, 0x4cd45581, 0x814c19d4, 0x143c2418, 0x1814303c, 0x355f7926, 0x26354c5f, 0x2f71b2c3, 0xc32f9d71, 0xe13886be, 0xbee16738, 0xa2fdc835, 0x35a26afd, 0xcc4fc788, 0x88cc0b4f, 0x394b652e, 0x2e395c4b
, 0x57f96a93, 0x93573df9, 0xf20d5855, 0x55f2aa0d, 0x829d61fc, 0xfc82e39d, 0x47c9b37a, 0x7a47f4c9, 0xacef27c8, 0xc8ac8bef, 0xe73288ba, 0xbae76f32, 0x2b7d4f32, 0x322b647d, 0x95a442e6, 0xe695d7a4
, 0xa0fb3bc0, 0xc0a09bfb, 0x98b3aa19, 0x199832b3, 0xd168f69e, 0x9ed12768, 0x7f8122a3, 0xa37f5d81, 0x66aaee44, 0x446688aa, 0x7e82d654, 0x547ea882, 0xabe6dd3b, 0x3bab76e6, 0x839e950b, 0xb83169e
, 0xca45c98c, 0x8cca0345, 0x297bbcc7, 0xc729957b, 0xd36e056b, 0x6bd3d66e, 0x3c446c28, 0x283c5044, 0x798b2ca7, 0xa779558b, 0xe23d81bc, 0xbce2633d, 0x1d273116, 0x161d2c27, 0x769a37ad, 0xad76419a
, 0x3b4d96db, 0xdb3bad4d, 0x56fa9e64, 0x6456c8fa, 0x4ed2a674, 0x744ee8d2, 0x1e223614, 0x141e2822, 0xdb76e492, 0x92db3f76, 0xa1e120c, 0xc0a181e, 0x6cb4fc48, 0x486c90b4, 0xe4378fb8, 0xb8e46b37
, 0x5de7789f, 0x9f5d25e7, 0x6eb20fbd, 0xbd6e61b2, 0xef2a6943, 0x43ef862a, 0xa6f135c4, 0xc4a693f1, 0xa8e3da39, 0x39a872e3, 0xa4f7c631, 0x31a462f7, 0x37598ad3, 0xd337bd59, 0x8b8674f2, 0xf28bff86
, 0x325683d5, 0xd532b156, 0x43c54e8b, 0x8b430dc5, 0x59eb856e, 0x6e59dceb, 0xb7c218da, 0xdab7afc2, 0x8c8f8e01, 0x18c028f, 0x64ac1db1, 0xb16479ac, 0xd26df19c, 0x9cd2236d, 0xe03b7249, 0x49e0923b
, 0xb4c71fd8, 0xd8b4abc7, 0xfa15b9ac, 0xacfa4315, 0x709faf3, 0xf307fd09, 0x256fa0cf, 0xcf25856f, 0xafea20ca, 0xcaaf8fea, 0x8e897df4, 0xf48ef389, 0xe9206747, 0x47e98e20, 0x18283810, 0x10182028
, 0xd5640b6f, 0x6fd5de64, 0x888373f0, 0xf088fb83, 0x6fb1fb4a, 0x4a6f94b1, 0x7296ca5c, 0x5c72b896, 0x246c5438, 0x3824706c, 0xf1085f57, 0x57f1ae08, 0xc7522173, 0x73c7e652, 0x51f36497, 0x975135f3
, 0x2365aecb, 0xcb238d65, 0x7c8425a1, 0xa17c5984, 0x9cbf57e8, 0xe89ccbbf, 0x21635d3e, 0x3e217c63, 0xdd7cea96, 0x96dd377c, 0xdc7f1e61, 0x61dcc27f, 0x86919c0d, 0xd861a91, 0x85949b0f, 0xf851e94
, 0x90ab4be0, 0xe090dbab, 0x42c6ba7c, 0x7c42f8c6, 0xc4572671, 0x71c4e257, 0xaae529cc, 0xccaa83e5, 0xd873e390, 0x90d83b73, 0x50f0906, 0x6050c0f, 0x103f4f7, 0xf701f503, 0x12362a1c, 0x1c123836
, 0xa3fe3cc2, 0xc2a39ffe, 0x5fe18b6a, 0x6a5fd4e1, 0xf910beae, 0xaef94710, 0xd06b0269, 0x69d0d26b, 0x91a8bf17, 0x17912ea8, 0x58e87199, 0x995829e8, 0x2769533a, 0x3a277469, 0xb9d0f727, 0x27b94ed0
, 0x384891d9, 0xd938a948, 0x1335deeb, 0xeb13cd35, 0xb3cee52b, 0x2bb356ce, 0x33557722, 0x22334455, 0xbbd604d2, 0xd2bbbfd6, 0x709039a9, 0xa9704990, 0x89808707, 0x7890e80, 0xa7f2c133, 0x33a766f2
, 0xb6c1ec2d, 0x2db65ac1, 0x22665a3c, 0x3c227866, 0x92adb815, 0x15922aad, 0x2060a9c9, 0xc9208960, 0x49db5c87, 0x874915db, 0xff1ab0aa, 0xaaff4f1a, 0x7888d850, 0x5078a088, 0x7a8e2ba5, 0xa57a518e
, 0x8f8a8903, 0x38f068a, 0xf8134a59, 0x59f8b213, 0x809b9209, 0x980129b, 0x1739231a, 0x1a173439, 0xda751065, 0x65daca75, 0x315384d7, 0xd731b553, 0xc651d584, 0x84c61351, 0xb8d303d0, 0xd0b8bbd3
, 0xc35edc82, 0x82c31f5e, 0xb0cbe229, 0x29b052cb, 0x7799c35a, 0x5a77b499, 0x11332d1e, 0x1e113c33, 0xcb463d7b, 0x7bcbf646, 0xfc1fb7a8, 0xa8fc4b1f, 0xd6610c6d, 0x6dd6da61, 0x3a4e622c, 0x2c3a584e
};
#define GROESTL_ROTATE_COLUMN_DOWN(v1, v2, amount_bytes, temp_var) \
{ temp_var = (v1<<(8*amount_bytes))|(v2>>(8*(4-amount_bytes))); \
v2 = (v2<<(8*amount_bytes))|(v1>>(8*(4-amount_bytes))); \
v1 = temp_var; }
#define GROESTL_COLUMN(x,y,i,c0,c1,c2,c3,c4,c5,c6,c7,tv1,tv2,tu,tl,t) \
tu = d_groestl_T[2*(uint32_t)x[4*c0+0]]; \
tl = d_groestl_T[2*(uint32_t)x[4*c0+0]+1]; \
tv1 = d_groestl_T[2*(uint32_t)x[4*c1+1]]; \
tv2 = d_groestl_T[2*(uint32_t)x[4*c1+1]+1]; \
GROESTL_ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \
tu ^= tv1; \
tl ^= tv2; \
tv1 = d_groestl_T[2*(uint32_t)x[4*c2+2]]; \
tv2 = d_groestl_T[2*(uint32_t)x[4*c2+2]+1]; \
GROESTL_ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \
tu ^= tv1; \
tl ^= tv2; \
tv1 = d_groestl_T[2*(uint32_t)x[4*c3+3]]; \
tv2 = d_groestl_T[2*(uint32_t)x[4*c3+3]+1]; \
GROESTL_ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \
tu ^= tv1; \
tl ^= tv2; \
tl ^= d_groestl_T[2*(uint32_t)x[4*c4+0]]; \
tu ^= d_groestl_T[2*(uint32_t)x[4*c4+0]+1]; \
tv1 = d_groestl_T[2*(uint32_t)x[4*c5+1]]; \
tv2 = d_groestl_T[2*(uint32_t)x[4*c5+1]+1]; \
GROESTL_ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \
tl ^= tv1; \
tu ^= tv2; \
tv1 = d_groestl_T[2*(uint32_t)x[4*c6+2]]; \
tv2 = d_groestl_T[2*(uint32_t)x[4*c6+2]+1]; \
GROESTL_ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \
tl ^= tv1; \
tu ^= tv2; \
tv1 = d_groestl_T[2*(uint32_t)x[4*c7+3]]; \
tv2 = d_groestl_T[2*(uint32_t)x[4*c7+3]+1]; \
GROESTL_ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \
tl ^= tv1; \
tu ^= tv2; \
y[i] = tu; \
y[i+1] = tl;
__device__ void cn_groestl_RND512P(uint8_t * __restrict__ x, uint32_t * __restrict__ y, uint32_t r)
{
uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp;
uint32_t* x32 = (uint32_t*)x;
x32[ 0] ^= 0x00000000^r;
x32[ 2] ^= 0x00000010^r;
x32[ 4] ^= 0x00000020^r;
x32[ 6] ^= 0x00000030^r;
x32[ 8] ^= 0x00000040^r;
x32[10] ^= 0x00000050^r;
x32[12] ^= 0x00000060^r;
x32[14] ^= 0x00000070^r;
GROESTL_COLUMN(x,y, 0, 0, 2, 4, 6, 9, 11, 13, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
GROESTL_COLUMN(x,y, 2, 2, 4, 6, 8, 11, 13, 15, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
GROESTL_COLUMN(x,y, 4, 4, 6, 8, 10, 13, 15, 1, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
GROESTL_COLUMN(x,y, 6, 6, 8, 10, 12, 15, 1, 3, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
GROESTL_COLUMN(x,y, 8, 8, 10, 12, 14, 1, 3, 5, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
GROESTL_COLUMN(x,y,10, 10, 12, 14, 0, 3, 5, 7, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
GROESTL_COLUMN(x,y,12, 12, 14, 0, 2, 5, 7, 9, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
GROESTL_COLUMN(x,y,14, 14, 0, 2, 4, 7, 9, 11, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
}
__device__ void cn_groestl_RND512Q(uint8_t * __restrict__ x, uint32_t * __restrict__ y, uint32_t r)
{
uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp;
uint32_t* x32 = (uint32_t*)x;
x32[ 0] = ~x32[ 0];
x32[ 1] ^= 0xffffffff^r;
x32[ 2] = ~x32[ 2];
x32[ 3] ^= 0xefffffff^r;
x32[ 4] = ~x32[ 4];
x32[ 5] ^= 0xdfffffff^r;
x32[ 6] = ~x32[ 6];
x32[ 7] ^= 0xcfffffff^r;
x32[ 8] = ~x32[ 8];
x32[ 9] ^= 0xbfffffff^r;
x32[10] = ~x32[10];
x32[11] ^= 0xafffffff^r;
x32[12] = ~x32[12];
x32[13] ^= 0x9fffffff^r;
x32[14] = ~x32[14];
x32[15] ^= 0x8fffffff^r;
GROESTL_COLUMN(x,y, 0, 2, 6, 10, 14, 1, 5, 9, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
GROESTL_COLUMN(x,y, 2, 4, 8, 12, 0, 3, 7, 11, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
GROESTL_COLUMN(x,y, 4, 6, 10, 14, 2, 5, 9, 13, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
GROESTL_COLUMN(x,y, 6, 8, 12, 0, 4, 7, 11, 15, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
GROESTL_COLUMN(x,y, 8, 10, 14, 2, 6, 9, 13, 1, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
GROESTL_COLUMN(x,y,10, 12, 0, 4, 8, 11, 15, 3, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
GROESTL_COLUMN(x,y,12, 14, 2, 6, 10, 13, 1, 5, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
GROESTL_COLUMN(x,y,14, 0, 4, 8, 12, 15, 3, 7, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
}
__device__ void cn_groestl_F512(uint32_t * __restrict__ h, const uint32_t * __restrict__ m)
{
int i;
uint32_t Ptmp[2*GROESTL_COLS512];
uint32_t Qtmp[2*GROESTL_COLS512];
uint32_t y[2*GROESTL_COLS512];
uint32_t z[2*GROESTL_COLS512];
for (i = 0; i < 2*GROESTL_COLS512; i++)
{
z[i] = m[i];
Ptmp[i] = h[i]^m[i];
}
cn_groestl_RND512Q((uint8_t*)z, y, 0x00000000);
cn_groestl_RND512Q((uint8_t*)y, z, 0x01000000);
cn_groestl_RND512Q((uint8_t*)z, y, 0x02000000);
cn_groestl_RND512Q((uint8_t*)y, z, 0x03000000);
cn_groestl_RND512Q((uint8_t*)z, y, 0x04000000);
cn_groestl_RND512Q((uint8_t*)y, z, 0x05000000);
cn_groestl_RND512Q((uint8_t*)z, y, 0x06000000);
cn_groestl_RND512Q((uint8_t*)y, z, 0x07000000);
cn_groestl_RND512Q((uint8_t*)z, y, 0x08000000);
cn_groestl_RND512Q((uint8_t*)y, Qtmp, 0x09000000);
cn_groestl_RND512P((uint8_t*)Ptmp, y, 0x00000000);
cn_groestl_RND512P((uint8_t*)y, z, 0x00000001);
cn_groestl_RND512P((uint8_t*)z, y, 0x00000002);
cn_groestl_RND512P((uint8_t*)y, z, 0x00000003);
cn_groestl_RND512P((uint8_t*)z, y, 0x00000004);
cn_groestl_RND512P((uint8_t*)y, z, 0x00000005);
cn_groestl_RND512P((uint8_t*)z, y, 0x00000006);
cn_groestl_RND512P((uint8_t*)y, z, 0x00000007);
cn_groestl_RND512P((uint8_t*)z, y, 0x00000008);
cn_groestl_RND512P((uint8_t*)y, Ptmp, 0x00000009);
for (i = 0; i < 2*GROESTL_COLS512; i++)
h[i] ^= Ptmp[i]^Qtmp[i];
}
__device__ void cn_groestl_outputtransformation(groestlHashState *ctx)
{
int j;
uint32_t temp[2*GROESTL_COLS512];
uint32_t y[2*GROESTL_COLS512];
uint32_t z[2*GROESTL_COLS512];
for (j = 0; j < 2*GROESTL_COLS512; j++)
temp[j] = ctx->chaining[j];
cn_groestl_RND512P((uint8_t*)temp, y, 0x00000000);
cn_groestl_RND512P((uint8_t*)y, z, 0x00000001);
cn_groestl_RND512P((uint8_t*)z, y, 0x00000002);
cn_groestl_RND512P((uint8_t*)y, z, 0x00000003);
cn_groestl_RND512P((uint8_t*)z, y, 0x00000004);
cn_groestl_RND512P((uint8_t*)y, z, 0x00000005);
cn_groestl_RND512P((uint8_t*)z, y, 0x00000006);
cn_groestl_RND512P((uint8_t*)y, z, 0x00000007);
cn_groestl_RND512P((uint8_t*)z, y, 0x00000008);
cn_groestl_RND512P((uint8_t*)y, temp, 0x00000009);
for (j = 0; j < 2*GROESTL_COLS512; j++)
ctx->chaining[j] ^= temp[j];
}
__device__ void cn_groestl_transform(groestlHashState * __restrict__ ctx,
const uint8_t * __restrict__ input, int msglen)
{
for (; msglen >= GROESTL_SIZE512; msglen -= GROESTL_SIZE512, input += GROESTL_SIZE512)
{
cn_groestl_F512(ctx->chaining,(uint32_t*)input);
ctx->block_counter1++;
if (ctx->block_counter1 == 0)
ctx->block_counter2++;
}
}
__device__ void cn_groestl_final(groestlHashState* __restrict__ ctx,
BitSequence* __restrict__ output)
{
int i, j = 0, hashbytelen = GROESTL_HASH_BIT_LEN/8;
uint8_t *s = (BitSequence*)ctx->chaining;
if (ctx->bits_in_last_byte)
{
ctx->buffer[(int)ctx->buf_ptr-1] &= ((1<<ctx->bits_in_last_byte)-1)<<(8-ctx->bits_in_last_byte);
ctx->buffer[(int)ctx->buf_ptr-1] ^= 0x1<<(7-ctx->bits_in_last_byte);
ctx->bits_in_last_byte = 0;
}
else
{
ctx->buffer[(int)ctx->buf_ptr++] = 0x80;
}
if (ctx->buf_ptr > GROESTL_SIZE512-GROESTL_LENGTHFIELDLEN)
{
while (ctx->buf_ptr < GROESTL_SIZE512)
ctx->buffer[(int)ctx->buf_ptr++] = 0;
cn_groestl_transform(ctx, ctx->buffer, GROESTL_SIZE512);
ctx->buf_ptr = 0;
}
while (ctx->buf_ptr < GROESTL_SIZE512-GROESTL_LENGTHFIELDLEN)
ctx->buffer[(int)ctx->buf_ptr++] = 0;
ctx->block_counter1++;
if (ctx->block_counter1 == 0)
ctx->block_counter2++;
ctx->buf_ptr = GROESTL_SIZE512;
while (ctx->buf_ptr > GROESTL_SIZE512-(int)sizeof(uint32_t))
{
ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter1;
ctx->block_counter1 >>= 8;
}
while (ctx->buf_ptr > GROESTL_SIZE512-GROESTL_LENGTHFIELDLEN)
{
ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter2;
ctx->block_counter2 >>= 8;
}
cn_groestl_transform(ctx, ctx->buffer, GROESTL_SIZE512);
cn_groestl_outputtransformation(ctx);
for (i = GROESTL_SIZE512-hashbytelen; i < GROESTL_SIZE512; i++,j++)
output[j] = s[i];
for (i = 0; i < GROESTL_COLS512; i++)
ctx->chaining[i] = 0;
for (i = 0; i < GROESTL_SIZE512; i++)
ctx->buffer[i] = 0;
}
__device__ void cn_groestl_update(groestlHashState* __restrict__ ctx,
const BitSequence* __restrict__ input, DataLength databitlen)
{
int index = 0;
int msglen = (int)(databitlen/8);
int rem = (int)(databitlen%8);
if (ctx->buf_ptr)
{
while (ctx->buf_ptr < GROESTL_SIZE512 && index < msglen)
ctx->buffer[(int)ctx->buf_ptr++] = input[index++];
if (ctx->buf_ptr < GROESTL_SIZE512)
{
if (rem)
{
ctx->bits_in_last_byte = rem;
ctx->buffer[(int)ctx->buf_ptr++] = input[index];
}
return;
}
ctx->buf_ptr = 0;
cn_groestl_transform(ctx, ctx->buffer, GROESTL_SIZE512);
}
cn_groestl_transform(ctx, input+index, msglen-index);
index += ((msglen-index)/GROESTL_SIZE512)*GROESTL_SIZE512;
while (index < msglen)
ctx->buffer[(int)ctx->buf_ptr++] = input[index++];
if (rem)
{
ctx->bits_in_last_byte = rem;
ctx->buffer[(int)ctx->buf_ptr++] = input[index];
}
}
__device__ void cn_groestl_init(groestlHashState* ctx)
{
int i = 0;
for(;i<(GROESTL_SIZE512/sizeof(uint32_t));i++)
ctx->chaining[i] = 0;
ctx->chaining[2*GROESTL_COLS512-1] = u32BIG((uint32_t)GROESTL_HASH_BIT_LEN);
ctx->buf_ptr = 0;
ctx->block_counter1 = 0;
ctx->block_counter2 = 0;
ctx->bits_in_last_byte = 0;
}
__device__ void cn_groestl(const BitSequence * __restrict__ data, DataLength len, BitSequence * __restrict__ hashval)
{
DataLength databitlen = len << 3;
groestlHashState context;
cn_groestl_init(&context);
cn_groestl_update(&context, data, databitlen);
cn_groestl_final(&context, hashval);
}
@@ -0,0 +1,301 @@
#include <stdint.h>
typedef struct {
int hashbitlen;
unsigned long long databitlen;
unsigned long long datasize_in_buffer;
uint64_t x[8][2];
unsigned char buffer[64];
} jhHashState;
__constant__ unsigned char d_JH256_H0[512] =
{
0xeb, 0x98, 0xa3, 0x41, 0x2c, 0x20, 0xd3, 0xeb, 0x92, 0xcd, 0xbe, 0x7b, 0x9c, 0xb2, 0x45, 0xc1,
0x1c, 0x93, 0x51, 0x91, 0x60, 0xd4, 0xc7, 0xfa, 0x26, 0x0, 0x82, 0xd6, 0x7e, 0x50, 0x8a, 0x3,
0xa4, 0x23, 0x9e, 0x26, 0x77, 0x26, 0xb9, 0x45, 0xe0, 0xfb, 0x1a, 0x48, 0xd4, 0x1a, 0x94, 0x77,
0xcd, 0xb5, 0xab, 0x26, 0x2, 0x6b, 0x17, 0x7a, 0x56, 0xf0, 0x24, 0x42, 0xf, 0xff, 0x2f, 0xa8,
0x71, 0xa3, 0x96, 0x89, 0x7f, 0x2e, 0x4d, 0x75, 0x1d, 0x14, 0x49, 0x8, 0xf7, 0x7d, 0xe2, 0x62,
0x27, 0x76, 0x95, 0xf7, 0x76, 0x24, 0x8f, 0x94, 0x87, 0xd5, 0xb6, 0x57, 0x47, 0x80, 0x29, 0x6c,
0x5c, 0x5e, 0x27, 0x2d, 0xac, 0x8e, 0xd, 0x6c, 0x51, 0x84, 0x50, 0xc6, 0x57, 0x5, 0x7a, 0xf,
0x7b, 0xe4, 0xd3, 0x67, 0x70, 0x24, 0x12, 0xea, 0x89, 0xe3, 0xab, 0x13, 0xd3, 0x1c, 0xd7, 0x69
};
__constant__ unsigned char d_E8_rc[42][32] =
{
{0x72, 0xd5, 0xde, 0xa2, 0xdf, 0x15, 0xf8, 0x67, 0x7b, 0x84, 0x15, 0xa, 0xb7, 0x23, 0x15, 0x57, 0x81, 0xab, 0xd6, 0x90, 0x4d, 0x5a, 0x87, 0xf6, 0x4e, 0x9f, 0x4f, 0xc5, 0xc3, 0xd1, 0x2b, 0x40},
{0xea, 0x98, 0x3a, 0xe0, 0x5c, 0x45, 0xfa, 0x9c, 0x3, 0xc5, 0xd2, 0x99, 0x66, 0xb2, 0x99, 0x9a, 0x66, 0x2, 0x96, 0xb4, 0xf2, 0xbb, 0x53, 0x8a, 0xb5, 0x56, 0x14, 0x1a, 0x88, 0xdb, 0xa2, 0x31},
{0x3, 0xa3, 0x5a, 0x5c, 0x9a, 0x19, 0xe, 0xdb, 0x40, 0x3f, 0xb2, 0xa, 0x87, 0xc1, 0x44, 0x10, 0x1c, 0x5, 0x19, 0x80, 0x84, 0x9e, 0x95, 0x1d, 0x6f, 0x33, 0xeb, 0xad, 0x5e, 0xe7, 0xcd, 0xdc},
{0x10, 0xba, 0x13, 0x92, 0x2, 0xbf, 0x6b, 0x41, 0xdc, 0x78, 0x65, 0x15, 0xf7, 0xbb, 0x27, 0xd0, 0xa, 0x2c, 0x81, 0x39, 0x37, 0xaa, 0x78, 0x50, 0x3f, 0x1a, 0xbf, 0xd2, 0x41, 0x0, 0x91, 0xd3},
{0x42, 0x2d, 0x5a, 0xd, 0xf6, 0xcc, 0x7e, 0x90, 0xdd, 0x62, 0x9f, 0x9c, 0x92, 0xc0, 0x97, 0xce, 0x18, 0x5c, 0xa7, 0xb, 0xc7, 0x2b, 0x44, 0xac, 0xd1, 0xdf, 0x65, 0xd6, 0x63, 0xc6, 0xfc, 0x23},
{0x97, 0x6e, 0x6c, 0x3, 0x9e, 0xe0, 0xb8, 0x1a, 0x21, 0x5, 0x45, 0x7e, 0x44, 0x6c, 0xec, 0xa8, 0xee, 0xf1, 0x3, 0xbb, 0x5d, 0x8e, 0x61, 0xfa, 0xfd, 0x96, 0x97, 0xb2, 0x94, 0x83, 0x81, 0x97},
{0x4a, 0x8e, 0x85, 0x37, 0xdb, 0x3, 0x30, 0x2f, 0x2a, 0x67, 0x8d, 0x2d, 0xfb, 0x9f, 0x6a, 0x95, 0x8a, 0xfe, 0x73, 0x81, 0xf8, 0xb8, 0x69, 0x6c, 0x8a, 0xc7, 0x72, 0x46, 0xc0, 0x7f, 0x42, 0x14},
{0xc5, 0xf4, 0x15, 0x8f, 0xbd, 0xc7, 0x5e, 0xc4, 0x75, 0x44, 0x6f, 0xa7, 0x8f, 0x11, 0xbb, 0x80, 0x52, 0xde, 0x75, 0xb7, 0xae, 0xe4, 0x88, 0xbc, 0x82, 0xb8, 0x0, 0x1e, 0x98, 0xa6, 0xa3, 0xf4},
{0x8e, 0xf4, 0x8f, 0x33, 0xa9, 0xa3, 0x63, 0x15, 0xaa, 0x5f, 0x56, 0x24, 0xd5, 0xb7, 0xf9, 0x89, 0xb6, 0xf1, 0xed, 0x20, 0x7c, 0x5a, 0xe0, 0xfd, 0x36, 0xca, 0xe9, 0x5a, 0x6, 0x42, 0x2c, 0x36},
{0xce, 0x29, 0x35, 0x43, 0x4e, 0xfe, 0x98, 0x3d, 0x53, 0x3a, 0xf9, 0x74, 0x73, 0x9a, 0x4b, 0xa7, 0xd0, 0xf5, 0x1f, 0x59, 0x6f, 0x4e, 0x81, 0x86, 0xe, 0x9d, 0xad, 0x81, 0xaf, 0xd8, 0x5a, 0x9f},
{0xa7, 0x5, 0x6, 0x67, 0xee, 0x34, 0x62, 0x6a, 0x8b, 0xb, 0x28, 0xbe, 0x6e, 0xb9, 0x17, 0x27, 0x47, 0x74, 0x7, 0x26, 0xc6, 0x80, 0x10, 0x3f, 0xe0, 0xa0, 0x7e, 0x6f, 0xc6, 0x7e, 0x48, 0x7b},
{0xd, 0x55, 0xa, 0xa5, 0x4a, 0xf8, 0xa4, 0xc0, 0x91, 0xe3, 0xe7, 0x9f, 0x97, 0x8e, 0xf1, 0x9e, 0x86, 0x76, 0x72, 0x81, 0x50, 0x60, 0x8d, 0xd4, 0x7e, 0x9e, 0x5a, 0x41, 0xf3, 0xe5, 0xb0, 0x62},
{0xfc, 0x9f, 0x1f, 0xec, 0x40, 0x54, 0x20, 0x7a, 0xe3, 0xe4, 0x1a, 0x0, 0xce, 0xf4, 0xc9, 0x84, 0x4f, 0xd7, 0x94, 0xf5, 0x9d, 0xfa, 0x95, 0xd8, 0x55, 0x2e, 0x7e, 0x11, 0x24, 0xc3, 0x54, 0xa5},
{0x5b, 0xdf, 0x72, 0x28, 0xbd, 0xfe, 0x6e, 0x28, 0x78, 0xf5, 0x7f, 0xe2, 0xf, 0xa5, 0xc4, 0xb2, 0x5, 0x89, 0x7c, 0xef, 0xee, 0x49, 0xd3, 0x2e, 0x44, 0x7e, 0x93, 0x85, 0xeb, 0x28, 0x59, 0x7f},
{0x70, 0x5f, 0x69, 0x37, 0xb3, 0x24, 0x31, 0x4a, 0x5e, 0x86, 0x28, 0xf1, 0x1d, 0xd6, 0xe4, 0x65, 0xc7, 0x1b, 0x77, 0x4, 0x51, 0xb9, 0x20, 0xe7, 0x74, 0xfe, 0x43, 0xe8, 0x23, 0xd4, 0x87, 0x8a},
{0x7d, 0x29, 0xe8, 0xa3, 0x92, 0x76, 0x94, 0xf2, 0xdd, 0xcb, 0x7a, 0x9, 0x9b, 0x30, 0xd9, 0xc1, 0x1d, 0x1b, 0x30, 0xfb, 0x5b, 0xdc, 0x1b, 0xe0, 0xda, 0x24, 0x49, 0x4f, 0xf2, 0x9c, 0x82, 0xbf},
{0xa4, 0xe7, 0xba, 0x31, 0xb4, 0x70, 0xbf, 0xff, 0xd, 0x32, 0x44, 0x5, 0xde, 0xf8, 0xbc, 0x48, 0x3b, 0xae, 0xfc, 0x32, 0x53, 0xbb, 0xd3, 0x39, 0x45, 0x9f, 0xc3, 0xc1, 0xe0, 0x29, 0x8b, 0xa0},
{0xe5, 0xc9, 0x5, 0xfd, 0xf7, 0xae, 0x9, 0xf, 0x94, 0x70, 0x34, 0x12, 0x42, 0x90, 0xf1, 0x34, 0xa2, 0x71, 0xb7, 0x1, 0xe3, 0x44, 0xed, 0x95, 0xe9, 0x3b, 0x8e, 0x36, 0x4f, 0x2f, 0x98, 0x4a},
{0x88, 0x40, 0x1d, 0x63, 0xa0, 0x6c, 0xf6, 0x15, 0x47, 0xc1, 0x44, 0x4b, 0x87, 0x52, 0xaf, 0xff, 0x7e, 0xbb, 0x4a, 0xf1, 0xe2, 0xa, 0xc6, 0x30, 0x46, 0x70, 0xb6, 0xc5, 0xcc, 0x6e, 0x8c, 0xe6},
{0xa4, 0xd5, 0xa4, 0x56, 0xbd, 0x4f, 0xca, 0x0, 0xda, 0x9d, 0x84, 0x4b, 0xc8, 0x3e, 0x18, 0xae, 0x73, 0x57, 0xce, 0x45, 0x30, 0x64, 0xd1, 0xad, 0xe8, 0xa6, 0xce, 0x68, 0x14, 0x5c, 0x25, 0x67},
{0xa3, 0xda, 0x8c, 0xf2, 0xcb, 0xe, 0xe1, 0x16, 0x33, 0xe9, 0x6, 0x58, 0x9a, 0x94, 0x99, 0x9a, 0x1f, 0x60, 0xb2, 0x20, 0xc2, 0x6f, 0x84, 0x7b, 0xd1, 0xce, 0xac, 0x7f, 0xa0, 0xd1, 0x85, 0x18},
{0x32, 0x59, 0x5b, 0xa1, 0x8d, 0xdd, 0x19, 0xd3, 0x50, 0x9a, 0x1c, 0xc0, 0xaa, 0xa5, 0xb4, 0x46, 0x9f, 0x3d, 0x63, 0x67, 0xe4, 0x4, 0x6b, 0xba, 0xf6, 0xca, 0x19, 0xab, 0xb, 0x56, 0xee, 0x7e},
{0x1f, 0xb1, 0x79, 0xea, 0xa9, 0x28, 0x21, 0x74, 0xe9, 0xbd, 0xf7, 0x35, 0x3b, 0x36, 0x51, 0xee, 0x1d, 0x57, 0xac, 0x5a, 0x75, 0x50, 0xd3, 0x76, 0x3a, 0x46, 0xc2, 0xfe, 0xa3, 0x7d, 0x70, 0x1},
{0xf7, 0x35, 0xc1, 0xaf, 0x98, 0xa4, 0xd8, 0x42, 0x78, 0xed, 0xec, 0x20, 0x9e, 0x6b, 0x67, 0x79, 0x41, 0x83, 0x63, 0x15, 0xea, 0x3a, 0xdb, 0xa8, 0xfa, 0xc3, 0x3b, 0x4d, 0x32, 0x83, 0x2c, 0x83},
{0xa7, 0x40, 0x3b, 0x1f, 0x1c, 0x27, 0x47, 0xf3, 0x59, 0x40, 0xf0, 0x34, 0xb7, 0x2d, 0x76, 0x9a, 0xe7, 0x3e, 0x4e, 0x6c, 0xd2, 0x21, 0x4f, 0xfd, 0xb8, 0xfd, 0x8d, 0x39, 0xdc, 0x57, 0x59, 0xef},
{0x8d, 0x9b, 0xc, 0x49, 0x2b, 0x49, 0xeb, 0xda, 0x5b, 0xa2, 0xd7, 0x49, 0x68, 0xf3, 0x70, 0xd, 0x7d, 0x3b, 0xae, 0xd0, 0x7a, 0x8d, 0x55, 0x84, 0xf5, 0xa5, 0xe9, 0xf0, 0xe4, 0xf8, 0x8e, 0x65},
{0xa0, 0xb8, 0xa2, 0xf4, 0x36, 0x10, 0x3b, 0x53, 0xc, 0xa8, 0x7, 0x9e, 0x75, 0x3e, 0xec, 0x5a, 0x91, 0x68, 0x94, 0x92, 0x56, 0xe8, 0x88, 0x4f, 0x5b, 0xb0, 0x5c, 0x55, 0xf8, 0xba, 0xbc, 0x4c},
{0xe3, 0xbb, 0x3b, 0x99, 0xf3, 0x87, 0x94, 0x7b, 0x75, 0xda, 0xf4, 0xd6, 0x72, 0x6b, 0x1c, 0x5d, 0x64, 0xae, 0xac, 0x28, 0xdc, 0x34, 0xb3, 0x6d, 0x6c, 0x34, 0xa5, 0x50, 0xb8, 0x28, 0xdb, 0x71},
{0xf8, 0x61, 0xe2, 0xf2, 0x10, 0x8d, 0x51, 0x2a, 0xe3, 0xdb, 0x64, 0x33, 0x59, 0xdd, 0x75, 0xfc, 0x1c, 0xac, 0xbc, 0xf1, 0x43, 0xce, 0x3f, 0xa2, 0x67, 0xbb, 0xd1, 0x3c, 0x2, 0xe8, 0x43, 0xb0},
{0x33, 0xa, 0x5b, 0xca, 0x88, 0x29, 0xa1, 0x75, 0x7f, 0x34, 0x19, 0x4d, 0xb4, 0x16, 0x53, 0x5c, 0x92, 0x3b, 0x94, 0xc3, 0xe, 0x79, 0x4d, 0x1e, 0x79, 0x74, 0x75, 0xd7, 0xb6, 0xee, 0xaf, 0x3f},
{0xea, 0xa8, 0xd4, 0xf7, 0xbe, 0x1a, 0x39, 0x21, 0x5c, 0xf4, 0x7e, 0x9, 0x4c, 0x23, 0x27, 0x51, 0x26, 0xa3, 0x24, 0x53, 0xba, 0x32, 0x3c, 0xd2, 0x44, 0xa3, 0x17, 0x4a, 0x6d, 0xa6, 0xd5, 0xad},
{0xb5, 0x1d, 0x3e, 0xa6, 0xaf, 0xf2, 0xc9, 0x8, 0x83, 0x59, 0x3d, 0x98, 0x91, 0x6b, 0x3c, 0x56, 0x4c, 0xf8, 0x7c, 0xa1, 0x72, 0x86, 0x60, 0x4d, 0x46, 0xe2, 0x3e, 0xcc, 0x8, 0x6e, 0xc7, 0xf6},
{0x2f, 0x98, 0x33, 0xb3, 0xb1, 0xbc, 0x76, 0x5e, 0x2b, 0xd6, 0x66, 0xa5, 0xef, 0xc4, 0xe6, 0x2a, 0x6, 0xf4, 0xb6, 0xe8, 0xbe, 0xc1, 0xd4, 0x36, 0x74, 0xee, 0x82, 0x15, 0xbc, 0xef, 0x21, 0x63},
{0xfd, 0xc1, 0x4e, 0xd, 0xf4, 0x53, 0xc9, 0x69, 0xa7, 0x7d, 0x5a, 0xc4, 0x6, 0x58, 0x58, 0x26, 0x7e, 0xc1, 0x14, 0x16, 0x6, 0xe0, 0xfa, 0x16, 0x7e, 0x90, 0xaf, 0x3d, 0x28, 0x63, 0x9d, 0x3f},
{0xd2, 0xc9, 0xf2, 0xe3, 0x0, 0x9b, 0xd2, 0xc, 0x5f, 0xaa, 0xce, 0x30, 0xb7, 0xd4, 0xc, 0x30, 0x74, 0x2a, 0x51, 0x16, 0xf2, 0xe0, 0x32, 0x98, 0xd, 0xeb, 0x30, 0xd8, 0xe3, 0xce, 0xf8, 0x9a},
{0x4b, 0xc5, 0x9e, 0x7b, 0xb5, 0xf1, 0x79, 0x92, 0xff, 0x51, 0xe6, 0x6e, 0x4, 0x86, 0x68, 0xd3, 0x9b, 0x23, 0x4d, 0x57, 0xe6, 0x96, 0x67, 0x31, 0xcc, 0xe6, 0xa6, 0xf3, 0x17, 0xa, 0x75, 0x5},
{0xb1, 0x76, 0x81, 0xd9, 0x13, 0x32, 0x6c, 0xce, 0x3c, 0x17, 0x52, 0x84, 0xf8, 0x5, 0xa2, 0x62, 0xf4, 0x2b, 0xcb, 0xb3, 0x78, 0x47, 0x15, 0x47, 0xff, 0x46, 0x54, 0x82, 0x23, 0x93, 0x6a, 0x48},
{0x38, 0xdf, 0x58, 0x7, 0x4e, 0x5e, 0x65, 0x65, 0xf2, 0xfc, 0x7c, 0x89, 0xfc, 0x86, 0x50, 0x8e, 0x31, 0x70, 0x2e, 0x44, 0xd0, 0xb, 0xca, 0x86, 0xf0, 0x40, 0x9, 0xa2, 0x30, 0x78, 0x47, 0x4e},
{0x65, 0xa0, 0xee, 0x39, 0xd1, 0xf7, 0x38, 0x83, 0xf7, 0x5e, 0xe9, 0x37, 0xe4, 0x2c, 0x3a, 0xbd, 0x21, 0x97, 0xb2, 0x26, 0x1, 0x13, 0xf8, 0x6f, 0xa3, 0x44, 0xed, 0xd1, 0xef, 0x9f, 0xde, 0xe7},
{0x8b, 0xa0, 0xdf, 0x15, 0x76, 0x25, 0x92, 0xd9, 0x3c, 0x85, 0xf7, 0xf6, 0x12, 0xdc, 0x42, 0xbe, 0xd8, 0xa7, 0xec, 0x7c, 0xab, 0x27, 0xb0, 0x7e, 0x53, 0x8d, 0x7d, 0xda, 0xaa, 0x3e, 0xa8, 0xde},
{0xaa, 0x25, 0xce, 0x93, 0xbd, 0x2, 0x69, 0xd8, 0x5a, 0xf6, 0x43, 0xfd, 0x1a, 0x73, 0x8, 0xf9, 0xc0, 0x5f, 0xef, 0xda, 0x17, 0x4a, 0x19, 0xa5, 0x97, 0x4d, 0x66, 0x33, 0x4c, 0xfd, 0x21, 0x6a},
{0x35, 0xb4, 0x98, 0x31, 0xdb, 0x41, 0x15, 0x70, 0xea, 0x1e, 0xf, 0xbb, 0xed, 0xcd, 0x54, 0x9b, 0x9a, 0xd0, 0x63, 0xa1, 0x51, 0x97, 0x40, 0x72, 0xf6, 0x75, 0x9d, 0xbf, 0x91, 0x47, 0x6f, 0xe2}
};
#define JH_SWAP1(x) (x) = ((((x) & 0x5555555555555555ULL) << 1) | (((x) & 0xaaaaaaaaaaaaaaaaULL) >> 1));
#define JH_SWAP2(x) (x) = ((((x) & 0x3333333333333333ULL) << 2) | (((x) & 0xccccccccccccccccULL) >> 2));
#define JH_SWAP4(x) (x) = ((((x) & 0x0f0f0f0f0f0f0f0fULL) << 4) | (((x) & 0xf0f0f0f0f0f0f0f0ULL) >> 4));
#define JH_SWAP8(x) (x) = ((((x) & 0x00ff00ff00ff00ffULL) << 8) | (((x) & 0xff00ff00ff00ff00ULL) >> 8));
#define JH_SWAP16(x) (x) = ((((x) & 0x0000ffff0000ffffULL) << 16) | (((x) & 0xffff0000ffff0000ULL) >> 16));
#define JH_SWAP32(x) (x) = (((x) << 32) | ((x) >> 32));
#define JH_L(m0,m1,m2,m3,m4,m5,m6,m7) \
(m4) ^= (m1); \
(m5) ^= (m2); \
(m6) ^= (m0) ^ (m3); \
(m7) ^= (m0); \
(m0) ^= (m5); \
(m1) ^= (m6); \
(m2) ^= (m4) ^ (m7); \
(m3) ^= (m4);
#define JH_SS(m0,m1,m2,m3,m4,m5,m6,m7,cc0,cc1) \
m3 = ~(m3); \
m7 = ~(m7); \
m0 ^= ((~(m2)) & (cc0)); \
m4 ^= ((~(m6)) & (cc1)); \
temp0 = (cc0) ^ ((m0) & (m1));\
temp1 = (cc1) ^ ((m4) & (m5));\
m0 ^= ((m2) & (m3)); \
m4 ^= ((m6) & (m7)); \
m3 ^= ((~(m1)) & (m2)); \
m7 ^= ((~(m5)) & (m6)); \
m1 ^= ((m0) & (m2)); \
m5 ^= ((m4) & (m6)); \
m2 ^= ((m0) & (~(m3))); \
m6 ^= ((m4) & (~(m7))); \
m0 ^= ((m1) | (m3)); \
m4 ^= ((m5) | (m7)); \
m3 ^= ((m1) & (m2)); \
m7 ^= ((m5) & (m6)); \
m1 ^= (temp0 & (m0)); \
m5 ^= (temp1 & (m4)); \
m2 ^= temp0; \
m6 ^= temp1;
__device__ void cn_jh_E8(jhHashState *state)
{
uint64_t i,roundnumber,temp0,temp1;
for (roundnumber = 0; roundnumber < 42; roundnumber = roundnumber+7)
{
for (i = 0; i < 2; i++)
{
JH_SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64_t *)d_E8_rc[roundnumber+0])[i],((uint64_t *)d_E8_rc[roundnumber+0])[i+2] );
JH_L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
JH_SWAP1(state->x[1][i]); JH_SWAP1(state->x[3][i]); JH_SWAP1(state->x[5][i]); JH_SWAP1(state->x[7][i]);
}
for (i = 0; i < 2; i++)
{
JH_SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64_t *)d_E8_rc[roundnumber+1])[i],((uint64_t *)d_E8_rc[roundnumber+1])[i+2] );
JH_L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
JH_SWAP2(state->x[1][i]); JH_SWAP2(state->x[3][i]); JH_SWAP2(state->x[5][i]); JH_SWAP2(state->x[7][i]);
}
for (i = 0; i < 2; i++)
{
JH_SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64_t *)d_E8_rc[roundnumber+2])[i],((uint64_t *)d_E8_rc[roundnumber+2])[i+2] );
JH_L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
JH_SWAP4(state->x[1][i]); JH_SWAP4(state->x[3][i]); JH_SWAP4(state->x[5][i]); JH_SWAP4(state->x[7][i]);
}
for (i = 0; i < 2; i++)
{
JH_SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64_t *)d_E8_rc[roundnumber+3])[i],((uint64_t *)d_E8_rc[roundnumber+3])[i+2] );
JH_L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
JH_SWAP8(state->x[1][i]); JH_SWAP8(state->x[3][i]); JH_SWAP8(state->x[5][i]); JH_SWAP8(state->x[7][i]);
}
for (i = 0; i < 2; i++)
{
JH_SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64_t *)d_E8_rc[roundnumber+4])[i],((uint64_t *)d_E8_rc[roundnumber+4])[i+2] );
JH_L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
JH_SWAP16(state->x[1][i]); JH_SWAP16(state->x[3][i]); JH_SWAP16(state->x[5][i]); JH_SWAP16(state->x[7][i]);
}
for (i = 0; i < 2; i++)
{
JH_SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64_t *)d_E8_rc[roundnumber+5])[i],((uint64_t *)d_E8_rc[roundnumber+5])[i+2] );
JH_L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
JH_SWAP32(state->x[1][i]); JH_SWAP32(state->x[3][i]); JH_SWAP32(state->x[5][i]); JH_SWAP32(state->x[7][i]);
}
for (i = 0; i < 2; i++)
{
JH_SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64_t *)d_E8_rc[roundnumber+6])[i],((uint64_t *)d_E8_rc[roundnumber+6])[i+2] );
JH_L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
}
for (i = 1; i < 8; i = i+2)
{
temp0 = state->x[i][0];
state->x[i][0] = state->x[i][1];
state->x[i][1] = temp0;
}
}
}
__device__ void cn_jh_F8(jhHashState *state)
{
uint64_t i;
for (i = 0; i < 8; i++)
state->x[i >> 1][i & 1] ^= ((uint64_t *)state->buffer)[i];
cn_jh_E8(state);
for (i = 0; i < 8; i++)
state->x[(8+i) >> 1][(8+i) & 1] ^= ((uint64_t *)state->buffer)[i];
}
__device__ void cn_jh_update(jhHashState * __restrict__ state, const BitSequence * __restrict__ data, DataLength databitlen)
{
DataLength index;
state->databitlen += databitlen;
index = 0;
if ( (state->datasize_in_buffer > 0 ) && (( state->datasize_in_buffer + databitlen) < 512) )
{
if ( (databitlen & 7) == 0 )
memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3));
else
memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3)+1);
state->datasize_in_buffer += databitlen;
databitlen = 0;
}
if ( (state->datasize_in_buffer > 0 ) && (( state->datasize_in_buffer + databitlen) >= 512) )
{
memcpy( state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3) );
index = 64-(state->datasize_in_buffer >> 3);
databitlen = databitlen - (512 - state->datasize_in_buffer);
cn_jh_F8(state);
state->datasize_in_buffer = 0;
}
for ( ; databitlen >= 512; index = index+64, databitlen = databitlen - 512)
{
memcpy(state->buffer, data+index, 64);
cn_jh_F8(state);
}
if ( databitlen > 0)
{
if ((databitlen & 7) == 0)
memcpy(state->buffer, data+index, (databitlen & 0x1ff) >> 3);
else
memcpy(state->buffer, data+index, ((databitlen & 0x1ff) >> 3)+1);
state->datasize_in_buffer = databitlen;
}
}
/*pad the message, process the padded block(s), truncate the hash value H to obtain the message digest*/
__device__ void cn_jh_final(jhHashState * __restrict__ state, BitSequence * __restrict__ hashval)
{
unsigned int i;
//uint32_t *bufptr = (uint32_t *)state->buffer;
if ( (state->databitlen & 0x1ff) == 0 )
{
/*pad the message when databitlen is multiple of 512 bits, then process the padded block*/
memset(state->buffer, 0, 64);
//for( i = 0; i < 16; i++ ) *(bufptr+i) = 0x00000000;
state->buffer[0] = 0x80;
state->buffer[63] = state->databitlen & 0xff;
state->buffer[62] = (state->databitlen >> 8) & 0xff;
state->buffer[61] = (state->databitlen >> 16) & 0xff;
state->buffer[60] = (state->databitlen >> 24) & 0xff;
state->buffer[59] = (state->databitlen >> 32) & 0xff;
state->buffer[58] = (state->databitlen >> 40) & 0xff;
state->buffer[57] = (state->databitlen >> 48) & 0xff;
state->buffer[56] = (state->databitlen >> 56) & 0xff;
cn_jh_F8(state);
}
else
{
/*set the rest of the bytes in the buffer to 0*/
if ( (state->datasize_in_buffer & 7) == 0)
{
for (i = (state->databitlen & 0x1ff) >> 3; i < 64; i++)
state->buffer[i] = 0;
}
else
{
for (i = ((state->databitlen & 0x1ff) >> 3)+1; i < 64; i++)
state->buffer[i] = 0;
}
/*pad and process the partial block when databitlen is not multiple of 512 bits, then hash the padded blocks*/
state->buffer[((state->databitlen & 0x1ff) >> 3)] |= 1 << (7- (state->databitlen & 7));
cn_jh_F8(state);
memset(state->buffer, 0, 64);
//for( i = 0; i < 16; i++ ) *(bufptr+i) = 0x00000000;
state->buffer[63] = state->databitlen & 0xff;
state->buffer[62] = (state->databitlen >> 8) & 0xff;
state->buffer[61] = (state->databitlen >> 16) & 0xff;
state->buffer[60] = (state->databitlen >> 24) & 0xff;
state->buffer[59] = (state->databitlen >> 32) & 0xff;
state->buffer[58] = (state->databitlen >> 40) & 0xff;
state->buffer[57] = (state->databitlen >> 48) & 0xff;
state->buffer[56] = (state->databitlen >> 56) & 0xff;
cn_jh_F8(state);
}
memcpy(hashval,(unsigned char*)state->x+64+32,32);
}
__device__ void cn_jh_init(jhHashState *state, int hashbitlen)
{
state->databitlen = 0;
state->datasize_in_buffer = 0;
state->hashbitlen = hashbitlen;
memcpy(state->x, d_JH256_H0, 128);
}
__device__ void cn_jh(const BitSequence * __restrict__ data, DataLength len, BitSequence * __restrict__ hashval)
{
int hashbitlen = 256;
DataLength databitlen = len << 3;
jhHashState state;
cn_jh_init(&state, hashbitlen);
cn_jh_update(&state, data, databitlen);
cn_jh_final(&state, hashval);
}
@@ -0,0 +1,197 @@
#if __CUDA_ARCH__ >= 350
__forceinline__ __device__ uint64_t cuda_rotl64(const uint64_t value, const int offset)
{
uint2 result;
if(offset >= 32)
{
asm("shf.l.wrap.b32 %0, %1, %2, %3;" : "=r"(result.x) : "r"(__double2loint(__longlong_as_double(value))), "r"(__double2hiint(__longlong_as_double(value))), "r"(offset));
asm("shf.l.wrap.b32 %0, %1, %2, %3;" : "=r"(result.y) : "r"(__double2hiint(__longlong_as_double(value))), "r"(__double2loint(__longlong_as_double(value))), "r"(offset));
}
else
{
asm("shf.l.wrap.b32 %0, %1, %2, %3;" : "=r"(result.x) : "r"(__double2hiint(__longlong_as_double(value))), "r"(__double2loint(__longlong_as_double(value))), "r"(offset));
asm("shf.l.wrap.b32 %0, %1, %2, %3;" : "=r"(result.y) : "r"(__double2loint(__longlong_as_double(value))), "r"(__double2hiint(__longlong_as_double(value))), "r"(offset));
}
return __double_as_longlong(__hiloint2double(result.y, result.x));
}
#define rotl64_1(x, y) (cuda_rotl64((x), (y)))
#else
#define rotl64_1(x, y) ((x) << (y) | ((x) >> (64 - (y))))
#endif
#define rotl64_2(x, y) rotl64_1(((x) >> 32) | ((x) << 32), (y))
#define bitselect(a, b, c) ((a) ^ ((c) & ((b) ^ (a))))
__device__ __forceinline__ void cn_keccakf2(uint64_t *s)
{
uint8_t i;
for(i = 0; i < 24; ++i)
{
uint64_t bc[5], tmpxor[5], tmp1, tmp2;
tmpxor[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];
tmpxor[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];
tmpxor[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];
tmpxor[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];
tmpxor[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];
bc[0] = tmpxor[0] ^ rotl64_1(tmpxor[2], 1);
bc[1] = tmpxor[1] ^ rotl64_1(tmpxor[3], 1);
bc[2] = tmpxor[2] ^ rotl64_1(tmpxor[4], 1);
bc[3] = tmpxor[3] ^ rotl64_1(tmpxor[0], 1);
bc[4] = tmpxor[4] ^ rotl64_1(tmpxor[1], 1);
tmp1 = s[1] ^ bc[0];
s[0] ^= bc[4];
s[1] = rotl64_2(s[6] ^ bc[0], 12);
s[6] = rotl64_1(s[9] ^ bc[3], 20);
s[9] = rotl64_2(s[22] ^ bc[1], 29);
s[22] = rotl64_2(s[14] ^ bc[3], 7);
s[14] = rotl64_1(s[20] ^ bc[4], 18);
s[20] = rotl64_2(s[2] ^ bc[1], 30);
s[2] = rotl64_2(s[12] ^ bc[1], 11);
s[12] = rotl64_1(s[13] ^ bc[2], 25);
s[13] = rotl64_1(s[19] ^ bc[3], 8);
s[19] = rotl64_2(s[23] ^ bc[2], 24);
s[23] = rotl64_2(s[15] ^ bc[4], 9);
s[15] = rotl64_1(s[4] ^ bc[3], 27);
s[4] = rotl64_1(s[24] ^ bc[3], 14);
s[24] = rotl64_1(s[21] ^ bc[0], 2);
s[21] = rotl64_2(s[8] ^ bc[2], 23);
s[8] = rotl64_2(s[16] ^ bc[0], 13);
s[16] = rotl64_2(s[5] ^ bc[4], 4);
s[5] = rotl64_1(s[3] ^ bc[2], 28);
s[3] = rotl64_1(s[18] ^ bc[2], 21);
s[18] = rotl64_1(s[17] ^ bc[1], 15);
s[17] = rotl64_1(s[11] ^ bc[0], 10);
s[11] = rotl64_1(s[7] ^ bc[1], 6);
s[7] = rotl64_1(s[10] ^ bc[4], 3);
s[10] = rotl64_1(tmp1, 1);
tmp1 = s[0]; tmp2 = s[1]; s[0] = bitselect(s[0] ^ s[2], s[0], s[1]); s[1] = bitselect(s[1] ^ s[3], s[1], s[2]); s[2] = bitselect(s[2] ^ s[4], s[2], s[3]); s[3] = bitselect(s[3] ^ tmp1, s[3], s[4]); s[4] = bitselect(s[4] ^ tmp2, s[4], tmp1);
tmp1 = s[5]; tmp2 = s[6]; s[5] = bitselect(s[5] ^ s[7], s[5], s[6]); s[6] = bitselect(s[6] ^ s[8], s[6], s[7]); s[7] = bitselect(s[7] ^ s[9], s[7], s[8]); s[8] = bitselect(s[8] ^ tmp1, s[8], s[9]); s[9] = bitselect(s[9] ^ tmp2, s[9], tmp1);
tmp1 = s[10]; tmp2 = s[11]; s[10] = bitselect(s[10] ^ s[12], s[10], s[11]); s[11] = bitselect(s[11] ^ s[13], s[11], s[12]); s[12] = bitselect(s[12] ^ s[14], s[12], s[13]); s[13] = bitselect(s[13] ^ tmp1, s[13], s[14]); s[14] = bitselect(s[14] ^ tmp2, s[14], tmp1);
tmp1 = s[15]; tmp2 = s[16]; s[15] = bitselect(s[15] ^ s[17], s[15], s[16]); s[16] = bitselect(s[16] ^ s[18], s[16], s[17]); s[17] = bitselect(s[17] ^ s[19], s[17], s[18]); s[18] = bitselect(s[18] ^ tmp1, s[18], s[19]); s[19] = bitselect(s[19] ^ tmp2, s[19], tmp1);
tmp1 = s[20]; tmp2 = s[21]; s[20] = bitselect(s[20] ^ s[22], s[20], s[21]); s[21] = bitselect(s[21] ^ s[23], s[21], s[22]); s[22] = bitselect(s[22] ^ s[24], s[22], s[23]); s[23] = bitselect(s[23] ^ tmp1, s[23], s[24]); s[24] = bitselect(s[24] ^ tmp2, s[24], tmp1);
s[0] ^= keccakf_rndc[i];
}
}
__device__ __forceinline__ void cn_keccakf(uint64_t *s)
{
uint64_t bc[5], tmpxor[5], tmp1, tmp2;
tmpxor[0] = s[0] ^ s[5];
tmpxor[1] = s[1] ^ s[6] ^ 0x8000000000000000ULL;
tmpxor[2] = s[2] ^ s[7];
tmpxor[3] = s[3] ^ s[8];
tmpxor[4] = s[4] ^ s[9];
bc[0] = tmpxor[0] ^ rotl64_1(tmpxor[2], 1);
bc[1] = tmpxor[1] ^ rotl64_1(tmpxor[3], 1);
bc[2] = tmpxor[2] ^ rotl64_1(tmpxor[4], 1);
bc[3] = tmpxor[3] ^ rotl64_1(tmpxor[0], 1);
bc[4] = tmpxor[4] ^ rotl64_1(tmpxor[1], 1);
tmp1 = s[1] ^ bc[0];
s[0] ^= bc[4];
s[1] = rotl64_2(s[6] ^ bc[0], 12);
s[6] = rotl64_1(s[9] ^ bc[3], 20);
s[9] = rotl64_2(bc[1], 29);
s[22] = rotl64_2(bc[3], 7);
s[14] = rotl64_1(bc[4], 18);
s[20] = rotl64_2(s[2] ^ bc[1], 30);
s[2] = rotl64_2(bc[1], 11);
s[12] = rotl64_1(bc[2], 25);
s[13] = rotl64_1(bc[3], 8);
s[19] = rotl64_2(bc[2], 24);
s[23] = rotl64_2(bc[4], 9);
s[15] = rotl64_1(s[4] ^ bc[3], 27);
s[4] = rotl64_1(bc[3], 14);
s[24] = rotl64_1(bc[0], 2);
s[21] = rotl64_2(s[8] ^ bc[2], 23);
s[8] = rotl64_2(0x8000000000000000ULL ^ bc[0], 13);
s[16] = rotl64_2(s[5] ^ bc[4], 4);
s[5] = rotl64_1(s[3] ^ bc[2], 28);
s[3] = rotl64_1(bc[2], 21);
s[18] = rotl64_1(bc[1], 15);
s[17] = rotl64_1(bc[0], 10);
s[11] = rotl64_1(s[7] ^ bc[1], 6);
s[7] = rotl64_1(bc[4], 3);
s[10] = rotl64_1(tmp1, 1);
tmp1 = s[0]; tmp2 = s[1]; s[0] = bitselect(s[0] ^ s[2], s[0], s[1]); s[1] = bitselect(s[1] ^ s[3], s[1], s[2]); s[2] = bitselect(s[2] ^ s[4], s[2], s[3]); s[3] = bitselect(s[3] ^ tmp1, s[3], s[4]); s[4] = bitselect(s[4] ^ tmp2, s[4], tmp1);
tmp1 = s[5]; tmp2 = s[6]; s[5] = bitselect(s[5] ^ s[7], s[5], s[6]); s[6] = bitselect(s[6] ^ s[8], s[6], s[7]); s[7] = bitselect(s[7] ^ s[9], s[7], s[8]); s[8] = bitselect(s[8] ^ tmp1, s[8], s[9]); s[9] = bitselect(s[9] ^ tmp2, s[9], tmp1);
tmp1 = s[10]; tmp2 = s[11]; s[10] = bitselect(s[10] ^ s[12], s[10], s[11]); s[11] = bitselect(s[11] ^ s[13], s[11], s[12]); s[12] = bitselect(s[12] ^ s[14], s[12], s[13]); s[13] = bitselect(s[13] ^ tmp1, s[13], s[14]); s[14] = bitselect(s[14] ^ tmp2, s[14], tmp1);
tmp1 = s[15]; tmp2 = s[16]; s[15] = bitselect(s[15] ^ s[17], s[15], s[16]); s[16] = bitselect(s[16] ^ s[18], s[16], s[17]); s[17] = bitselect(s[17] ^ s[19], s[17], s[18]); s[18] = bitselect(s[18] ^ tmp1, s[18], s[19]); s[19] = bitselect(s[19] ^ tmp2, s[19], tmp1);
tmp1 = s[20]; tmp2 = s[21]; s[20] = bitselect(s[20] ^ s[22], s[20], s[21]); s[21] = bitselect(s[21] ^ s[23], s[21], s[22]); s[22] = bitselect(s[22] ^ s[24], s[22], s[23]); s[23] = bitselect(s[23] ^ tmp1, s[23], s[24]); s[24] = bitselect(s[24] ^ tmp2, s[24], tmp1);
s[0] ^= 0x0000000000000001;
for(int i = 1; i < 24; ++i)
{
tmpxor[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];
tmpxor[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];
tmpxor[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];
tmpxor[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];
tmpxor[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];
bc[0] = tmpxor[0] ^ rotl64_1(tmpxor[2], 1);
bc[1] = tmpxor[1] ^ rotl64_1(tmpxor[3], 1);
bc[2] = tmpxor[2] ^ rotl64_1(tmpxor[4], 1);
bc[3] = tmpxor[3] ^ rotl64_1(tmpxor[0], 1);
bc[4] = tmpxor[4] ^ rotl64_1(tmpxor[1], 1);
tmp1 = s[1] ^ bc[0];
s[0] ^= bc[4];
s[1] = rotl64_2(s[6] ^ bc[0], 12);
s[6] = rotl64_1(s[9] ^ bc[3], 20);
s[9] = rotl64_2(s[22] ^ bc[1], 29);
s[22] = rotl64_2(s[14] ^ bc[3], 7);
s[14] = rotl64_1(s[20] ^ bc[4], 18);
s[20] = rotl64_2(s[2] ^ bc[1], 30);
s[2] = rotl64_2(s[12] ^ bc[1], 11);
s[12] = rotl64_1(s[13] ^ bc[2], 25);
s[13] = rotl64_1(s[19] ^ bc[3], 8);
s[19] = rotl64_2(s[23] ^ bc[2], 24);
s[23] = rotl64_2(s[15] ^ bc[4], 9);
s[15] = rotl64_1(s[4] ^ bc[3], 27);
s[4] = rotl64_1(s[24] ^ bc[3], 14);
s[24] = rotl64_1(s[21] ^ bc[0], 2);
s[21] = rotl64_2(s[8] ^ bc[2], 23);
s[8] = rotl64_2(s[16] ^ bc[0], 13);
s[16] = rotl64_2(s[5] ^ bc[4], 4);
s[5] = rotl64_1(s[3] ^ bc[2], 28);
s[3] = rotl64_1(s[18] ^ bc[2], 21);
s[18] = rotl64_1(s[17] ^ bc[1], 15);
s[17] = rotl64_1(s[11] ^ bc[0], 10);
s[11] = rotl64_1(s[7] ^ bc[1], 6);
s[7] = rotl64_1(s[10] ^ bc[4], 3);
s[10] = rotl64_1(tmp1, 1);
tmp1 = s[0]; tmp2 = s[1]; s[0] = bitselect(s[0] ^ s[2], s[0], s[1]); s[1] = bitselect(s[1] ^ s[3], s[1], s[2]); s[2] = bitselect(s[2] ^ s[4], s[2], s[3]); s[3] = bitselect(s[3] ^ tmp1, s[3], s[4]); s[4] = bitselect(s[4] ^ tmp2, s[4], tmp1);
tmp1 = s[5]; tmp2 = s[6]; s[5] = bitselect(s[5] ^ s[7], s[5], s[6]); s[6] = bitselect(s[6] ^ s[8], s[6], s[7]); s[7] = bitselect(s[7] ^ s[9], s[7], s[8]); s[8] = bitselect(s[8] ^ tmp1, s[8], s[9]); s[9] = bitselect(s[9] ^ tmp2, s[9], tmp1);
tmp1 = s[10]; tmp2 = s[11]; s[10] = bitselect(s[10] ^ s[12], s[10], s[11]); s[11] = bitselect(s[11] ^ s[13], s[11], s[12]); s[12] = bitselect(s[12] ^ s[14], s[12], s[13]); s[13] = bitselect(s[13] ^ tmp1, s[13], s[14]); s[14] = bitselect(s[14] ^ tmp2, s[14], tmp1);
tmp1 = s[15]; tmp2 = s[16]; s[15] = bitselect(s[15] ^ s[17], s[15], s[16]); s[16] = bitselect(s[16] ^ s[18], s[16], s[17]); s[17] = bitselect(s[17] ^ s[19], s[17], s[18]); s[18] = bitselect(s[18] ^ tmp1, s[18], s[19]); s[19] = bitselect(s[19] ^ tmp2, s[19], tmp1);
tmp1 = s[20]; tmp2 = s[21]; s[20] = bitselect(s[20] ^ s[22], s[20], s[21]); s[21] = bitselect(s[21] ^ s[23], s[21], s[22]); s[22] = bitselect(s[22] ^ s[24], s[22], s[23]); s[23] = bitselect(s[23] ^ tmp1, s[23], s[24]); s[24] = bitselect(s[24] ^ tmp2, s[24], tmp1);
s[0] ^= keccakf_rndc[i];
}
}
__device__ __forceinline__ void cn_keccak(const uint8_t * __restrict__ in, uint32_t len, uint8_t * __restrict__ md)
{
uint64_t st[25];
MEMSET8(st + 8, 0x00, 25 - 8);
memcpy(st, in, len);
((uint8_t*)st)[len] = 0x01;
st[16] = 0x8000000000000000ULL;
cn_keccakf(st);
MEMCPY8(md, st, 25);
return;
}
@@ -0,0 +1,347 @@
#pragma once
typedef unsigned int uint_t; /* native unsigned integer */
#define SKEIN_MODIFIER_WORDS ( 2) /* number of modifier (tweak) words */
#define SKEIN_256_STATE_WORDS ( 4)
#define SKEIN_512_STATE_WORDS ( 8)
#define SKEIN1024_STATE_WORDS (16)
#define SKEIN_256_STATE_BYTES ( 8*SKEIN_256_STATE_WORDS)
#define SKEIN_512_STATE_BYTES ( 8*SKEIN_512_STATE_WORDS)
#define SKEIN1024_STATE_BYTES ( 8*SKEIN1024_STATE_WORDS)
#define SKEIN_256_STATE_BITS (64*SKEIN_256_STATE_WORDS)
#define SKEIN_512_STATE_BITS (64*SKEIN_512_STATE_WORDS)
#define SKEIN1024_STATE_BITS (64*SKEIN1024_STATE_WORDS)
#define SKEIN_256_BLOCK_BYTES ( 8*SKEIN_256_STATE_WORDS)
#define SKEIN_512_BLOCK_BYTES ( 8*SKEIN_512_STATE_WORDS)
#define SKEIN1024_BLOCK_BYTES ( 8*SKEIN1024_STATE_WORDS)
#define SKEIN_MK_64(hi32,lo32) ((lo32) + (((uint64_t) (hi32)) << 32))
#define SKEIN_KS_PARITY SKEIN_MK_64(0x1BD11BDA,0xA9FC1A22)
#define SKEIN_T1_BIT(BIT) ((BIT) - 64) /* offset 64 because it's the second word */
#define SKEIN_T1_POS_FIRST SKEIN_T1_BIT(126) /* bits 126 : first block flag */
#define SKEIN_T1_POS_BIT_PAD SKEIN_T1_BIT(119) /* bit 119 : partial final input byte */
#define SKEIN_T1_POS_FINAL SKEIN_T1_BIT(127) /* bit 127 : final block flag */
#define SKEIN_T1_POS_BLK_TYPE SKEIN_T1_BIT(120) /* bits 120..125: type field */
#define SKEIN_T1_FLAG_FIRST (((uint64_t) 1 ) << SKEIN_T1_POS_FIRST)
#define SKEIN_T1_FLAG_BIT_PAD (((uint64_t) 1 ) << SKEIN_T1_POS_BIT_PAD)
#define SKEIN_T1_FLAG_FINAL (((uint64_t) 1 ) << SKEIN_T1_POS_FINAL)
#define SKEIN_BLK_TYPE_MSG (48) /* message processing */
#define SKEIN_BLK_TYPE_OUT (63) /* output stage */
#define SKEIN_T1_BLK_TYPE(T) (((uint64_t) (SKEIN_BLK_TYPE_##T)) << SKEIN_T1_POS_BLK_TYPE)
#define SKEIN_T1_BLK_TYPE_MSG SKEIN_T1_BLK_TYPE(MSG) /* message processing */
#define SKEIN_T1_BLK_TYPE_OUT SKEIN_T1_BLK_TYPE(OUT) /* output stage */
#define SKEIN_T1_BLK_TYPE_OUT_FINAL (SKEIN_T1_BLK_TYPE_OUT | SKEIN_T1_FLAG_FINAL)
#define Skein_Set_Tweak(ctxPtr,TWK_NUM,tVal) {(ctxPtr)->h.T[TWK_NUM] = (tVal);}
#define Skein_Set_T0(ctxPtr,T0) Skein_Set_Tweak(ctxPtr,0,T0)
#define Skein_Set_T1(ctxPtr,T1) Skein_Set_Tweak(ctxPtr,1,T1)
#define Skein_Set_T0_T1(ctxPtr,T0,T1) { \
Skein_Set_T0(ctxPtr,(T0)); \
Skein_Set_T1(ctxPtr,(T1)); }
#define Skein_Start_New_Type(ctxPtr,BLK_TYPE) \
{ Skein_Set_T0_T1(ctxPtr,0,SKEIN_T1_FLAG_FIRST | SKEIN_T1_BLK_TYPE_##BLK_TYPE); (ctxPtr)->h.bCnt=0; }
#define Skein_Set_Bit_Pad_Flag(hdr) { (hdr).T[1] |= SKEIN_T1_FLAG_BIT_PAD; }
#define KW_TWK_BASE (0)
#define KW_KEY_BASE (3)
#define ks (kw + KW_KEY_BASE)
#define ts (kw + KW_TWK_BASE)
#define R512(p0,p1,p2,p3,p4,p5,p6,p7,R512ROT,rNum) \
X##p0 += X##p1; X##p1 = ROTL64(X##p1,R512ROT##_0); X##p1 ^= X##p0; \
X##p2 += X##p3; X##p3 = ROTL64(X##p3,R512ROT##_1); X##p3 ^= X##p2; \
X##p4 += X##p5; X##p5 = ROTL64(X##p5,R512ROT##_2); X##p5 ^= X##p4; \
X##p6 += X##p7; X##p7 = ROTL64(X##p7,R512ROT##_3); X##p7 ^= X##p6;
#define I512(R) \
X0 += ks[((R)+1) % 9]; \
X1 += ks[((R)+2) % 9]; \
X2 += ks[((R)+3) % 9]; \
X3 += ks[((R)+4) % 9]; \
X4 += ks[((R)+5) % 9]; \
X5 += ks[((R)+6) % 9] + ts[((R)+1) % 3]; \
X6 += ks[((R)+7) % 9] + ts[((R)+2) % 3]; \
X7 += ks[((R)+8) % 9] + (R)+1;
#define R512_8_rounds(R) \
R512(0,1,2,3,4,5,6,7,R_512_0,8*(R)+ 1); \
R512(2,1,4,7,6,5,0,3,R_512_1,8*(R)+ 2); \
R512(4,1,6,3,0,5,2,7,R_512_2,8*(R)+ 3); \
R512(6,1,0,7,2,5,4,3,R_512_3,8*(R)+ 4); \
I512(2*(R)); \
R512(0,1,2,3,4,5,6,7,R_512_4,8*(R)+ 5); \
R512(2,1,4,7,6,5,0,3,R_512_5,8*(R)+ 6); \
R512(4,1,6,3,0,5,2,7,R_512_6,8*(R)+ 7); \
R512(6,1,0,7,2,5,4,3,R_512_7,8*(R)+ 8); \
I512(2*(R)+1);
typedef struct
{
size_t hashBitLen;
size_t bCnt;
uint64_t T[SKEIN_MODIFIER_WORDS];
} Skein_Ctxt_Hdr_t;
typedef struct {
Skein_Ctxt_Hdr_t h;
uint64_t X[SKEIN_256_STATE_WORDS];
uint8_t b[SKEIN_256_BLOCK_BYTES];
} Skein_256_Ctxt_t;
typedef struct {
Skein_Ctxt_Hdr_t h;
uint64_t X[SKEIN_512_STATE_WORDS];
uint8_t b[SKEIN_512_BLOCK_BYTES];
} Skein_512_Ctxt_t;
typedef struct {
Skein_Ctxt_Hdr_t h;
uint64_t X[SKEIN1024_STATE_WORDS];
uint8_t b[SKEIN1024_BLOCK_BYTES];
} Skein1024_Ctxt_t;
typedef struct {
uint_t statebits;
union {
Skein_Ctxt_Hdr_t h;
Skein_256_Ctxt_t ctx_256;
Skein_512_Ctxt_t ctx_512;
Skein1024_Ctxt_t ctx1024;
} u;
} skeinHashState;
__device__ void cn_skein_init(skeinHashState *state, size_t hashBitLen)
{
const uint64_t SKEIN_512_IV_256[] =
{
SKEIN_MK_64(0xCCD044A1,0x2FDB3E13),
SKEIN_MK_64(0xE8359030,0x1A79A9EB),
SKEIN_MK_64(0x55AEA061,0x4F816E6F),
SKEIN_MK_64(0x2A2767A4,0xAE9B94DB),
SKEIN_MK_64(0xEC06025E,0x74DD7683),
SKEIN_MK_64(0xE7A436CD,0xC4746251),
SKEIN_MK_64(0xC36FBAF9,0x393AD185),
SKEIN_MK_64(0x3EEDBA18,0x33EDFC13)
};
Skein_512_Ctxt_t *ctx = &state->u.ctx_512;
ctx->h.hashBitLen = hashBitLen;
memcpy(ctx->X, SKEIN_512_IV_256, sizeof(ctx->X));
Skein_Start_New_Type(ctx, MSG);
}
__device__ void cn_skein512_processblock(Skein_512_Ctxt_t * __restrict__ ctx, const uint8_t * __restrict__ blkPtr, size_t blkCnt, size_t byteCntAdd)
{
enum {
R_512_0_0=46, R_512_0_1=36, R_512_0_2=19, R_512_0_3=37,
R_512_1_0=33, R_512_1_1=27, R_512_1_2=14, R_512_1_3=42,
R_512_2_0=17, R_512_2_1=49, R_512_2_2=36, R_512_2_3=39,
R_512_3_0=44, R_512_3_1= 9, R_512_3_2=54, R_512_3_3=56,
R_512_4_0=39, R_512_4_1=30, R_512_4_2=34, R_512_4_3=24,
R_512_5_0=13, R_512_5_1=50, R_512_5_2=10, R_512_5_3=17,
R_512_6_0=25, R_512_6_1=29, R_512_6_2=39, R_512_6_3=43,
R_512_7_0= 8, R_512_7_1=35, R_512_7_2=56, R_512_7_3=22
};
uint64_t X0,X1,X2,X3,X4,X5,X6,X7;
uint64_t w[SKEIN_512_STATE_WORDS];
uint64_t kw[SKEIN_512_STATE_WORDS+4];
ts[0] = ctx->h.T[0];
ts[1] = ctx->h.T[1];
do
{
ts[0] += byteCntAdd;
ks[0] = ctx->X[0];
ks[1] = ctx->X[1];
ks[2] = ctx->X[2];
ks[3] = ctx->X[3];
ks[4] = ctx->X[4];
ks[5] = ctx->X[5];
ks[6] = ctx->X[6];
ks[7] = ctx->X[7];
ks[8] = ks[0] ^ ks[1] ^ ks[2] ^ ks[3] ^
ks[4] ^ ks[5] ^ ks[6] ^ ks[7] ^ SKEIN_KS_PARITY;
ts[2] = ts[0] ^ ts[1];
memcpy(w, blkPtr, SKEIN_512_STATE_WORDS << 3);
X0 = w[0] + ks[0];
X1 = w[1] + ks[1];
X2 = w[2] + ks[2];
X3 = w[3] + ks[3];
X4 = w[4] + ks[4];
X5 = w[5] + ks[5] + ts[0];
X6 = w[6] + ks[6] + ts[1];
X7 = w[7] + ks[7];
blkPtr += SKEIN_512_BLOCK_BYTES;
R512_8_rounds( 0);
R512_8_rounds( 1);
R512_8_rounds( 2);
R512_8_rounds( 3);
R512_8_rounds( 4);
R512_8_rounds( 5);
R512_8_rounds( 6);
R512_8_rounds( 7);
R512_8_rounds( 8);
ctx->X[0] = X0 ^ w[0];
ctx->X[1] = X1 ^ w[1];
ctx->X[2] = X2 ^ w[2];
ctx->X[3] = X3 ^ w[3];
ctx->X[4] = X4 ^ w[4];
ctx->X[5] = X5 ^ w[5];
ctx->X[6] = X6 ^ w[6];
ctx->X[7] = X7 ^ w[7];
ts[1] &= ~SKEIN_T1_FLAG_FIRST;
}
while (--blkCnt);
ctx->h.T[0] = ts[0];
ctx->h.T[1] = ts[1];
}
__device__ void cn_skein_final(skeinHashState * __restrict__ state, uint8_t * __restrict__ hashVal)
{
size_t i,n,byteCnt;
uint64_t X[SKEIN_512_STATE_WORDS];
Skein_512_Ctxt_t *ctx = (Skein_512_Ctxt_t *)&state->u.ctx_512;
//size_t tmp;
//uint8_t *p8;
//uint64_t *p64;
ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;
if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES)
{
memset(&ctx->b[ctx->h.bCnt],0,SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
//p8 = &ctx->b[ctx->h.bCnt];
//tmp = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt;
//for( i = 0; i < tmp; i++ ) *(p8+i) = 0;
}
cn_skein512_processblock(ctx,ctx->b,1,ctx->h.bCnt);
byteCnt = (ctx->h.hashBitLen + 7) >> 3;
//uint8_t b[SKEIN_512_BLOCK_BYTES] == 64
memset(ctx->b,0,sizeof(ctx->b));
//p64 = (uint64_t *)ctx->b;
//for( i = 0; i < 8; i++ ) *(p64+i) = 0;
memcpy(X,ctx->X,sizeof(X));
for (i=0;i*SKEIN_512_BLOCK_BYTES < byteCnt;i++)
{
((uint64_t *)ctx->b)[0]= (uint64_t)i;
Skein_Start_New_Type(ctx,OUT_FINAL);
cn_skein512_processblock(ctx,ctx->b,1,sizeof(uint64_t));
n = byteCnt - i*SKEIN_512_BLOCK_BYTES;
if (n >= SKEIN_512_BLOCK_BYTES)
n = SKEIN_512_BLOCK_BYTES;
memcpy(hashVal+i*SKEIN_512_BLOCK_BYTES,ctx->X,n);
memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */
}
}
__device__ void cn_skein512_update(Skein_512_Ctxt_t * __restrict__ ctx, const uint8_t * __restrict__ msg, size_t msgByteCnt)
{
size_t n;
if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES)
{
if (ctx->h.bCnt)
{
n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt;
if (n)
{
memcpy(&ctx->b[ctx->h.bCnt],msg,n);
msgByteCnt -= n;
msg += n;
ctx->h.bCnt += n;
}
cn_skein512_processblock(ctx,ctx->b,1,SKEIN_512_BLOCK_BYTES);
ctx->h.bCnt = 0;
}
if (msgByteCnt > SKEIN_512_BLOCK_BYTES)
{
n = (msgByteCnt-1) / SKEIN_512_BLOCK_BYTES;
cn_skein512_processblock(ctx,msg,n,SKEIN_512_BLOCK_BYTES);
msgByteCnt -= n * SKEIN_512_BLOCK_BYTES;
msg += n * SKEIN_512_BLOCK_BYTES;
}
}
if (msgByteCnt)
{
memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt);
ctx->h.bCnt += msgByteCnt;
}
}
__device__ void cn_skein_update(skeinHashState * __restrict__ state, const BitSequence * __restrict__ data, DataLength databitlen)
{
if ((databitlen & 7) == 0)
{
cn_skein512_update(&state->u.ctx_512,data,databitlen >> 3);
}
else
{
size_t bCnt = (databitlen >> 3) + 1;
uint8_t b,mask;
mask = (uint8_t) (1u << (7 - (databitlen & 7)));
b = (uint8_t) ((data[bCnt-1] & (0-mask)) | mask);
cn_skein512_update(&state->u.ctx_512,data,bCnt-1);
cn_skein512_update(&state->u.ctx_512,&b , 1 );
Skein_Set_Bit_Pad_Flag(state->u.h);
}
}
__device__ void cn_skein(const BitSequence * __restrict__ data, DataLength len, BitSequence * __restrict__ hashval)
{
int hashbitlen = 256;
DataLength databitlen = len << 3;
skeinHashState state;
state.statebits = 64*SKEIN_512_STATE_WORDS;
cn_skein_init(&state, hashbitlen);
cn_skein_update(&state, data, databitlen);
cn_skein_final(&state, hashval);
}
+99
View File
@@ -0,0 +1,99 @@
#pragma once
#include "xmrstak/misc/environment.hpp"
#include "xmrstak/params.hpp"
#include <thread>
#include <atomic>
#include <vector>
#include <string>
#include "iBackend.hpp"
#include <iostream>
#ifndef USE_PRECOMPILED_HEADERS
# ifdef WIN32
# include <direct.h>
# include <windows.h>
# else
# include <sys/types.h>
# include <dlfcn.h>
# endif
# include <iostream>
#endif
namespace xmrstak
{
struct plugin
{
plugin(const std::string backendName, const std::string libName) : fn_starterBackend(nullptr), m_backendName(backendName)
{
#ifdef WIN32
libBackend = LoadLibrary(TEXT((libName + ".dll").c_str()));
if(!libBackend)
{
std::cerr << "WARNING: "<< m_backendName <<" cannot load backend library: " << (libName + ".dll") << std::endl;
return;
}
#else
libBackend = dlopen((params::inst().executablePrefix + "/lib" + libName + ".so").c_str(), RTLD_LAZY);
if(!libBackend)
{
std::cerr << "WARNING: "<< m_backendName <<" cannot load backend library: " << dlerror() << std::endl;
return;
}
#endif
#ifdef WIN32
fn_starterBackend = (starterBackend_t) GetProcAddress(libBackend, "xmrstak_start_backend");
if (!fn_starterBackend)
{
std::cerr << "WARNING: backend plugin " << libName << " contains no entry 'xmrstak_start_backend': " <<GetLastError()<< std::endl;
}
#else
// reset last error
dlerror();
fn_starterBackend = (starterBackend_t) dlsym(libBackend, "xmrstak_start_backend");
const char* dlsym_error = dlerror();
if(dlsym_error)
{
std::cerr << "WARNING: backend plugin " << libName << " contains no entry 'xmrstak_start_backend': " << dlsym_error << std::endl;
}
#endif
}
std::vector<iBackend*>* startBackend(uint32_t threadOffset, miner_work& pWork, environment& env)
{
if(fn_starterBackend == nullptr)
{
std::vector<iBackend*>* pvThreads = new std::vector<iBackend*>();
std::cerr << "WARNING: " << m_backendName << " Backend disabled"<< std::endl;
return pvThreads;
}
return fn_starterBackend(threadOffset, pWork, env);
}
std::string m_backendName;
typedef std::vector<iBackend*>* (*starterBackend_t)(uint32_t threadOffset, miner_work& pWork, environment& env);
starterBackend_t fn_starterBackend;
#ifdef WIN32
HINSTANCE libBackend;
#else
void *libBackend;
#endif
/* \todo add unload to destructor and change usage of plugin that libs keeped open until the miner endss
#ifdef WIN32
FreeLibrary(libBackend);
#else
dlclose(libBackend);
#endif
* */
};
} // namepsace xmrstak
+370
View File
@@ -0,0 +1,370 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with OpenSSL (or a modified version of that library), containing parts
* covered by the terms of OpenSSL License and SSLeay License, the licensors
* of this Program grant you additional permission to convey the resulting work.
*
*/
#include "xmrstak/misc/executor.hpp"
#include "xmrstak/backend/miner_work.hpp"
#include "xmrstak/backend/globalStates.hpp"
#include "xmrstak/backend/backendConnector.hpp"
#include "xmrstak/jconf.hpp"
#include "xmrstak/misc/console.hpp"
#include "xmrstak/donate-level.hpp"
#include "xmrstak/params.hpp"
#include "xmrstak/misc/configEditor.hpp"
#include "xmrstak/version.hpp"
#ifndef CONF_NO_HTTPD
# include "xmrstak/http//httpd.hpp"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <time.h>
#include <iostream>
#ifndef CONF_NO_TLS
#include <openssl/ssl.h>
#include <openssl/err.h>
#endif
#ifdef _WIN32
# define strcasecmp _stricmp
#endif // _WIN32
void do_benchmark();
void help()
{
using namespace std;
using namespace xmrstak;
cout<<"Usage: "<<params::inst().binaryName<<" [OPTION]..."<<endl;
cout<<" "<<endl;
cout<<" -c, --config FILE common miner configuration file"<<endl;
cout<<" -h, --help show this help"<<endl;
#ifndef CONF_NO_CPU
cout<<" --noCPU disable the CPU miner backend"<<endl;
cout<<" --cpu FILE CPU backend miner config file"<<endl;
#endif
#ifndef CONF_NO_OPENCL
cout<<" --noAMD disable the AMD miner backend"<<endl;
cout<<" --amd FILE AMD backend miner config file"<<endl;
#endif
#ifndef CONF_NO_CUDA
cout<<" --noNVIDIA disable the NVIDIA miner backend"<<endl;
cout<<" --nvidia FILE NVIDIA backend miner config file"<<endl;
#endif
cout<<" "<<endl;
cout<<"The Following options temporary overwrites the config file settings:"<<endl;
cout<<" -o, --url URL pool url and port, e.g. pool.usxmrpool.com:3333"<<endl;
cout<<" -u, --user USERNAME pool user name or wallet address"<<endl;
cout<<" -p, --pass PASSWD pool password, in the most cases x or empty \"\""<<endl;
cout<<" \n"<<endl;
cout<<XMR_STAK_NAME<<" "<<XMR_STAK_VERSION<<endl;
cout<<"Brought to by fireice_uk and psychocrypt under GPLv3."<<endl;
}
int main(int argc, char *argv[])
{
#ifndef CONF_NO_TLS
SSL_library_init();
SSL_load_error_strings();
ERR_load_BIO_strings();
ERR_load_crypto_strings();
SSL_load_error_strings();
OpenSSL_add_all_digests();
#endif
srand(time(0));
using namespace xmrstak;
std::string pathWithName(argv[0]);
auto pos = pathWithName.rfind("/");
if(pos == std::string::npos)
{
// try windows "\"
pos = pathWithName.rfind("\\");
}
params::inst().binaryName = std::string(pathWithName, pos + 1, std::string::npos);
if(params::inst().binaryName.compare(pathWithName) != 0)
params::inst().executablePrefix = std::string(pathWithName, 0, pos);
bool userSetPasswd = false;
for(int i = 1; i < argc; ++i)
{
std::string opName(argv[i]);
if(opName.compare("-h") == 0 || opName.compare("--help") == 0)
{
help();
// \todo give return code to win_exit to allow passing CI
//win_exit();
return 0;
}
else if(opName.compare("--noCPU") == 0)
{
params::inst().useCPU = false;
}
else if(opName.compare("--noAMD") == 0)
{
params::inst().useAMD = false;
}
else if(opName.compare("--noNVIDIA") == 0)
{
params::inst().useNVIDIA = false;
}
else if(opName.compare("--cpu") == 0)
{
++i;
if( i >=argc )
{
printer::inst()->print_msg(L0, "No argument for parameter '--cpu' given");
win_exit();
return 1;
}
params::inst().configFileCPU = argv[i];
}
else if(opName.compare("--amd") == 0)
{
++i;
if( i >=argc )
{
printer::inst()->print_msg(L0, "No argument for parameter '--amd' given");
win_exit();
return 1;
}
params::inst().configFileAMD = argv[i];
}
else if(opName.compare("--nvidia") == 0)
{
++i;
if( i >=argc )
{
printer::inst()->print_msg(L0, "No argument for parameter '--nvidia' given");
win_exit();
return 1;
}
params::inst().configFileNVIDIA = argv[i];
}
else if(opName.compare("-o") == 0 || opName.compare("--url") == 0)
{
++i;
if( i >=argc )
{
printer::inst()->print_msg(L0, "No argument for parameter '-o/--url' given");
win_exit();
return 1;
}
params::inst().poolURL = argv[i];
}
else if(opName.compare("-u") == 0 || opName.compare("--user") == 0)
{
++i;
if( i >=argc )
{
printer::inst()->print_msg(L0, "No argument for parameter '-u/--user' given");
win_exit();
return 1;
}
params::inst().poolUsername = argv[i];
}
else if(opName.compare("-p") == 0 || opName.compare("--pass") == 0)
{
++i;
if( i >=argc )
{
printer::inst()->print_msg(L0, "No argument for parameter '-p/--pass' given");
win_exit();
return 1;
}
userSetPasswd = true;
params::inst().poolPasswd = argv[i];
}
else if(opName.compare("-c") == 0 || opName.compare("--config") == 0)
{
++i;
if( i >=argc )
{
printer::inst()->print_msg(L0, "No argument for parameter '-c/--config' given");
win_exit();
return 1;
}
params::inst().configFile = argv[i];
}
else
{
printer::inst()->print_msg(L0, "Parameter unknown '%s'",argv[i]);
win_exit();
return 1;
}
}
// check if we need a guided start
if(!configEditor::file_exist(params::inst().configFile))
{
// load the template of the backend config into a char variable
const char *tpl =
#include "../config.tpl"
;
configEditor configTpl{};
configTpl.set(std::string(tpl));
auto& pool = params::inst().poolURL;
if(pool.empty())
{
std::cout<<"Please enter:\n- pool address: e.g. pool.usxmrpool.com:3333"<<std::endl;
std::cin >> pool;
}
auto& userName = params::inst().poolUsername;
if(userName.empty())
{
std::cout<<"- user name (wallet address or pool login):"<<std::endl;
std::cin >> userName;
}
auto& passwd = params::inst().poolPasswd;
if(passwd.empty() && (!userSetPasswd))
{
// clear everything from stdin to allow an empty password
std::cin.clear(); std::cin.ignore(INT_MAX,'\n');
std::cout<<"- password (mostly empty or x):"<<std::endl;
getline(std::cin, passwd);
}
configTpl.replace("POOLURL", pool);
configTpl.replace("POOLUSER", userName);
configTpl.replace("POOLPASSWD", passwd);
configTpl.write(params::inst().configFile);
std::cout<<"Configuration stored in file '"<<params::inst().configFile<<"'"<<std::endl;
}
if(!jconf::inst()->parse_config(params::inst().configFile.c_str()))
{
win_exit();
return 0;
}
if (!BackendConnector::self_test())
{
win_exit();
return 0;
}
#ifndef CONF_NO_HTTPD
if(jconf::inst()->GetHttpdPort() != 0)
{
if (!httpd::inst()->start_daemon())
{
win_exit();
return 0;
}
}
#endif
printer::inst()->print_str("-------------------------------------------------------------------\n");
printer::inst()->print_str( XMR_STAK_NAME" " XMR_STAK_VERSION " mining software.\n");
printer::inst()->print_str("Based on CPU mining code by wolf9466 (heavily optimized by fireice_uk).\n");
#ifndef CONF_NO_CUDA
printer::inst()->print_str("NVIDIA mining code was written by KlausT and psychocrypt.\n");
#endif
#ifndef CONF_NO_OPENCL
printer::inst()->print_str("AMD mining code was written by wolf9466.\n");
#endif
printer::inst()->print_str("Brought to you by fireice_uk and psychocrypt under GPLv3.\n\n");
char buffer[64];
snprintf(buffer, sizeof(buffer), "Configurable dev donation level is set to %.1f %%\n\n", fDevDonationLevel * 100.0);
printer::inst()->print_str(buffer);
printer::inst()->print_str("You can use following keys to display reports:\n");
printer::inst()->print_str("'h' - hashrate\n");
printer::inst()->print_str("'r' - results\n");
printer::inst()->print_str("'c' - connection\n");
printer::inst()->print_str("-------------------------------------------------------------------\n");
if(strlen(jconf::inst()->GetOutputFile()) != 0)
printer::inst()->open_logfile(jconf::inst()->GetOutputFile());
executor::inst()->ex_start(jconf::inst()->DaemonMode());
using namespace std::chrono;
uint64_t lastTime = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
int key;
while(true)
{
key = get_key();
switch(key)
{
case 'h':
executor::inst()->push_event(ex_event(EV_USR_HASHRATE));
break;
case 'r':
executor::inst()->push_event(ex_event(EV_USR_RESULTS));
break;
case 'c':
executor::inst()->push_event(ex_event(EV_USR_CONNSTAT));
break;
default:
break;
}
uint64_t currentTime = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
/* Hard guard to make sure we never get called more than twice per second */
if( currentTime - lastTime < 500)
std::this_thread::sleep_for(std::chrono::milliseconds(500 - (currentTime - lastTime)));
lastTime = currentTime;
}
return 0;
}
void do_benchmark()
{
using namespace std::chrono;
std::vector<xmrstak::iBackend*>* pvThreads;
printer::inst()->print_msg(L0, "Running a 60 second benchmark...");
uint8_t work[76] = {0};
xmrstak::miner_work oWork = xmrstak::miner_work("", work, sizeof(work), 0, 0, 0);
pvThreads = xmrstak::BackendConnector::thread_starter(oWork);
uint64_t iStartStamp = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
std::this_thread::sleep_for(std::chrono::seconds(60));
oWork = xmrstak::miner_work();
xmrstak::globalStates::inst().switch_work(oWork);
double fTotalHps = 0.0;
for (uint32_t i = 0; i < pvThreads->size(); i++)
{
double fHps = pvThreads->at(i)->iHashCount;
fHps /= (pvThreads->at(i)->iTimestamp - iStartStamp) / 1000.0;
printer::inst()->print_msg(L0, "Thread %u: %.1f H/S", i, fHps);
fTotalHps += fHps;
}
printer::inst()->print_msg(L0, "Total: %.1f H/S", fTotalHps);
}
+161 -184
View File
@@ -1,184 +1,161 @@
/*
* Thread configuration for each thread. Make sure it matches the number above.
* low_power_mode - This mode will double the cache usage, and double the single thread performance. It will
* consume much less power (as less cores are working), but will max out at around 80-85% of
* the maximum performance.
*
* no_prefetch - Some sytems can gain up to extra 5% here, but sometimes it will have no difference or make
* things slower.
*
* affine_to_cpu - This can be either false (no affinity), or the CPU core number. Note that on hyperthreading
* systems it is better to assign threads to physical cores. On Windows this usually means selecting
* even or odd numbered cpu numbers. For Linux it will be usually the lower CPU numbers, so for a 4
* physical core CPU you should select cpu numbers 0-3.
*
* On the first run the miner will look at your system and suggest a basic configuration that will work,
* you can try to tweak it from there to get the best performance.
*
* A filled out configuration should look like this:
* "cpu_threads_conf" :
* [
* { "low_power_mode" : false, "no_prefetch" : true, "affine_to_cpu" : 0 },
* { "low_power_mode" : false, "no_prefetch" : true, "affine_to_cpu" : 1 },
* ],
*/
"cpu_threads_conf" :
null,
/*
* LARGE PAGE SUPPORT
* Large pages need a properly set up OS. It can be difficult if you are not used to systems administration,
* but the performance results are worth the trouble - you will get around 20% boost. Slow memory mode is
* meant as a backup, you won't get stellar results there. If you are running into trouble, especially
* on Windows, please read the common issues in the README.
*
* By default we will try to allocate large pages. This means you need to "Run As Administrator" on Windows.
* You need to edit your system's group policies to enable locking large pages. Here are the steps from MSDN
*
* 1. On the Start menu, click Run. In the Open box, type gpedit.msc.
* 2. On the Local Group Policy Editor console, expand Computer Configuration, and then expand Windows Settings.
* 3. Expand Security Settings, and then expand Local Policies.
* 4. Select the User Rights Assignment folder.
* 5. The policies will be displayed in the details pane.
* 6. In the pane, double-click Lock pages in memory.
* 7. In the Local Security Setting – Lock pages in memory dialog box, click Add User or Group.
* 8. In the Select Users, Service Accounts, or Groups dialog box, add an account that you will run the miner on
* 9. Reboot for change to take effect.
*
* Windows also tends to fragment memory a lot. If you are running on a system with 4-8GB of RAM you might need
* to switch off all the auto-start applications and reboot to have a large enough chunk of contiguous memory.
*
* On Linux you will need to configure large page support "sudo sysctl -w vm.nr_hugepages=128" and increase your
* ulimit -l. To do do this you need to add following lines to /etc/security/limits.conf - "* soft memlock 262144"
* and "* hard memlock 262144". You can also do it Windows-style and simply run-as-root, but this is NOT
* recommended for security reasons.
*
* Memory locking means that the kernel can't swap out the page to disk - something that is unlikely to happen on a
* command line system that isn't starved of memory. I haven't observed any difference on a CLI Linux system between
* locked and unlocked memory. If that is your setup see option "no_mlck".
*/
/*
* use_slow_memory defines our behavior with regards to large pages. There are three possible options here:
* always - Don't even try to use large pages. Always use slow memory.
* warn - We will try to use large pages, but fall back to slow memory if that fails.
* no_mlck - This option is only relevant on Linux, where we can use large pages without locking memory.
* It will never use slow memory, but it won't attempt to mlock
* never - If we fail to allocate large pages we will print an error and exit.
*/
"use_slow_memory" : "warn",
/*
* NiceHash mode
* nicehash_nonce - Limit the nonce to 3 bytes as required by nicehash. This cuts all the safety margins, and
* if a block isn't found within 30 minutes then you might run into nonce collisions. Number
* of threads in this mode is hard-limited to 32.
*/
"nicehash_nonce" : false,
/*
* Manual hardware AES override
*
* Some VMs don't report AES capability correctly. You can set this value to true to enforce hardware AES or
* to false to force disable AES or null to let the miner decide if AES is used.
*
* WARNING: setting this to true on a CPU that doesn't support hardware AES will crash the miner.
*/
"aes_override" : null,
/*
* TLS Settings
* If you need real security, make sure tls_secure_algo is enabled (otherwise MITM attack can downgrade encryption
* to trivially breakable stuff like DES and MD5), and verify the server's fingerprint through a trusted channel.
*
* use_tls - This option will make us connect using Transport Layer Security.
* tls_secure_algo - Use only secure algorithms. This will make us quit with an error if we can't negotiate a secure algo.
* tls_fingerprint - Server's SHA256 fingerprint. If this string is non-empty then we will check the server's cert against it.
*/
"use_tls" : false,
"tls_secure_algo" : true,
"tls_fingerprint" : "",
/*
* pool_address - Pool address should be in the form "pool.supportxmr.com:3333". Only stratum pools are supported.
* wallet_address - Your wallet, or pool login.
* pool_password - Can be empty in most cases or "x".
*
* We feature pools up to 1MH/s. For a more complete list see M5M400's pool list at www.moneropools.com
*/
"pool_address" : "pool.usxmrpool.com:3333",
"wallet_address" : "",
"pool_password" : "",
/*
* Network timeouts.
* Because of the way this client is written it doesn't need to constantly talk (keep-alive) to the server to make
* sure it is there. We detect a buggy / overloaded server by the call timeout. The default values will be ok for
* nearly all cases. If they aren't the pool has most likely overload issues. Low call timeout values are preferable -
* long timeouts mean that we waste hashes on potentially stale jobs. Connection report will tell you how long the
* server usually takes to process our calls.
*
* call_timeout - How long should we wait for a response from the server before we assume it is dead and drop the connection.
* retry_time - How long should we wait before another connection attempt.
* Both values are in seconds.
* giveup_limit - Limit how many times we try to reconnect to the pool. Zero means no limit. Note that stak miners
* don't mine while the connection is lost, so your computer's power usage goes down to idle.
*/
"call_timeout" : 10,
"retry_time" : 10,
"giveup_limit" : 0,
/*
* Output control.
* Since most people are used to miners printing all the time, that's what we do by default too. This is suboptimal
* really, since you cannot see errors under pages and pages of text and performance stats. Given that we have internal
* performance monitors, there is very little reason to spew out pages of text instead of concise reports.
* Press 'h' (hashrate), 'r' (results) or 'c' (connection) to print reports.
*
* verbose_level - 0 - Don't print anything.
* 1 - Print intro, connection event, disconnect event
* 2 - All of level 1, and new job (block) event if the difficulty is different from the last job
* 3 - All of level 1, and new job (block) event in all cases, result submission event.
* 4 - All of level 3, and automatic hashrate report printing
*/
"verbose_level" : 3,
/*
* Automatic hashrate report
*
* h_print_time - How often, in seconds, should we print a hashrate report if verbose_level is set to 4.
* This option has no effect if verbose_level is not 4.
*/
"h_print_time" : 60,
/*
* Daemon mode
*
* If you are running the process in the background and you don't need the keyboard reports, set this to true.
* This should solve the hashrate problems on some emulated terminals.
*/
"daemon_mode" : false,
/*
* Output file
*
* output_file - This option will log all output to a file.
*
*/
"output_file" : "",
/*
* Built-in web server
* I like checking my hashrate on my phone. Don't you?
* Keep in mind that you will need to set up port forwarding on your router if you want to access it from
* outside of your home network. Ports lower than 1024 on Linux systems will require root.
*
* httpd_port - Port we should listen on. Default, 0, will switch off the server.
*/
"httpd_port" : 0,
/*
* prefer_ipv4 - IPv6 preference. If the host is available on both IPv4 and IPv6 net, which one should be choose?
* This setting will only be needed in 2020's. No need to worry about it now.
*/
"prefer_ipv4" : true,
R"===(
/*
* pool_address - Pool address should be in the form "pool.supportxmr.com:3333". Only stratum pools are supported.
* wallet_address - Your wallet, or pool login.
* pool_password - Can be empty in most cases or "x".
*
* We feature pools up to 1MH/s. For a more complete list see M5M400's pool list at www.moneropools.com
*/
"pool_address" : "POOLURL",
"wallet_address" : "POOLUSER",
"pool_password" : "POOLPASSWD",
/*
* Network timeouts.
* Because of the way this client is written it doesn't need to constantly talk (keep-alive) to the server to make
* sure it is there. We detect a buggy / overloaded server by the call timeout. The default values will be ok for
* nearly all cases. If they aren't the pool has most likely overload issues. Low call timeout values are preferable -
* long timeouts mean that we waste hashes on potentially stale jobs. Connection report will tell you how long the
* server usually takes to process our calls.
*
* call_timeout - How long should we wait for a response from the server before we assume it is dead and drop the connection.
* retry_time - How long should we wait before another connection attempt.
* Both values are in seconds.
* giveup_limit - Limit how many times we try to reconnect to the pool. Zero means no limit. Note that stak miners
* don't mine while the connection is lost, so your computer's power usage goes down to idle.
*/
"call_timeout" : 10,
"retry_time" : 10,
"giveup_limit" : 0,
/*
* Output control.
* Since most people are used to miners printing all the time, that's what we do by default too. This is suboptimal
* really, since you cannot see errors under pages and pages of text and performance stats. Given that we have internal
* performance monitors, there is very little reason to spew out pages of text instead of concise reports.
* Press 'h' (hashrate), 'r' (results) or 'c' (connection) to print reports.
*
* verbose_level - 0 - Don't print anything.
* 1 - Print intro, connection event, disconnect event
* 2 - All of level 1, and new job (block) event if the difficulty is different from the last job
* 3 - All of level 1, and new job (block) event in all cases, result submission event.
* 4 - All of level 3, and automatic hashrate report printing
*/
"verbose_level" : 3,
/*
* Automatic hashrate report
*
* h_print_time - How often, in seconds, should we print a hashrate report if verbose_level is set to 4.
* This option has no effect if verbose_level is not 4.
*/
"h_print_time" : 60,
/*
* Manual hardware AES override
*
* Some VMs don't report AES capability correctly. You can set this value to true to enforce hardware AES or
* to false to force disable AES or null to let the miner decide if AES is used.
*
* WARNING: setting this to true on a CPU that doesn't support hardware AES will crash the miner.
*/
"aes_override" : null,
/*
* LARGE PAGE SUPPORT
* Large pages need a properly set up OS. It can be difficult if you are not used to systems administration,
* but the performance results are worth the trouble - you will get around 20% boost. Slow memory mode is
* meant as a backup, you won't get stellar results there. If you are running into trouble, especially
* on Windows, please read the common issues in the README.
*
* By default we will try to allocate large pages. This means you need to "Run As Administrator" on Windows.
* You need to edit your system's group policies to enable locking large pages. Here are the steps from MSDN
*
* 1. On the Start menu, click Run. In the Open box, type gpedit.msc.
* 2. On the Local Group Policy Editor console, expand Computer Configuration, and then expand Windows Settings.
* 3. Expand Security Settings, and then expand Local Policies.
* 4. Select the User Rights Assignment folder.
* 5. The policies will be displayed in the details pane.
* 6. In the pane, double-click Lock pages in memory.
* 7. In the Local Security Setting – Lock pages in memory dialog box, click Add User or Group.
* 8. In the Select Users, Service Accounts, or Groups dialog box, add an account that you will run the miner on
* 9. Reboot for change to take effect.
*
* Windows also tends to fragment memory a lot. If you are running on a system with 4-8GB of RAM you might need
* to switch off all the auto-start applications and reboot to have a large enough chunk of contiguous memory.
*
* On Linux you will need to configure large page support "sudo sysctl -w vm.nr_hugepages=128" and increase your
* ulimit -l. To do do this you need to add following lines to /etc/security/limits.conf - "* soft memlock 262144"
* and "* hard memlock 262144". You can also do it Windows-style and simply run-as-root, but this is NOT
* recommended for security reasons.
*
* Memory locking means that the kernel can't swap out the page to disk - something that is unlikely to happen on a
* command line system that isn't starved of memory. I haven't observed any difference on a CLI Linux system between
* locked and unlocked memory. If that is your setup see option "no_mlck".
*/
/*
* use_slow_memory defines our behavior with regards to large pages. There are three possible options here:
* always - Don't even try to use large pages. Always use slow memory.
* warn - We will try to use large pages, but fall back to slow memory if that fails.
* no_mlck - This option is only relevant on Linux, where we can use large pages without locking memory.
* It will never use slow memory, but it won't attempt to mlock
* never - If we fail to allocate large pages we will print an error and exit.
*/
"use_slow_memory" : "warn",
/*
* NiceHash mode
* nicehash_nonce - Limit the nonce to 3 bytes as required by nicehash. This cuts all the safety margins, and
* if a block isn't found within 30 minutes then you might run into nonce collisions. Number
* of threads in this mode is hard-limited to 32.
*/
"nicehash_nonce" : false,
/*
* TLS Settings
* If you need real security, make sure tls_secure_algo is enabled (otherwise MITM attack can downgrade encryption
* to trivially breakable stuff like DES and MD5), and verify the server's fingerprint through a trusted channel.
*
* use_tls - This option will make us connect using Transport Layer Security.
* tls_secure_algo - Use only secure algorithms. This will make us quit with an error if we can't negotiate a secure algo.
* tls_fingerprint - Server's SHA256 fingerprint. If this string is non-empty then we will check the server's cert against it.
*/
"use_tls" : false,
"tls_secure_algo" : true,
"tls_fingerprint" : "",
/*
* Daemon mode
*
* If you are running the process in the background and you don't need the keyboard reports, set this to true.
* This should solve the hashrate problems on some emulated terminals.
*/
"daemon_mode" : false,
/*
* Output file
*
* output_file - This option will log all output to a file.
*
*/
"output_file" : "",
/*
* Built-in web server
* I like checking my hashrate on my phone. Don't you?
* Keep in mind that you will need to set up port forwarding on your router if you want to access it from
* outside of your home network. Ports lower than 1024 on Linux systems will require root.
*
* httpd_port - Port we should listen on. Default, 0, will switch off the server.
*/
"httpd_port" : 0,
/*
* prefer_ipv4 - IPv6 preference. If the host is available on both IPv4 and IPv6 net, which one should be choose?
* This setting will only be needed in 2020's. No need to worry about it now.
*/
"prefer_ipv4" : true,
)==="
+8 -8
View File
@@ -23,19 +23,19 @@
#ifndef CONF_NO_HTTPD
#include "httpd.hpp"
#include "webdesign.hpp"
#include "xmrstak/net/msgstruct.hpp"
#include "xmrstak/misc/console.hpp"
#include "xmrstak/misc/executor.hpp"
#include "xmrstak/jconf.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include "msgstruct.h"
#include "httpd.h"
#include "console.h"
#include "executor.h"
#include "jconf.h"
#include "webdesign.h"
#include <microhttpd.h>
#ifdef _WIN32
#define strcasecmp _stricmp
+2
View File
@@ -1,5 +1,7 @@
#pragma once
#include <stdlib.h>
struct MHD_Daemon;
struct MHD_Connection;
+1 -1
View File
@@ -115,7 +115,7 @@ extern const char sHtmlCommonHeader [] =
extern const char sHtmlHashrateBodyHigh [] =
"<div class=data>"
"<table>"
"<tr><th>Thread ID</th><th>2.5s</th><th>60s</th><th>15m</th><th rowspan='%u'>H/s</td></tr>";
"<tr><th>Thread ID</th><th>10s</th><th>60s</th><th>15m</th><th rowspan='%u'>H/s</td></tr>";
extern const char sHtmlHashrateTableRow [] =
"<tr><th>%u</th><td>%s</td><td>%s</td><td>%s</td></tr>";
+71 -127
View File
@@ -21,8 +21,12 @@
*
*/
#include "jconf.h"
#include "console.h"
#include "jconf.hpp"
#include "params.hpp"
#include "xmrstak/misc/console.hpp"
#include "xmrstak/misc/jext.hpp"
#include "xmrstak/misc/console.hpp"
#include <stdio.h>
#include <stdlib.h>
@@ -35,20 +39,16 @@
#include <cpuid.h>
#endif
#include "rapidjson/document.h"
#include "rapidjson/error/en.h"
#include "jext.h"
#include "console.h"
using namespace rapidjson;
/*
* This enum needs to match index in oConfigValues, otherwise we will get a runtime error
*/
enum configEnum { aCpuThreadsConf, sUseSlowMem, bNiceHashMode, bAesOverride,
enum configEnum {
bTlsMode, bTlsSecureAlgo, sTlsFingerprint, sPoolAddr, sWalletAddr, sPoolPwd,
iCallTimeout, iNetRetry, iGiveUpLimit, iVerboseLevel, iAutohashTime,
bDaemonMode, sOutputFile, iHttpdPort, bPreferIpv4 };
bDaemonMode, sOutputFile, iHttpdPort, bPreferIpv4, bNiceHashMode, bAesOverride, sUseSlowMem };
struct configVal {
configEnum iName;
@@ -59,10 +59,6 @@ struct configVal {
// Same order as in configEnum, as per comment above
// kNullType means any type
configVal oConfigValues[] = {
{ aCpuThreadsConf, "cpu_threads_conf", kNullType },
{ sUseSlowMem, "use_slow_memory", kStringType },
{ bNiceHashMode, "nicehash_nonce", kTrueType },
{ bAesOverride, "aes_override", kNullType },
{ bTlsMode, "use_tls", kTrueType },
{ bTlsSecureAlgo, "tls_secure_algo", kTrueType },
{ sTlsFingerprint, "tls_fingerprint", kStringType },
@@ -77,7 +73,10 @@ configVal oConfigValues[] = {
{ bDaemonMode, "daemon_mode", kTrueType },
{ sOutputFile, "output_file", kStringType },
{ iHttpdPort, "httpd_port", kNumberType },
{ bPreferIpv4, "prefer_ipv4", kTrueType }
{ bPreferIpv4, "prefer_ipv4", kTrueType },
{ bNiceHashMode, "nicehash_nonce", kTrueType },
{ bAesOverride, "aes_override", kNullType },
{ sUseSlowMem, "use_slow_memory", kStringType }
};
constexpr size_t iConfigCnt = (sizeof(oConfigValues)/sizeof(oConfigValues[0]));
@@ -106,70 +105,11 @@ struct jconf::opaque_private
}
};
jconf* jconf::oInst = nullptr;
jconf::jconf()
{
prv = new opaque_private();
}
bool jconf::GetThreadConfig(size_t id, thd_cfg &cfg)
{
if(!prv->configValues[aCpuThreadsConf]->IsArray())
return false;
if(id >= prv->configValues[aCpuThreadsConf]->Size())
return false;
const Value& oThdConf = prv->configValues[aCpuThreadsConf]->GetArray()[id];
if(!oThdConf.IsObject())
return false;
const Value *mode, *no_prefetch, *aff;
mode = GetObjectMember(oThdConf, "low_power_mode");
no_prefetch = GetObjectMember(oThdConf, "no_prefetch");
aff = GetObjectMember(oThdConf, "affine_to_cpu");
if(mode == nullptr || no_prefetch == nullptr || aff == nullptr)
return false;
if(!mode->IsBool() || !no_prefetch->IsBool())
return false;
if(!aff->IsNumber() && !aff->IsBool())
return false;
if(aff->IsNumber() && aff->GetInt64() < 0)
return false;
cfg.bDoubleMode = mode->GetBool();
cfg.bNoPrefetch = no_prefetch->GetBool();
if(aff->IsNumber())
cfg.iCpuAff = aff->GetInt64();
else
cfg.iCpuAff = -1;
return true;
}
jconf::slow_mem_cfg jconf::GetSlowMemSetting()
{
const char* opt = prv->configValues[sUseSlowMem]->GetString();
if(strcasecmp(opt, "always") == 0)
return always_use;
else if(strcasecmp(opt, "no_mlck") == 0)
return no_mlck;
else if(strcasecmp(opt, "warn") == 0)
return print_warning;
else if(strcasecmp(opt, "never") == 0)
return never_use;
else
return unknown_value;
}
bool jconf::GetTlsSetting()
{
return prv->configValues[bTlsMode]->GetBool();
@@ -187,17 +127,27 @@ const char* jconf::GetTlsFingerprint()
const char* jconf::GetPoolAddress()
{
return prv->configValues[sPoolAddr]->GetString();
auto& poolURL = xmrstak::params::inst().poolURL;
if(poolURL.empty())
poolURL = prv->configValues[sPoolAddr]->GetString();
return poolURL.c_str();
}
const char* jconf::GetPoolPwd()
{
return prv->configValues[sPoolPwd]->GetString();
auto& poolPasswd = xmrstak::params::inst().poolPasswd;
if(poolPasswd.empty())
poolPasswd = prv->configValues[sPoolPwd]->GetString();
return poolPasswd.c_str();
}
const char* jconf::GetWalletAddress()
{
return prv->configValues[sWalletAddr]->GetString();
auto& poolUsername = xmrstak::params::inst().poolUsername;
if(poolUsername.empty())
poolUsername = prv->configValues[sWalletAddr]->GetString();
return poolUsername.c_str();
}
bool jconf::PreferIpv4()
@@ -205,19 +155,6 @@ bool jconf::PreferIpv4()
return prv->configValues[bPreferIpv4]->GetBool();
}
size_t jconf::GetThreadCount()
{
if(prv->configValues[aCpuThreadsConf]->IsArray())
return prv->configValues[aCpuThreadsConf]->Size();
else
return 0;
}
bool jconf::NeedsAutoconf()
{
return !prv->configValues[aCpuThreadsConf]->IsArray();
}
uint64_t jconf::GetCallTimeout()
{
return prv->configValues[iCallTimeout]->GetUint64();
@@ -248,11 +185,6 @@ uint16_t jconf::GetHttpdPort()
return prv->configValues[iHttpdPort]->GetUint();
}
bool jconf::NiceHashMode()
{
return prv->configValues[bNiceHashMode]->GetBool();
}
bool jconf::DaemonMode()
{
return prv->configValues[bDaemonMode]->GetBool();
@@ -263,6 +195,12 @@ const char* jconf::GetOutputFile()
return prv->configValues[sOutputFile]->GetString();
}
bool jconf::NiceHashMode()
{
return prv->configValues[bNiceHashMode]->GetBool();
}
void jconf::cpuid(uint32_t eax, int32_t ecx, int32_t val[4])
{
memset(val, 0, sizeof(int32_t)*4);
@@ -289,6 +227,22 @@ bool jconf::check_cpu_features()
return bHaveSse2;
}
jconf::slow_mem_cfg jconf::GetSlowMemSetting()
{
const char* opt = prv->configValues[sUseSlowMem]->GetString();
if(strcasecmp(opt, "always") == 0)
return always_use;
else if(strcasecmp(opt, "no_mlck") == 0)
return no_mlck;
else if(strcasecmp(opt, "warn") == 0)
return print_warning;
else if(strcasecmp(opt, "never") == 0)
return never_use;
else
return unknown_value;
}
bool jconf::parse_config(const char* sFilename)
{
FILE * pFile;
@@ -389,29 +343,6 @@ bool jconf::parse_config(const char* sFilename)
}
}
thd_cfg c;
for(size_t i=0; i < GetThreadCount(); i++)
{
if(!GetThreadConfig(i, c))
{
printer::inst()->print_msg(L0, "Thread %llu has invalid config.", int_port(i));
return false;
}
}
if(NiceHashMode() && GetThreadCount() >= 32)
{
printer::inst()->print_msg(L0, "You need to use less than 32 threads in NiceHash mode.");
return false;
}
if(GetSlowMemSetting() == unknown_value)
{
printer::inst()->print_msg(L0,
"Invalid config file. use_slow_memory must be \"always\", \"no_mlck\", \"warn\" or \"never\"");
return false;
}
if(!prv->configValues[iCallTimeout]->IsUint64() ||
!prv->configValues[iNetRetry]->IsUint64() ||
!prv->configValues[iGiveUpLimit]->IsUint64())
@@ -444,6 +375,30 @@ bool jconf::parse_config(const char* sFilename)
}
#endif // CONF_NO_TLS
/* \todo check in the cpu backend if we have more than 32 worker
* keep in mined that we have change the why how the nonce is calculated (reverse thread index)
if(NiceHashMode() && GetThreadCount() >= 32)
{
printer::inst()->print_msg(L0, "You need to use less than 32 threads in NiceHash mode.");
return false;
}
*/
if(prv->configValues[bAesOverride]->IsBool())
bHaveAes = prv->configValues[bAesOverride]->GetBool();
if(!bHaveAes)
printer::inst()->print_msg(L0, "Your CPU doesn't support hardware AES. Don't expect high hashrates.");
printer::inst()->set_verbose_level(prv->configValues[iVerboseLevel]->GetUint64());
if(GetSlowMemSetting() == unknown_value)
{
printer::inst()->print_msg(L0,
"Invalid config file. use_slow_memory must be \"always\", \"no_mlck\", \"warn\" or \"never\"");
return false;
}
#ifdef _WIN32
if(GetSlowMemSetting() == no_mlck)
{
@@ -452,16 +407,5 @@ bool jconf::parse_config(const char* sFilename)
}
#endif // _WIN32
printer::inst()->set_verbose_level(prv->configValues[iVerboseLevel]->GetUint64());
if(NeedsAutoconf())
return true;
if(prv->configValues[bAesOverride]->IsBool())
bHaveAes = prv->configValues[bAesOverride]->GetBool();
if(!bHaveAes)
printer::inst()->print_msg(L0, "Your CPU doesn't support hardware AES. Don't expect high hashrates.");
return true;
}
+15 -12
View File
@@ -1,17 +1,24 @@
#pragma once
#include "xmrstak/misc/environment.hpp"
#include "params.hpp"
#include <stdlib.h>
#include <string>
class jconf
{
public:
static jconf* inst()
{
if (oInst == nullptr) oInst = new jconf;
return oInst;
auto& env = xmrstak::environment::inst();
if(env.pJconfConfig == nullptr)
env.pJconfConfig = new jconf;
return env.pJconfConfig;
};
bool parse_config(const char* sFilename);
bool parse_config(const char* sFilename = xmrstak::params::inst().configFile.c_str());
struct thd_cfg {
bool bDoubleMode;
@@ -27,12 +34,6 @@ public:
unknown_value
};
size_t GetThreadCount();
bool GetThreadConfig(size_t id, thd_cfg &cfg);
bool NeedsAutoconf();
slow_mem_cfg GetSlowMemSetting();
bool GetTlsSetting();
bool TlsSecureAlgos();
const char* GetTlsFingerprint();
@@ -52,19 +53,21 @@ public:
uint16_t GetHttpdPort();
bool NiceHashMode();
bool DaemonMode();
bool PreferIpv4();
bool NiceHashMode();
inline bool HaveHardwareAes() { return bHaveAes; }
static void cpuid(uint32_t eax, int32_t ecx, int32_t val[4]);
slow_mem_cfg GetSlowMemSetting();
private:
jconf();
static jconf* oInst;
bool check_cpu_features();
struct opaque_private;
+57
View File
@@ -0,0 +1,57 @@
#pragma once
#include <atomic>
#include <string>
#include <fstream>
#include <streambuf>
#include <regex>
namespace xmrstak
{
struct configEditor
{
std::string m_fileContent;
configEditor()
{
}
static bool file_exist( const std::string filename)
{
std::ifstream fstream(filename);
return fstream.good();
}
void set( const std::string && content)
{
m_fileContent = content;
}
bool load(const std::string filename)
{
std::ifstream fstream(filename);
m_fileContent = std::string(
(std::istreambuf_iterator<char>(fstream)),
std::istreambuf_iterator<char>()
);
return fstream.good();
}
void write(const std::string filename)
{
std::ofstream out(filename);
out << m_fileContent;
out.close();
}
void replace(const std::string search, const std::string substring)
{
m_fileContent = std::regex_replace(m_fileContent, std::regex(search), substring);
}
};
} // namepsace xmrstak
+18 -3
View File
@@ -21,11 +21,13 @@
*
*/
#include "console.h"
#include "xmrstak/misc/console.hpp"
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <cstdlib>
#ifdef _WIN32
#include <windows.h>
@@ -150,8 +152,6 @@ inline void comp_localtime(const time_t* ctime, tm* stime)
#endif // __WIN32
}
printer* printer::oInst = nullptr;
printer::printer()
{
verbose_level = LINF;
@@ -211,3 +211,18 @@ void printer::print_str(const char* str)
fflush(logfile);
}
}
//Do a press any key for the windows folk. *insert any key joke here*
#ifdef _WIN32
void win_exit()
{
printer::inst()->print_str("Press any key to exit.");
get_key();
std::exit(1);
}
#else
void win_exit() {
std::exit(1);
}
#endif // _WIN32
+10 -3
View File
@@ -1,6 +1,10 @@
#pragma once
#include "xmrstak/misc/environment.hpp"
#include <mutex>
enum out_colours { K_RED, K_GREEN, K_BLUE, K_YELLOW, K_CYAN, K_MAGENTA, K_WHITE, K_NONE };
// Warning - on Linux get_key will detect control keys, but not on Windows.
@@ -24,8 +28,10 @@ class printer
public:
static inline printer* inst()
{
if (oInst == nullptr) oInst = new printer;
return oInst;
auto& env = xmrstak::environment::inst();
if(env.pPrinter == nullptr)
env.pPrinter = new printer;
return env.pPrinter;
};
inline void set_verbose_level(size_t level) { verbose_level = (verbosity)level; }
@@ -35,9 +41,10 @@ public:
private:
printer();
static printer* oInst;
std::mutex print_mutex;
verbosity verbose_level;
FILE* logfile;
};
void win_exit();
+46
View File
@@ -0,0 +1,46 @@
#pragma once
class printer;
class jconf;
class executor;
namespace xmrstak
{
class globalStates;
class params;
struct environment
{
static environment& inst()
{
static environment env;
return env;
}
environment& operator=(const environment& env)
{
this->pPrinter = env.pPrinter;
this->pglobalStates = env.pglobalStates;
this->pJconfConfig = env.pJconfConfig;
this->pExecutor = env.pExecutor;
this->pParams = env.pParams;
return *this;
}
environment() : pPrinter(nullptr), pglobalStates(nullptr)
{
}
printer* pPrinter;
globalStates* pglobalStates;
jconf* pJconfConfig;
executor* pExecutor;
params* pParams;
};
} // namepsace xmrstak
+39 -23
View File
@@ -21,26 +21,30 @@
*
*/
#include "executor.hpp"
#include "xmrstak/net/jpsock.hpp"
#include "telemetry.hpp"
#include "xmrstak/backend/miner_work.hpp"
#include "xmrstak/backend/globalStates.hpp"
#include "xmrstak/backend/backendConnector.hpp"
#include "xmrstak/jconf.hpp"
#include "xmrstak/misc/console.hpp"
#include "xmrstak/donate-level.hpp"
#include "xmrstak/http/webdesign.hpp"
#include <thread>
#include <string>
#include <cmath>
#include <algorithm>
#include <assert.h>
#include <time.h>
#include "executor.h"
#include "jpsock.h"
#include "minethd.h"
#include "jconf.h"
#include "console.h"
#include "donate-level.h"
#include "webdesign.h"
#ifdef _WIN32
#define strncasecmp _strnicmp
#endif // _WIN32
executor* executor::oInst = NULL;
executor::executor()
{
}
@@ -116,8 +120,8 @@ void executor::sched_reconnect()
printer::inst()->print_msg(L1, "Pool connection lost. Waiting %lld s before retry (attempt %llu).",
rt, int_port(iReconnectAttempts));
auto work = minethd::miner_work();
minethd::switch_work(work);
auto work = xmrstak::miner_work();
xmrstak::globalStates::inst().switch_work(work);
push_timed_event(ex_event(EV_RECONNECT, usr_pool_id), rt);
}
@@ -229,12 +233,13 @@ void executor::on_pool_have_job(size_t pool_id, pool_job& oPoolJob)
jpsock* pool = pick_pool_by_id(pool_id);
minethd::miner_work oWork(oPoolJob.sJobID, oPoolJob.bWorkBlob,
xmrstak::miner_work oWork(oPoolJob.sJobID, oPoolJob.bWorkBlob,
oPoolJob.iWorkLen, oPoolJob.iResumeCnt, oPoolJob.iTarget,
pool_id != dev_pool_id && jconf::inst()->NiceHashMode(),
pool_id);
minethd::switch_work(oWork);
oWork.iTarget32 = oPoolJob.iTarget32;
xmrstak::globalStates::inst().switch_work(oWork);
if(pool_id == dev_pool_id)
return;
@@ -350,11 +355,13 @@ void executor::on_switch_pool(size_t pool_id)
return;
}
minethd::miner_work oWork(oPoolJob.sJobID, oPoolJob.bWorkBlob,
xmrstak::miner_work oWork(oPoolJob.sJobID, oPoolJob.bWorkBlob,
oPoolJob.iWorkLen, oPoolJob.iResumeCnt, oPoolJob.iTarget,
jconf::inst()->NiceHashMode(), pool_id);
pool_id);
minethd::switch_work(oWork);
oWork.iTarget32 = oPoolJob.iTarget32;
xmrstak::globalStates::inst().switch_work(oWork);
if(dev_pool->is_running())
push_timed_event(ex_event(EV_DEV_POOL_EXIT), 5);
@@ -365,9 +372,18 @@ void executor::ex_main()
{
assert(1000 % iTickTime == 0);
minethd::miner_work oWork = minethd::miner_work();
pvThreads = minethd::thread_starter(oWork);
telem = new telemetry(pvThreads->size());
xmrstak::miner_work oWork = xmrstak::miner_work();
// \todo collect all backend threads
pvThreads = xmrstak::BackendConnector::thread_starter(oWork);
if(pvThreads->size()==0)
{
printer::inst()->print_msg(L1, "ERROR: No miner backend enabled.");
win_exit();
}
telem = new xmrstak::telemetry(pvThreads->size());
current_pool_id = usr_pool_id;
usr_pool = new jpsock(usr_pool_id, jconf::inst()->GetTlsSetting());
@@ -499,9 +515,9 @@ void executor::hashrate_report(std::string& out)
size_t i;
out.append("HASHRATE REPORT\n");
out.append("| ID | 2.5s | 60s | 15m |");
out.append("| ID | 10s | 60s | 15m |");
if(nthd != 1)
out.append(" ID | 2.5s | 60s | 15m |\n");
out.append(" ID | 10s | 60s | 15m |\n");
else
out.append(1, '\n');
@@ -509,7 +525,7 @@ void executor::hashrate_report(std::string& out)
{
double fHps[3];
fHps[0] = telem->calc_telemetry_data(2500, i);
fHps[0] = telem->calc_telemetry_data(10000, i);
fHps[1] = telem->calc_telemetry_data(60000, i);
fHps[2] = telem->calc_telemetry_data(900000, i);
+22 -8
View File
@@ -1,22 +1,37 @@
#pragma once
#include "thdq.hpp"
#include "msgstruct.h"
#include "telemetry.hpp"
#include "xmrstak/backend/iBackend.hpp"
#include "xmrstak/misc/environment.hpp"
#include "xmrstak/net/msgstruct.hpp"
#include <atomic>
#include <array>
#include <list>
#include <future>
class jpsock;
namespace xmrstak
{
namespace cpu
{
class minethd;
class telemetry;
} // namespace cpu
} // namepsace xmrstak
class executor
{
public:
static executor* inst()
{
if (oInst == nullptr) oInst = new executor;
return oInst;
auto& env = xmrstak::environment::inst();
if(env.pExecutor == nullptr)
env.pExecutor = new executor;
return env.pExecutor;
};
void ex_start(bool daemon) { daemon ? ex_main() : std::thread(&executor::ex_main, this).detach(); }
@@ -25,6 +40,7 @@ public:
inline void push_event(ex_event&& ev) { oEventQ.push(std::move(ev)); }
void push_timed_event(ex_event&& ev, size_t sec);
void log_result_error(std::string&& sError);
constexpr static size_t invalid_pool_id = 0;
constexpr static size_t dev_pool_id = 1;
@@ -50,8 +66,8 @@ private:
std::mutex timed_event_mutex;
thdq<ex_event> oEventQ;
telemetry* telem;
std::vector<minethd*>* pvThreads;
xmrstak::telemetry* telem;
std::vector<xmrstak::iBackend*>* pvThreads;
size_t current_pool_id;
@@ -63,7 +79,6 @@ private:
bool is_dev_time;
executor();
static executor* oInst;
void ex_main();
@@ -157,7 +172,6 @@ private:
double fHighestHps = 0.0;
void log_socket_error(std::string&& sError);
void log_result_error(std::string&& sError);
void log_result_ok(uint64_t iActualDiff);
void sched_reconnect();
+3
View File
@@ -1,5 +1,8 @@
#pragma once
#include "xmrstak/rapidjson/document.h"
#include "xmrstak/rapidjson/error/en.h"
using namespace rapidjson;
/* This macro brings rapidjson more in line with other libs */
+109
View File
@@ -0,0 +1,109 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with OpenSSL (or a modified version of that library), containing parts
* covered by the terms of OpenSSL License and SSLeay License, the licensors
* of this Program grant you additional permission to convey the resulting work.
*
*/
#include "telemetry.hpp"
#include <cmath>
#include <cstring>
#include <chrono>
namespace xmrstak
{
telemetry::telemetry(size_t iThd)
{
ppHashCounts = new uint64_t*[iThd];
ppTimestamps = new uint64_t*[iThd];
iBucketTop = new uint32_t[iThd];
for (size_t i = 0; i < iThd; i++)
{
ppHashCounts[i] = new uint64_t[iBucketSize];
ppTimestamps[i] = new uint64_t[iBucketSize];
iBucketTop[i] = 0;
memset(ppHashCounts[i], 0, sizeof(uint64_t) * iBucketSize);
memset(ppTimestamps[i], 0, sizeof(uint64_t) * iBucketSize);
}
}
double telemetry::calc_telemetry_data(size_t iLastMilisec, size_t iThread)
{
using namespace std::chrono;
uint64_t iTimeNow = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
uint64_t iEarliestHashCnt = 0;
uint64_t iEarliestStamp = 0;
uint64_t iLastestStamp = 0;
uint64_t iLastestHashCnt = 0;
bool bHaveFullSet = false;
//Start at 1, buckettop points to next empty
for (size_t i = 1; i < iBucketSize; i++)
{
size_t idx = (iBucketTop[iThread] - i) & iBucketMask; //overflow expected here
if (ppTimestamps[iThread][idx] == 0)
break; //That means we don't have the data yet
if (iLastestStamp == 0)
{
iLastestStamp = ppTimestamps[iThread][idx];
iLastestHashCnt = ppHashCounts[iThread][idx];
}
if (iTimeNow - ppTimestamps[iThread][idx] > iLastMilisec)
{
bHaveFullSet = true;
break; //We are out of the requested time period
}
iEarliestStamp = ppTimestamps[iThread][idx];
iEarliestHashCnt = ppHashCounts[iThread][idx];
}
if (!bHaveFullSet || iEarliestStamp == 0 || iLastestStamp == 0)
return nan("");
//Don't think that can happen, but just in case
if (iLastestStamp - iEarliestStamp == 0)
return nan("");
double fHashes, fTime;
fHashes = iLastestHashCnt - iEarliestHashCnt;
fTime = iLastestStamp - iEarliestStamp;
fTime /= 1000.0;
return fHashes / fTime;
}
void telemetry::push_perf_value(size_t iThd, uint64_t iHashCount, uint64_t iTimestamp)
{
size_t iTop = iBucketTop[iThd];
ppHashCounts[iThd][iTop] = iHashCount;
ppTimestamps[iThd][iTop] = iTimestamp;
iBucketTop[iThd] = (iTop + 1) & iBucketMask;
}
} // namepsace xmrstak
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include <cstdint>
#include <cstring>
namespace xmrstak
{
class telemetry
{
public:
telemetry(size_t iThd);
void push_perf_value(size_t iThd, uint64_t iHashCount, uint64_t iTimestamp);
double calc_telemetry_data(size_t iLastMilisec, size_t iThread);
private:
constexpr static size_t iBucketSize = 2 << 11; //Power of 2 to simplify calculations
constexpr static size_t iBucketMask = iBucketSize - 1;
uint32_t* iBucketTop;
uint64_t** ppHashCounts;
uint64_t** ppTimestamps;
};
} // namepsace xmrstak
View File

Some files were not shown because too many files have changed in this diff Show More