├── propPoolExploit ├── config │ ├── sys.config │ └── vm.args ├── attach.sh ├── rebar3 ├── start.sh ├── rebar.lock ├── apps │ └── propPoolExploit │ │ └── src │ │ ├── config.erl │ │ ├── propPoolExploit.app.src │ │ ├── mining_pool.erl │ │ ├── propPoolExploit_app.erl │ │ ├── multipool.erl │ │ ├── pools.erl │ │ ├── updater.erl │ │ ├── propPoolExploit_sup.erl │ │ └── talker.erl ├── .gitignore ├── README.md └── rebar.config ├── base64.h ├── AmoveoMinerGpuCuda.sln ├── poolApi.h ├── base64.cpp ├── README.md ├── poolApi.cpp ├── AmoveoMinerGpuCuda.vcxproj ├── sha256.cuh └── main.cpp /propPoolExploit/config/sys.config: -------------------------------------------------------------------------------- 1 | [ 2 | { propPoolExploit, []} 3 | ]. 4 | -------------------------------------------------------------------------------- /propPoolExploit/attach.sh: -------------------------------------------------------------------------------- 1 | ./_build/prod/rel/propPoolExploit/bin/propPoolExploit attach 2 | -------------------------------------------------------------------------------- /propPoolExploit/rebar3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zack-bitcoin/AmoveoMinerGpuCuda/master/propPoolExploit/rebar3 -------------------------------------------------------------------------------- /propPoolExploit/config/vm.args: -------------------------------------------------------------------------------- 1 | -sname propPoolExploit 2 | 3 | -setcookie propPoolExploit_cookie 4 | 5 | +K true 6 | +A30 7 | -------------------------------------------------------------------------------- /propPoolExploit/start.sh: -------------------------------------------------------------------------------- 1 | 2 | ./rebar3 compile 3 | ./rebar3 as prod release 4 | ./_build/prod/rel/propPoolExploit/bin/propPoolExploit start 5 | -------------------------------------------------------------------------------- /propPoolExploit/rebar.lock: -------------------------------------------------------------------------------- 1 | [{<<"encrypter">>, 2 | {git,"https://github.com/zack-bitcoin/encrypter", 3 | {ref,"dd702465a7d88fd12ce4a4e26786b872ad5d0530"}}, 4 | 0}, 5 | {<<"jiffy">>, 6 | {git,"https://github.com/davisp/jiffy", 7 | {ref,"1febce3ca86c5ca5d5a3618ed3d5f125bb99e4c5"}}, 8 | 0}]. 9 | -------------------------------------------------------------------------------- /propPoolExploit/apps/propPoolExploit/src/config.erl: -------------------------------------------------------------------------------- 1 | -module(config). 2 | -compile(export_all). 3 | 4 | pools() -> 5 | [{amoveopool, "http://70.133.222.59:8080"}, 6 | {zack, "http://159.65.120.84:8080"}]. 7 | pool_ids() -> 8 | lists:map(fun(X) -> element(1, X) end, 9 | pools()). 10 | 11 | -------------------------------------------------------------------------------- /propPoolExploit/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .edts 3 | *.iml 4 | _build 5 | /rel/ 6 | *.db 7 | *~ 8 | .#* 9 | \#* 10 | .rebar 11 | erl_crash.dump 12 | keys_backup 13 | lib/ 14 | bin/ 15 | .Python 16 | include/ 17 | *.pyc 18 | nosetests.xml 19 | pip-selfcheck.json 20 | config/*/sys.config 21 | man 22 | compile_commands.json 23 | -------------------------------------------------------------------------------- /propPoolExploit/README.md: -------------------------------------------------------------------------------- 1 | propPoolExploit 2 | ===== 3 | 4 | First you need to install the miner for your system. [read this](../README.md) 5 | 6 | then you can do these things in the current directory 7 | 8 | turn it on: 9 | ``` 10 | sh start.sh 11 | ``` 12 | 13 | attach to the running process: 14 | ``` 15 | sh attach.sh 16 | ``` -------------------------------------------------------------------------------- /base64.h: -------------------------------------------------------------------------------- 1 | // 2 | // base64 encoding and decoding with C++. 3 | // Version: 1.01.00 4 | // 5 | 6 | #ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A 7 | #define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A 8 | 9 | #include 10 | 11 | std::string base64_encode(unsigned char const*, unsigned int len); 12 | std::string base64_decode(std::string const& s); 13 | 14 | #endif /* BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A */ -------------------------------------------------------------------------------- /propPoolExploit/apps/propPoolExploit/src/propPoolExploit.app.src: -------------------------------------------------------------------------------- 1 | {application, propPoolExploit, 2 | [{description, "An OTP application"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {mod, { propPoolExploit_app, []}}, 6 | {applications, 7 | [kernel, 8 | stdlib, 9 | ssl, 10 | inets, 11 | jiffy, 12 | encrypter 13 | ]}, 14 | {env,[]}, 15 | {modules, []}, 16 | 17 | {maintainers, []}, 18 | {licenses, ["Apache 2.0"]}, 19 | {links, []} 20 | ]}. 21 | -------------------------------------------------------------------------------- /propPoolExploit/apps/propPoolExploit/src/mining_pool.erl: -------------------------------------------------------------------------------- 1 | -module(mining_pool). 2 | -behaviour(gen_server). 3 | -export([start_link/2,code_change/3,handle_call/3,handle_cast/2,handle_info/2,init/1,terminate/2, 4 | read/1, write/2]). 5 | init(Address) -> {ok, updater:new_pool(Address)}. 6 | start_link(Pool, ID) -> gen_server:start_link({global, ID}, ?MODULE, Pool, []). 7 | code_change(_OldVsn, State, _Extra) -> {ok, State}. 8 | terminate(_, _) -> io:format("died!"), ok. 9 | handle_info(_, X) -> {noreply, X}. 10 | handle_cast({write, Val}, _) -> 11 | {noreply, Val}; 12 | handle_cast(_, X) -> {noreply, X}. 13 | handle_call(_, _From, X) -> {reply, X, X}. 14 | read(X) -> gen_server:call({global, X}, read). 15 | write(ID, Val) -> gen_server:cast({global, ID}, {write, Val}). 16 | 17 | -------------------------------------------------------------------------------- /propPoolExploit/apps/propPoolExploit/src/propPoolExploit_app.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc propPoolExploit public API 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(propPoolExploit_app). 7 | 8 | -behaviour(application). 9 | 10 | %% Application callbacks 11 | -export([start/2, stop/1]). 12 | 13 | %%==================================================================== 14 | %% API 15 | %%==================================================================== 16 | 17 | start(_StartType, _StartArgs) -> 18 | inets:start(), 19 | propPoolExploit_sup:start_link(). 20 | 21 | %%-------------------------------------------------------------------- 22 | stop(_State) -> 23 | ok. 24 | 25 | %%==================================================================== 26 | %% Internal functions 27 | %%==================================================================== 28 | -------------------------------------------------------------------------------- /AmoveoMinerGpuCuda.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AmoveoMinerGpuCuda", "AmoveoMinerGpuCuda.vcxproj", "{04611E5F-FEC5-4CB8-8F87-CB09C17245A5}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {04611E5F-FEC5-4CB8-8F87-CB09C17245A5}.Debug|x64.ActiveCfg = Debug|x64 15 | {04611E5F-FEC5-4CB8-8F87-CB09C17245A5}.Debug|x64.Build.0 = Debug|x64 16 | {04611E5F-FEC5-4CB8-8F87-CB09C17245A5}.Release|x64.ActiveCfg = Release|x64 17 | {04611E5F-FEC5-4CB8-8F87-CB09C17245A5}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /propPoolExploit/rebar.config: -------------------------------------------------------------------------------- 1 | %{erl_opts, [native, {hipe, [verbose]}, warnings_as_errors, debug_info]}. 2 | {deps, [ 3 | {jiffy, "0.14.8", {git, "https://github.com/davisp/jiffy", {tag, "0.14.8"}}}, 4 | {encrypter, "1", {git, "https://github.com/zack-bitcoin/encrypter", {tag, "master"}}} 5 | ]}. 6 | 7 | {relx, [{release, { propPoolExploit, "0.1.0" }, 8 | [propPoolExploit, 9 | sasl]}, 10 | 11 | {sys_config, "./config/sys.config"}, 12 | {vm_args, "./config/vm.args"}, 13 | 14 | {dev_mode, true}, 15 | {include_erts, false}, 16 | 17 | {extended_start_script, true}] 18 | }. 19 | 20 | {profiles, [{prod, [{relx, [{dev_mode, false}, 21 | {include_erts, true}]}] 22 | }] 23 | }. 24 | 25 | {overrides, 26 | [{override, jiffy, [ 27 | {plugins, [pc]}, 28 | {artifacts, ["priv/jiffy.so"]}, 29 | {provider_hooks, [ 30 | {post, 31 | [ 32 | {compile, {pc, compile}}, 33 | {clean, {pc, clean}} 34 | ] 35 | }] 36 | } 37 | ]} 38 | ]}. -------------------------------------------------------------------------------- /propPoolExploit/apps/propPoolExploit/src/multipool.erl: -------------------------------------------------------------------------------- 1 | -module(multipool). 2 | -export([test/0]). 3 | 4 | test() -> 5 | %Data = <<"[\"height\"]">>, 6 | P = pools:read(), 7 | pool_height(hd(P)). 8 | pool_height(Pool) -> 9 | PoolLoc = pools:location(Pool), 10 | talker({height}, PoolLoc, 1). 11 | 12 | talk_helper2(Data, Peer) -> 13 | httpc:request(post, {Peer, [], "application/octet-stream", iolist_to_binary(Data)}, [{timeout, 3000}], []). 14 | talker(_Data, _Peer, 0) -> throw("talk helper failed"); 15 | talker(Data1, Peer, N) -> 16 | Data = packer:pack(Data1), 17 | case talk_helper2(Data, Peer) of 18 | {ok, {_Status, _Headers, []}} -> 19 | io:fwrite("server gave confusing response\n"), 20 | talker(Data, Peer, N-1); 21 | {ok, {_, _, R}} -> R; 22 | %{error, _} -> 23 | E -> 24 | io:fwrite("\nIf you are running a solo-mining node, then this error may have happened because you need to turn on and sync your Amoveo node before you can mine. You can get it here: https://github.com/zack-bitcoin/amoveo \n If this error happens while connected to the public mining node, then it can probably be safely ignored."), 25 | talker(Data, Peer, N-1) 26 | end. 27 | -------------------------------------------------------------------------------- /propPoolExploit/apps/propPoolExploit/src/pools.erl: -------------------------------------------------------------------------------- 1 | -module(pools). 2 | -behaviour(gen_server). 3 | -export([start_link/0,code_change/3,handle_call/3,handle_cast/2,handle_info/2,init/1,terminate/2, 4 | location/1, 5 | read/0]). 6 | -record(pool, {location, header_height, block_height, time}). 7 | -define(REFRESH, 3000).%How often in miliseconds to update data from the mining pools. 8 | location(P) -> P#pool.location. 9 | 10 | init(ok) -> {ok, {#pool{location = "http://176.9.84.75:8080"}, 11 | #pool{location = "http://159.65.120.84:8080"}}}. 12 | start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, ok, []). 13 | code_change(_OldVsn, State, _Extra) -> {ok, State}. 14 | terminate(_, _) -> io:format("died!"), ok. 15 | handle_info(_, X) -> {noreply, X}. 16 | handle_cast({write, D}, _) -> {noreply, D}; 17 | handle_cast(_, X) -> {noreply, X}. 18 | handle_call(height, _From, X) -> 19 | {Height, X2} = height_internal(tuple_to_list(X), 0), 20 | {reply, Height, X2}; 21 | handle_call(_, _From, X) -> {reply, X, X}. 22 | 23 | read() -> gen_server:call(?MODULE, read). 24 | write(D) -> gen_server:call(?MODULE, {write, D}). 25 | height() -> gen_server:call(?MODULE, height). 26 | 27 | height_internal([], N) -> N; 28 | height_internal([H|T], N) -> 29 | X = if 30 | H#pool.header_height == H#pool.block_height -> 31 | max(N, H#pool.header_height); 32 | true -> N 33 | end, 34 | height_internal(T, X). 35 | 36 | -------------------------------------------------------------------------------- /poolApi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | using namespace utility; // Common utilities like string conversions 9 | 10 | void mySleep(unsigned milliseconds); 11 | 12 | class WorkData 13 | { 14 | private: 15 | unsigned char ctx[0x70]; 16 | bool newWork = false; 17 | 18 | public: 19 | vector bhash; 20 | vector nonce; 21 | int blockDifficulty; 22 | int shareDifficulty; 23 | 24 | std::mutex mutexNewWork; 25 | //std::mutex mutexCtx; 26 | 27 | public: 28 | WorkData() { 29 | bhash = vector(32); 30 | nonce = vector(15); 31 | } 32 | 33 | bool HasNewWork() { return newWork; } 34 | void clearNewWork() 35 | { 36 | mutexNewWork.lock(); 37 | newWork = false; 38 | mutexNewWork.unlock(); 39 | } 40 | 41 | void getCtx(unsigned char * pCtx) { 42 | //mutexCtx.lock(); 43 | memcpy(pCtx, ctx, 0x70); 44 | //mutexCtx.unlock(); 45 | } 46 | void setCtx(unsigned char * pCtx) 47 | { 48 | //mutexCtx.lock(); 49 | memcpy(ctx, pCtx, 0x70); 50 | //mutexCtx.unlock(); 51 | mutexNewWork.lock(); 52 | newWork = true; 53 | mutexNewWork.unlock(); 54 | } 55 | 56 | 57 | 58 | }; 59 | 60 | class PoolApi 61 | { 62 | public: 63 | void GetWork(string_t poolUrl, WorkData * pMinerThreadData, string minerPublicKeyBase64); 64 | void SubmitWork(string_t poolUrl, string nonceBase64, string minerPublicKeyBase64); 65 | 66 | 67 | }; 68 | -------------------------------------------------------------------------------- /propPoolExploit/apps/propPoolExploit/src/updater.erl: -------------------------------------------------------------------------------- 1 | -module(updater). 2 | -behaviour(gen_server). 3 | -export([start_link/2,code_change/3,handle_call/3,handle_cast/2,handle_info/2,init/1,terminate/2, 4 | update/1, new_pool/1, update_all/0]). 5 | -define(REFRESH, 3000).%How often in miliseconds to update data from the mining pools. 6 | -record(pool, {location, header_height = 0, block_height = 0, time = {0,0,0}}). 7 | init(ID) -> {ok, ID}. 8 | start_link(A, ID) -> gen_server:start_link({global, ID}, ?MODULE, A, []). 9 | code_change(_OldVsn, State, _Extra) -> {ok, State}. 10 | terminate(_, _) -> io:format("died!"), ok. 11 | handle_info(_, X) -> {noreply, X}. 12 | handle_cast(update, ID) -> 13 | X = mining_pool:read(ID), 14 | T = X#pool.time, 15 | L = X#pool.location, 16 | TD = timer:now_diff(erlang:timestamp(), T), 17 | X2 = if 18 | TD > (?REFRESH * 1000) -> 19 | Msg = {height},%block:height 20 | BlockHeight = element(2, talker:talk(Msg, L)), 21 | Msg2 = {header},%header:top 22 | HeaderHeight = element(2, (element(2, talker:talk(Msg2, L)))), 23 | X#pool{time = erlang:timestamp(), 24 | header_height = max(X#pool.header_height, 25 | HeaderHeight), 26 | block_height = max(X#pool.block_height, 27 | BlockHeight)}; 28 | true -> 29 | X 30 | end, 31 | mining_pool:write(ID, X2), 32 | {noreply, ID}; 33 | handle_cast(_, X) -> {noreply, X}. 34 | handle_call(_, _From, X) -> {reply, X, X}. 35 | update(N) -> 36 | ID2 = list_to_atom(atom_to_list(N) ++ "_updater"), 37 | gen_server:cast({global, ID2}, update). 38 | update_all() -> 39 | lists:map(fun(X) -> update(X) end, 40 | config:pool_ids()). 41 | 42 | new_pool(L) -> #pool{location = L}. 43 | -------------------------------------------------------------------------------- /propPoolExploit/apps/propPoolExploit/src/propPoolExploit_sup.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc propPoolExploit top level supervisor. 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(propPoolExploit_sup). 7 | 8 | -behaviour(supervisor). 9 | 10 | %% API 11 | -export([start_link/0]). 12 | 13 | %% Supervisor callbacks 14 | -export([init/1]). 15 | -define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}). 16 | -define(SERVER, ?MODULE). 17 | -define(keys, []). 18 | child_killer([]) -> []; 19 | child_killer([H|T]) -> 20 | supervisor:terminate_child(testnet_sup, H), 21 | child_killer(T). 22 | stop() -> child_killer(?keys). 23 | child_maker([]) -> []; 24 | child_maker([H|T]) -> [?CHILD(H, worker)|child_maker(T)]. 25 | 26 | %%==================================================================== 27 | %% API functions 28 | %%==================================================================== 29 | 30 | start_link() -> 31 | supervisor:start_link({local, ?SERVER}, ?MODULE, []). 32 | 33 | %%==================================================================== 34 | %% Supervisor callbacks 35 | %%==================================================================== 36 | update_children([]) -> []; 37 | update_children([{ID, _}|T]) -> 38 | [update_child(ID)|update_children(T)]. 39 | update_child(ID) -> 40 | ID2 = list_to_atom(atom_to_list(ID) ++ "_updater"), 41 | {ID2, {updater, start_link, [ID, ID2]}, permanent, 5000, worker, [updater]}. 42 | pool_children([]) -> []; 43 | pool_children([{ID, Location}|T]) -> 44 | [pool_child(ID, Location)|pool_children(T)]. 45 | pool_child(ID, Address) -> {ID, {mining_pool, start_link, [Address, ID]}, permanent, 5000, worker, [mining_pool]}. 46 | %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} 47 | init([]) -> 48 | Children = child_maker(?keys), 49 | PC = pool_children(config:pools()), 50 | UC = update_children(config:pools()), 51 | {ok, { {one_for_all, 50000, 1}, PC ++ UC} }. 52 | -------------------------------------------------------------------------------- /base64.cpp: -------------------------------------------------------------------------------- 1 | #include "base64.h" 2 | #include 3 | 4 | static const std::string base64_chars = 5 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 6 | "abcdefghijklmnopqrstuvwxyz" 7 | "0123456789+/"; 8 | 9 | 10 | static inline bool is_base64(unsigned char c) { 11 | return (isalnum(c) || (c == '+') || (c == '/')); 12 | } 13 | 14 | std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { 15 | std::string ret; 16 | int i = 0; 17 | int j = 0; 18 | unsigned char char_array_3[3]; 19 | unsigned char char_array_4[4]; 20 | 21 | while (in_len--) { 22 | char_array_3[i++] = *(bytes_to_encode++); 23 | if (i == 3) { 24 | char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; 25 | char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); 26 | char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); 27 | char_array_4[3] = char_array_3[2] & 0x3f; 28 | 29 | for (i = 0; (i <4); i++) 30 | ret += base64_chars[char_array_4[i]]; 31 | i = 0; 32 | } 33 | } 34 | 35 | if (i) 36 | { 37 | for (j = i; j < 3; j++) 38 | char_array_3[j] = '\0'; 39 | 40 | char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; 41 | char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); 42 | char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); 43 | 44 | for (j = 0; (j < i + 1); j++) 45 | ret += base64_chars[char_array_4[j]]; 46 | 47 | while ((i++ < 3)) 48 | ret += '='; 49 | 50 | } 51 | 52 | return ret; 53 | 54 | } 55 | 56 | std::string base64_decode(std::string const& encoded_string) { 57 | int in_len = encoded_string.size(); 58 | int i = 0; 59 | int j = 0; 60 | int in_ = 0; 61 | unsigned char char_array_4[4], char_array_3[3]; 62 | std::string ret; 63 | 64 | while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { 65 | char_array_4[i++] = encoded_string[in_]; in_++; 66 | if (i == 4) { 67 | for (i = 0; i <4; i++) 68 | char_array_4[i] = base64_chars.find(char_array_4[i]); 69 | 70 | char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); 71 | char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); 72 | char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; 73 | 74 | for (i = 0; (i < 3); i++) 75 | ret += char_array_3[i]; 76 | i = 0; 77 | } 78 | } 79 | 80 | if (i) { 81 | for (j = 0; j < i; j++) 82 | char_array_4[j] = base64_chars.find(char_array_4[j]); 83 | 84 | char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); 85 | char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); 86 | 87 | for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; 88 | } 89 | 90 | return ret; 91 | } -------------------------------------------------------------------------------- /propPoolExploit/apps/propPoolExploit/src/talker.erl: -------------------------------------------------------------------------------- 1 | -module(talker). 2 | -export([talk/2, talk/3, talk_timeout/3]). 3 | 4 | -define(RETRY, 3). 5 | 6 | talk_timeout(Msg, {IP, Port}, X) -> 7 | P = build_string_peer(IP, Port), 8 | talk_helper(Msg, P, ?RETRY, X). 9 | 10 | talk(Msg, {IP, Port}) -> 11 | talk(Msg, build_string_peer(IP, Port)); 12 | 13 | talk(Msg, Peer) -> 14 | talk_helper(Msg, Peer, ?RETRY, 20000). 15 | 16 | talk(Msg, IP, Port) -> 17 | talk(Msg, build_string_peer(IP, Port)). 18 | ip2string2(X) -> 19 | (integer_to_list(X)) ++ ("."). 20 | ip2string([A,B,C,D]) -> 21 | ip2string({A,B,C,D}); 22 | ip2string({A,B,C,D}) -> 23 | ip2string2(A) ++ 24 | ip2string2(B) ++ 25 | ip2string2(C) ++ 26 | integer_to_list(D). 27 | build_string_peer(IP, Port) -> 28 | T = ip2string(IP), 29 | P = integer_to_list(Port), 30 | "http://" ++ T ++ ":" ++ P ++ "/". 31 | 32 | talk_helper(_, _, 0, _) -> 33 | io:fwrite("talk helper fail\n"), 34 | bad_peer; 35 | %{error, failed_connect}; 36 | talk_helper(Msg, Peer, N, TimeOut) -> 37 | PM = packer:pack(Msg), 38 | %io:fwrite("sending message "), 39 | %io:fwrite(PM), 40 | %io:fwrite("\n"), 41 | %timer:sleep(500), 42 | Msg = packer:unpack(PM), 43 | case httpc:request(post, {Peer, [], "application/octet-stream", iolist_to_binary(PM)}, [{timeout, TimeOut}], []) of 44 | {ok, {{_, 500, _}, _Headers, []}} -> 45 | io:fwrite("server crashed.\n"), 46 | io:fwrite(element(1, Msg)), 47 | io:fwrite(" \n"), 48 | bad_peer; 49 | %talk_helper(Msg, Peer, 0, TimeOut); 50 | {ok, {Status, _Headers, []}} -> 51 | io:fwrite("talk_helper weird response \n"), 52 | io:fwrite(packer:pack(Status)), 53 | talk_helper(Msg, Peer, N - 1, TimeOut); 54 | {ok, {_, _, R}} -> 55 | %io:fwrite("talker peer is "), 56 | %io:fwrite(Peer), 57 | %io:fwrite("\n"), 58 | %io:fwrite("talker msg is "), 59 | %io:fwrite(packer:pack(Msg)), 60 | %io:fwrite("\n"), 61 | %io:fwrite("talker response is "), 62 | %io:fwrite(R), 63 | %io:fwrite("\n"), 64 | DoubleOK = packer:pack({ok, ok}), 65 | if 66 | R == DoubleOK -> 0; 67 | true -> 68 | packer:unpack(R) 69 | end; 70 | {error, socket_closed_remotely} -> 71 | io:fwrite("talk_helper socket closed remotely \n"), 72 | talk_helper(Msg, Peer, N - 1, TimeOut); 73 | {error, timeout} -> 74 | io:fwrite("talk_helper timeout \n"), 75 | io:fwrite(element(1, Msg)), 76 | io:fwrite("\n"), 77 | talk_helper(Msg, Peer, N - 1, TimeOut); 78 | {error, failed_connect} -> 79 | io:fwrite("talk_helper failed_connect 0 \n"), 80 | bad_peer; 81 | %talk_helper(Msg, Peer, N - 1, TimeOut); 82 | {error, {failed_connect, _}} -> 83 | io:fwrite("talk_helper failed_connect 1 \n"), 84 | %io:fwrite(PM), 85 | bad_peer; 86 | %talk_helper(Msg, Peer, N - 1, TimeOut); 87 | X -> io:fwrite("talk helper unexpected error"), 88 | io:fwrite(X), 89 | error 90 | end. 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AmoveoMinerGpuCuda 2 | Amoveo Cryptocurrency Miner for Gpu work to be used with [AmoveoPool2.com](http://AmoveoPool2.com). 3 | 4 | [for the prop-pool-exploit version](propPoolExploit/README.md) 5 | 6 | Tested Gpu Speeds: 7 | 8 | * Tesla V100: ??? Mh/s - Suggested BlockSize: 1024, Numblocks: 64 9 | * Tesla P100: ??? Mh/s - Suggested BlockSize: 192, Numblocks: 168 10 | * GTX1080 TI: 2900 Mh/s - Suggested BlockSize: 96, Numblocks: 168 11 | * GTX1060 6GB: 1300 Mh/s - Suggested BlockSize: 64 12 | * GTX1050: 550 Mh/s - Suggested BlockSize: 64 13 | * Tesla K80: 451 Mh/s - Suggested BlockSize: 128 14 | * 750TI: 323 Mh/s - Suggested BlockSize: 32 15 | 16 | Default BlockSize is 64. 17 | Default NumBlocks is 96. 18 | Default SuffixMax is 65536. 19 | 20 | * Try various BlockSize setting values. Optimal setting for BlockSize is very personal to your system. Try BlockSize values like 96, 64, 32, or 128. A higher BlockSize is almost always better, but too high will crash the miner. 21 | * If you get too much OS lag, reduce the SuffixMax setting (at the cost of a some hash rate). 22 | * If your Memory Controller Load is constantly at 100%, you may want to try lowering your NumBlocks. 23 | 24 | Best Settings from My Tests: 25 | * Gtx1060: BlockSize=64, NumBlocks=96 26 | * Gtx1050: BlockSize=64, NumBlocks=90 27 | * Tesla K80: BlockSize=128, NumBlocks=128 28 | * 750Ti: BlockSize=32, NumBlocks=64 29 | 30 | 31 | 32 | ## Windows 33 | 34 | ### Run Dependencies 35 | * Install Visual Studio 2015 (Community Edition is free.) 36 | * Install Cuda 9.1 37 | 38 | ### Releases 39 | 40 | [Latest pre-built releases are here](https://github.com/Mandelhoff/AmoveoMinerGpuCuda/releases) 41 | 42 | 43 | ### Run 44 | 45 | Example Usage: 46 | ``` 47 | AmoveoMinerGpuCuda.exe BPA3r0XDT1V8W4sB14YKyuu/PgC6ujjYooVVzq1q1s5b6CAKeu9oLfmxlplcPd+34kfZ1qx+Dwe3EeoPu0SpzcI= 48 | ``` 49 | 50 | Advanced Usage Template: 51 | ``` 52 | AmoveoMinerGpuCuda.exe 53 | ``` 54 | * CudaDeviceId is optional an defaults to 0. 55 | * BlockSize is optional and defaults to 64. 56 | * NumBlocks is optional and defaults to 96. 57 | * RandomSeed is optional. Set this if you want multiple miners using the same address to avoid nonce collisions. 58 | * SuffixMax optional and defaults to 65536. Do NOT use anything higher than 65536. Lower numbers reduce OS lag and will reduce hash rate by a few percent. 59 | * PoolUrl is optional and defaults to http://amoveopool.com/work 60 | 61 | 62 | ### Build 63 | The Windows releases are built with Visual Studio 2015 with Cuda, RestCPP, boost, and openSSL. 64 | 65 | 66 | ## Linux 67 | 68 | ### Install dependencies 69 | 70 | ``` 71 | sudo apt-get install libcpprest-dev libncurses5-dev libssl-dev unixodbc-dev g++ git 72 | ``` 73 | 74 | ### Install CUDA9.1 75 | 76 | ``` 77 | wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_9.1.85-1_amd64.deb 78 | sudo apt-key adv —fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub 79 | sudo dpkg -i cuda-repo-ubuntu1604_9.1.85-1_amd64.deb 80 | sudo apt update 81 | sudo apt install cuda -y 82 | ``` 83 | 84 | Add these lines to the end of `~/.bashrc` 85 | 86 | ``` 87 | export CUDA_HOME=/usr/local/cuda 88 | export PATH="/usr/local/cuda/bin:$PATH" 89 | export LD_LIBRARY_PATH="/usr/local/cuda/lib64:$LD_LIBRARY_PATH" 90 | ``` 91 | 92 | ### Build 93 | 94 | ``` 95 | git clone https://github.com/Mandelhoff/AmoveoMinerGpuCuda.git 96 | cd ./AmoveoMinerGpuCuda 97 | sh build.sh 98 | ``` 99 | 100 | Donations are welcome: 101 | * Amoveo: BGH+3P768A9cSNR3GLSRXgsokSL/Jdbm+rOJogbgiPxq8M+J2R4nVxZ+Hj6WdI4rMsq6nPzkMh77WGBCMx89HUM= 102 | -------------------------------------------------------------------------------- /poolApi.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // HTTP server 4 | #include // JSON library 5 | #include // URI library 6 | 7 | #include "poolApi.h" 8 | #include "base64.h" 9 | 10 | #ifdef _WIN32 11 | #include 12 | #include 13 | 14 | void mySleep(unsigned milliseconds) 15 | { 16 | Sleep(milliseconds); 17 | } 18 | #else 19 | #include 20 | #include 21 | 22 | void mySleep(unsigned milliseconds) 23 | { 24 | usleep(milliseconds * 1000); // takes microseconds 25 | } 26 | #endif 27 | 28 | using namespace std; 29 | using namespace std::chrono; 30 | 31 | using namespace utility; // Common utilities like string conversions 32 | using namespace web; // Common features like URIs. 33 | using namespace web::http; // Common HTTP functionality 34 | using namespace web::http::client; // HTTP client features 35 | using namespace concurrency::streams; // Asynchronous streams 36 | using namespace web::http::experimental::listener; // HTTP server 37 | using namespace web::json; // JSON library 38 | 39 | wstring successResponse = L"[-6,102,111,117,110,100,32,119,111,114,107]"; 40 | 41 | void PoolApi::SubmitWork(string_t poolUrl, string nonceBase64, string minerPublicKeyBase64) 42 | { 43 | http_client client(poolUrl); 44 | http_request request(methods::POST); 45 | std::stringstream body; 46 | body << "[\"work\",\"" << nonceBase64 << "\",\"" << minerPublicKeyBase64 << "\"]"; 47 | request.set_body(body.str()); 48 | 49 | try 50 | { 51 | http_response response = client.request(request).get(); 52 | if (response.status_code() == status_codes::OK) { 53 | // Response data comes in as application/octet-stream, so extract_json throws an exception 54 | // Need to use extract_vector and then convert to string and then to json 55 | std::vector responseData = response.extract_vector().get(); 56 | 57 | wstring responseString(responseData.begin(), responseData.end()); 58 | 59 | if (successResponse.compare(responseString) != 0) { 60 | wcout << "Info: " << responseString << endl; 61 | } 62 | } else { 63 | wcout << "ERROR: SubmitWork response code: " << response.status_code() << endl; 64 | } 65 | } 66 | catch (...) { 67 | wcout << "ERROR: SubmitWork Exception..." << endl; 68 | } 69 | return; 70 | } 71 | 72 | void PoolApi::GetWork(string_t poolUrl, WorkData * pMinerThreadData, string minerPublicKeyBase64) 73 | { 74 | bool success = false; 75 | do { 76 | try { 77 | http_client client(poolUrl); 78 | http_request request(methods::POST); 79 | std::stringstream body; 80 | body << "[\"mining_data\",\"" << minerPublicKeyBase64 << "\"]"; 81 | request.set_body(body.str()); 82 | //wcout << request.to_string(); 83 | 84 | http_response response = client.request(request).get(); 85 | if (response.status_code() == status_codes::OK) 86 | { 87 | // Response data comes in as application/octet-stream, so extract_json throws an exception 88 | // Need to use extract_vector and then convert to string and then to json 89 | std::vector responseData = response.extract_vector().get(); 90 | 91 | string responseString(responseData.begin(), responseData.end()); 92 | 93 | json::value jsonResponse = json::value::parse(responseString); 94 | json::array dataArray = jsonResponse.as_array(); 95 | 96 | string wBHhashBase64(dataArray[1].at(1).as_string().c_str()); 97 | string bhashBase64(wBHhashBase64.begin(), wBHhashBase64.end()); 98 | string bhashString = base64_decode(bhashBase64); 99 | vector bhash(bhashString.begin(), bhashString.end()); 100 | pMinerThreadData->bhash = bhash; 101 | 102 | int blockDifficulty = dataArray[1].at(2).as_integer(); 103 | pMinerThreadData->blockDifficulty = blockDifficulty; 104 | 105 | int shareDifficulty = dataArray[1].at(3).as_integer(); 106 | pMinerThreadData->shareDifficulty = shareDifficulty; 107 | 108 | success = true; 109 | } 110 | else { 111 | wcout << "ERROR: GetWork: " << response.status_code() << " Sleep and retry..." << endl; 112 | mySleep(3000); 113 | } 114 | } 115 | catch (...) { 116 | wcout << "ERROR: GetWork failed. Sleep and retry..." << endl; 117 | mySleep(3000); 118 | } 119 | } while (!success); 120 | 121 | return; 122 | } 123 | 124 | -------------------------------------------------------------------------------- /AmoveoMinerGpuCuda.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {04611E5F-FEC5-4CB8-8F87-CB09C17245A5} 15 | amoveo-miner 16 | 17 | 18 | 19 | Application 20 | true 21 | MultiByte 22 | v140 23 | 24 | 25 | Application 26 | false 27 | true 28 | MultiByte 29 | v140 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | 47 | Level3 48 | Disabled 49 | WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 50 | 51 | 52 | true 53 | Console 54 | cudart.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 55 | 56 | 57 | echo copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 58 | copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 59 | 60 | 61 | 64 62 | 63 | 64 | compute_30,sm_30 65 | -lineinfo %(AdditionalOptions) 66 | 67 | 68 | 69 | 70 | Level3 71 | MaxSpeed 72 | true 73 | true 74 | WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 75 | 76 | 77 | true 78 | true 79 | true 80 | Console 81 | cudart.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 82 | 83 | 84 | echo copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 85 | copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 86 | 87 | 88 | 64 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /sha256.cuh: -------------------------------------------------------------------------------- 1 | #ifndef SHA256_H 2 | #define SHA256_H 3 | 4 | #include 5 | 6 | 7 | /****************************** MACROS ******************************/ 8 | #define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest 9 | 10 | #define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b)))) 11 | #define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b)))) 12 | 13 | #define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) 14 | #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 15 | #define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22)) 16 | #define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25)) 17 | #define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3)) 18 | #define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10)) 19 | 20 | #define checkCudaErrors(x) \ 21 | { \ 22 | cudaGetLastError(); \ 23 | x; \ 24 | cudaError_t err = cudaGetLastError(); \ 25 | if (err != cudaSuccess) \ 26 | printf("GPU: cudaError %d (%s)\n", err, cudaGetErrorString(err)); \ 27 | } 28 | /**************************** DATA TYPES ****************************/ 29 | typedef unsigned char BYTE; // 8-bit byte 30 | typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines 31 | 32 | typedef struct { 33 | BYTE data[64]; 34 | WORD datalen; 35 | unsigned long long bitlen; 36 | WORD state[8]; 37 | } SHA256_CTX; 38 | 39 | __constant__ WORD dev_k[64]; 40 | 41 | static const WORD host_k[64] = { 42 | 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, 43 | 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, 44 | 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, 45 | 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, 46 | 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, 47 | 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, 48 | 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, 49 | 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 50 | }; 51 | 52 | /*********************** FUNCTION DECLARATIONS **********************/ 53 | char * print_sha(BYTE * buff); 54 | __device__ void sha256_init(SHA256_CTX *ctx); 55 | __device__ void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len); 56 | __device__ void sha256_final(SHA256_CTX *ctx, BYTE hash[]); 57 | 58 | __device__ void mycpy12(uint32_t *d, const uint32_t *s) { 59 | #pragma unroll 3 60 | for (int k = 0; k < 3; k++) d[k] = s[k]; 61 | } 62 | 63 | __device__ void mycpy16(uint32_t *d, const uint32_t *s) { 64 | #pragma unroll 4 65 | for (int k = 0; k < 4; k++) d[k] = s[k]; 66 | } 67 | 68 | __device__ void mycpy32(uint32_t *d, const uint32_t *s) { 69 | #pragma unroll 8 70 | for (int k = 0; k < 8; k++) d[k] = s[k]; 71 | } 72 | 73 | __device__ void mycpy44(uint32_t *d, const uint32_t *s) { 74 | #pragma unroll 11 75 | for (int k = 0; k < 11; k++) d[k] = s[k]; 76 | } 77 | 78 | __device__ void mycpy48(uint32_t *d, const uint32_t *s) { 79 | #pragma unroll 12 80 | for (int k = 0; k < 12; k++) d[k] = s[k]; 81 | } 82 | 83 | __device__ void mycpy64(uint32_t *d, const uint32_t *s) { 84 | #pragma unroll 16 85 | for (int k = 0; k < 16; k++) d[k] = s[k]; 86 | } 87 | 88 | __device__ void sha256_transform(SHA256_CTX *ctx, const BYTE data[]) 89 | { 90 | WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; 91 | //WORD S[8]; 92 | 93 | //mycpy32(S, ctx->state); 94 | 95 | #pragma unroll 16 96 | for (i = 0, j = 0; i < 16; ++i, j += 4) 97 | m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); 98 | 99 | #pragma unroll 64 100 | for (; i < 64; ++i) 101 | m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; 102 | 103 | a = ctx->state[0]; 104 | b = ctx->state[1]; 105 | c = ctx->state[2]; 106 | d = ctx->state[3]; 107 | e = ctx->state[4]; 108 | f = ctx->state[5]; 109 | g = ctx->state[6]; 110 | h = ctx->state[7]; 111 | 112 | #pragma unroll 64 113 | for (i = 0; i < 64; ++i) { 114 | t1 = h + EP1(e) + CH(e, f, g) + dev_k[i] + m[i]; 115 | t2 = EP0(a) + MAJ(a, b, c); 116 | h = g; 117 | g = f; 118 | f = e; 119 | e = d + t1; 120 | d = c; 121 | c = b; 122 | b = a; 123 | a = t1 + t2; 124 | } 125 | 126 | ctx->state[0] += a; 127 | ctx->state[1] += b; 128 | ctx->state[2] += c; 129 | ctx->state[3] += d; 130 | ctx->state[4] += e; 131 | ctx->state[5] += f; 132 | ctx->state[6] += g; 133 | ctx->state[7] += h; 134 | } 135 | 136 | __device__ void sha256_init(SHA256_CTX *ctx) 137 | { 138 | ctx->datalen = 0; 139 | ctx->bitlen = 0; 140 | ctx->state[0] = 0x6a09e667; 141 | ctx->state[1] = 0xbb67ae85; 142 | ctx->state[2] = 0x3c6ef372; 143 | ctx->state[3] = 0xa54ff53a; 144 | ctx->state[4] = 0x510e527f; 145 | ctx->state[5] = 0x9b05688c; 146 | ctx->state[6] = 0x1f83d9ab; 147 | ctx->state[7] = 0x5be0cd19; 148 | } 149 | 150 | __device__ void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len) 151 | { 152 | WORD i; 153 | 154 | // for each byte in message 155 | for (i = 0; i < len; ++i) { 156 | // ctx->data == message 512 bit chunk 157 | ctx->data[ctx->datalen] = data[i]; 158 | ctx->datalen++; 159 | if (ctx->datalen == 64) { 160 | sha256_transform(ctx, ctx->data); 161 | ctx->bitlen += 512; 162 | ctx->datalen = 0; 163 | } 164 | } 165 | } 166 | 167 | __device__ void sha256_updateAmoveoCtxTrailer(SHA256_CTX *ctx) 168 | { 169 | ctx->data[55] = 0x80; 170 | 171 | ctx->bitlen = 440; 172 | ctx->data[63] = ctx->bitlen; 173 | ctx->data[62] = ctx->bitlen >> 8; 174 | ctx->data[61] = ctx->bitlen >> 16; 175 | ctx->data[60] = ctx->bitlen >> 24; 176 | ctx->data[59] = ctx->bitlen >> 32; 177 | ctx->data[58] = ctx->bitlen >> 40; 178 | ctx->data[57] = ctx->bitlen >> 48; 179 | ctx->data[56] = ctx->bitlen >> 56; 180 | } 181 | 182 | __device__ void sha256_updateAmoveoSpecial(SHA256_CTX *ctx, const BYTE data[]) 183 | { 184 | ctx->data[47] = data[0]; 185 | ctx->data[48] = data[1]; 186 | ctx->data[49] = data[2]; 187 | ctx->data[50] = data[3]; 188 | ctx->data[51] = data[4]; 189 | ctx->data[52] = data[5]; 190 | /* 191 | ctx->data[55] = 0x80; 192 | 193 | ctx->bitlen = 440; 194 | ctx->data[63] = ctx->bitlen; 195 | ctx->data[62] = ctx->bitlen >> 8; 196 | ctx->data[61] = ctx->bitlen >> 16; 197 | ctx->data[60] = ctx->bitlen >> 24; 198 | ctx->data[59] = ctx->bitlen >> 32; 199 | ctx->data[58] = ctx->bitlen >> 40; 200 | ctx->data[57] = ctx->bitlen >> 48; 201 | ctx->data[56] = ctx->bitlen >> 56; 202 | */ 203 | } 204 | 205 | __device__ void sha256_finalAmoveo(SHA256_CTX *ctx, const BYTE data[], BYTE hash[]) 206 | { 207 | ctx->data[53] = data[0]; 208 | ctx->data[54] = data[1]; 209 | 210 | sha256_transform(ctx, ctx->data); 211 | 212 | hash[0] = (ctx->state[0] >> 24) & 0x000000ff; 213 | hash[4] = (ctx->state[1] >> 24) & 0x000000ff; 214 | hash[8] = (ctx->state[2] >> 24) & 0x000000ff; 215 | hash[12] = (ctx->state[3] >> 24) & 0x000000ff; 216 | hash[16] = (ctx->state[4] >> 24) & 0x000000ff; 217 | hash[20] = (ctx->state[5] >> 24) & 0x000000ff; 218 | hash[24] = (ctx->state[6] >> 24) & 0x000000ff; 219 | hash[28] = (ctx->state[7] >> 24) & 0x000000ff; 220 | 221 | hash[1] = (ctx->state[0] >> 16) & 0x000000ff; 222 | hash[5] = (ctx->state[1] >> 16) & 0x000000ff; 223 | hash[9] = (ctx->state[2] >> 16) & 0x000000ff; 224 | hash[13] = (ctx->state[3] >> 16) & 0x000000ff; 225 | hash[17] = (ctx->state[4] >> 16) & 0x000000ff; 226 | hash[21] = (ctx->state[5] >> 16) & 0x000000ff; 227 | hash[25] = (ctx->state[6] >> 16) & 0x000000ff; 228 | hash[29] = (ctx->state[7] >> 16) & 0x000000ff; 229 | 230 | hash[2] = (ctx->state[0] >> 8) & 0x000000ff; 231 | hash[6] = (ctx->state[1] >> 8) & 0x000000ff; 232 | hash[10] = (ctx->state[2] >> 8) & 0x000000ff; 233 | hash[14] = (ctx->state[3] >> 8) & 0x000000ff; 234 | hash[18] = (ctx->state[4] >> 8) & 0x000000ff; 235 | hash[22] = (ctx->state[5] >> 8) & 0x000000ff; 236 | hash[26] = (ctx->state[6] >> 8) & 0x000000ff; 237 | hash[30] = (ctx->state[7] >> 8) & 0x000000ff; 238 | 239 | hash[3] = ctx->state[0] & 0x000000ff; 240 | hash[7] = ctx->state[1] & 0x000000ff; 241 | hash[11] = ctx->state[2] & 0x000000ff; 242 | hash[15] = ctx->state[3] & 0x000000ff; 243 | hash[19] = ctx->state[4] & 0x000000ff; 244 | hash[23] = ctx->state[5] & 0x000000ff; 245 | hash[27] = ctx->state[6] & 0x000000ff; 246 | hash[31] = ctx->state[7] & 0x000000ff; 247 | } 248 | 249 | __device__ void sha256_final(SHA256_CTX *ctx, BYTE hash[]) 250 | { 251 | WORD i; 252 | 253 | i = ctx->datalen; 254 | 255 | // Pad whatever data is left in the buffer. 256 | if (ctx->datalen < 56) { 257 | ctx->data[i++] = 0x80; 258 | while (i < 56) 259 | ctx->data[i++] = 0x00; 260 | } 261 | else { 262 | ctx->data[i++] = 0x80; 263 | while (i < 64) 264 | ctx->data[i++] = 0x00; 265 | sha256_transform(ctx, ctx->data); 266 | memset(ctx->data, 0, 56); 267 | } 268 | 269 | // Append to the padding the total message's length in bits and transform. 270 | ctx->bitlen += ctx->datalen * 8; 271 | ctx->data[63] = ctx->bitlen; 272 | ctx->data[62] = ctx->bitlen >> 8; 273 | ctx->data[61] = ctx->bitlen >> 16; 274 | ctx->data[60] = ctx->bitlen >> 24; 275 | ctx->data[59] = ctx->bitlen >> 32; 276 | ctx->data[58] = ctx->bitlen >> 40; 277 | ctx->data[57] = ctx->bitlen >> 48; 278 | ctx->data[56] = ctx->bitlen >> 56; 279 | sha256_transform(ctx, ctx->data); 280 | 281 | // Since this implementation uses little endian byte ordering and SHA uses big endian, 282 | // reverse all the bytes when copying the final state to the output hash. 283 | for (i = 0; i < 4; ++i) { 284 | hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; 285 | hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; 286 | hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; 287 | hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; 288 | hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; 289 | hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; 290 | hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; 291 | hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; 292 | } 293 | } 294 | 295 | #endif // SHA256_H -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #define VERSION_STRING "2.0.0.1" 2 | #define TOOL_NAME "AmoveoMinerGpuCuda" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "cuda_runtime.h" 19 | #include "device_launch_parameters.h" 20 | 21 | #include "sha256.cuh" 22 | #include "stdlib.h" 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | 38 | #include "poolApi.h" 39 | #include "base64.h" 40 | 41 | using namespace std; 42 | using namespace std::chrono; 43 | 44 | using namespace utility; // Common utilities like string conversions 45 | 46 | #define FETCH_WORK_INTERVAL_MS 3000 47 | #define SHOW_INTERVAL_MS 4000 48 | 49 | int gElapsedMilliSecMax = FETCH_WORK_INTERVAL_MS; 50 | 51 | //#define POOL_URL "http://localhost:32371/work" // local pool 52 | #define POOL_URL "http://159.65.120.84:8085" 53 | #define MINER_ADDRESS "BGH+3P768A9cSNR3GLSRXgsokSL/Jdbm+rOJogbgiPxq8M+J2R4nVxZ+Hj6WdI4rMsq6nPzkMh77WGBCMx89HUM=" 54 | #define DEFAULT_DEVICE_ID 0 55 | 56 | string gMinerPublicKeyBase64(MINER_ADDRESS); 57 | string gPoolUrl(POOL_URL); 58 | string_t gPoolUrlW; 59 | int gDevicdeId = DEFAULT_DEVICE_ID; 60 | 61 | PoolApi gPoolApi; 62 | WorkData gWorkData; 63 | std::mutex mutexWorkData; 64 | 65 | 66 | uint64_t gTotalNonce = 0; 67 | 68 | // First timestamp when program starts 69 | static std::chrono::high_resolution_clock::time_point t1; 70 | 71 | // Last timestamp we printed debug info 72 | static std::chrono::high_resolution_clock::time_point t_last_updated; 73 | static std::chrono::high_resolution_clock::time_point t_last_work_fetch; 74 | 75 | 76 | 77 | __device__ bool checkResult(unsigned char* h, size_t diff) { 78 | WORD x = 0; 79 | WORD z = 0; 80 | for (int i = 0; i < 31; i++) { 81 | if (h[i] == 0) { 82 | x += 8; 83 | continue; 84 | } 85 | else if (h[i] < 2) { 86 | x += 7; 87 | z = h[i + 1]; 88 | } 89 | else if (h[i] < 4) { 90 | x += 6; 91 | z = (h[i + 1] / 2) + ((h[i] % 2) * 128); 92 | } 93 | else if (h[i] < 8) { 94 | x += 5; 95 | z = (h[i + 1] / 4) + ((h[i] % 4) * 64); 96 | } 97 | else if (h[i] < 16) { 98 | x += 4; 99 | z = (h[i + 1] / 8) + ((h[i] % 8) * 32); 100 | } 101 | else if (h[i] < 32) { 102 | x += 3; 103 | z = (h[i + 1] / 16) + ((h[i] % 16) * 16); 104 | } 105 | else if (h[i] < 64) { 106 | x += 2; 107 | z = (h[i + 1] / 32) + ((h[i] % 32) * 8); 108 | } 109 | else if (h[i] < 128) { 110 | x += 1; 111 | z = (h[i + 1] / 64) + ((h[i] % 64) * 4); 112 | } 113 | else { 114 | z = (h[i + 1] / 128) + ((h[i] % 128) * 2); 115 | } 116 | break; 117 | } 118 | WORD y[2]; 119 | y[0] = x; 120 | y[1] = z; 121 | return(((256 * y[0]) + y[1]) >= diff); 122 | } 123 | 124 | 125 | __global__ void sha256_kernel(/*unsigned char * out_hash,*/ unsigned char * out_nonce, int *out_found, const SHA256_CTX * in_ctx, uint64_t nonceOffset, int shareDiff, int suffixMax) 126 | { 127 | __shared__ SHA256_CTX ctxShared; 128 | __shared__ int diff; 129 | __shared__ uint64_t nonceOff; 130 | 131 | // If this is the first thread of the block, init the input string in shared memory 132 | if (threadIdx.x == 0) { 133 | memcpy(&ctxShared, in_ctx, 0x70); 134 | diff = shareDiff; 135 | nonceOff = nonceOffset; 136 | } 137 | __syncthreads(); // Ensure the input string has been written in SMEM 138 | 139 | unsigned int threadIndex = threadIdx.x; 140 | uint64_t currentBlockIdx = blockIdx.x * blockDim.x + threadIdx.x + nonceOff; 141 | 142 | unsigned char shaResult[32]; 143 | SHA256_CTX ctxReuse; 144 | memcpy(&ctxReuse, &ctxShared, 0x70); 145 | // sha256_update(&ctxReuse, (BYTE*)¤tBlockIdx, 6); 146 | sha256_updateAmoveoSpecial(&ctxReuse, (BYTE*)¤tBlockIdx); 147 | 148 | SHA256_CTX ctxTmp; 149 | int nonceSuffix = 0; 150 | for (nonceSuffix = 0; nonceSuffix < suffixMax; nonceSuffix++) { 151 | memcpy(&ctxTmp, &ctxReuse, 0x70); 152 | sha256_finalAmoveo(&ctxTmp, (BYTE*)&nonceSuffix, shaResult); 153 | if (checkResult(shaResult, diff) && atomicExch(out_found, 1) == 0) { 154 | memcpy(out_nonce, ¤tBlockIdx, 6); 155 | memcpy(out_nonce + 6, &nonceSuffix, 2); 156 | //memcpy(out_hash, shaResult, 32); 157 | return; 158 | } 159 | } 160 | } 161 | 162 | __global__ void sha256Init_kernel(unsigned char * out_ctx, unsigned char * bhash, unsigned char * noncePart) 163 | { 164 | SHA256_CTX ctx; 165 | unsigned char bhashLocal[32]; 166 | unsigned char nonceLocal[15]; 167 | 168 | memcpy(bhashLocal, bhash, 32); 169 | memcpy(nonceLocal, noncePart, 15); 170 | 171 | sha256_init(&ctx); 172 | sha256_update(&ctx, bhashLocal, 32); 173 | sha256_update(&ctx, nonceLocal, 15); 174 | sha256_updateAmoveoCtxTrailer(&ctx); 175 | memcpy(out_ctx, &ctx, 0x70); 176 | } 177 | 178 | 179 | void pre_sha256() { 180 | checkCudaErrors(cudaMemcpyToSymbol(dev_k, host_k, sizeof(host_k), 0, cudaMemcpyHostToDevice)); 181 | } 182 | 183 | // Prints a 32 bytes sha256 to the hexadecimal form filled with zeroes 184 | void print_hash(const unsigned char* sha256) { 185 | for (size_t i = 0; i < 32; ++i) { 186 | std::cout << std::hex << std::setfill('0') << std::setw(2) << static_cast(sha256[i]); 187 | } 188 | std::cout << std::dec << std::endl; 189 | } 190 | void print_nonce(const unsigned char* nonce) { 191 | for (size_t i = 0; i < 23; ++i) { 192 | std::cout << std::hex << std::setfill('0') << std::setw(2) << static_cast(nonce[i]); 193 | } 194 | std::cout << std::dec << std::endl; 195 | } 196 | 197 | bool isTimeToGetNewWork() 198 | { 199 | std::chrono::high_resolution_clock::time_point tNow = std::chrono::high_resolution_clock::now(); 200 | std::chrono::duration lastWorkFetchInterval = tNow - t_last_work_fetch; 201 | if (lastWorkFetchInterval.count() > gElapsedMilliSecMax) { 202 | t_last_work_fetch = tNow; 203 | return true; 204 | } 205 | return false; 206 | } 207 | 208 | void print_state() { 209 | std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now(); 210 | 211 | std::chrono::duration last_show_interval = t2 - t_last_updated; 212 | if (last_show_interval.count() > SHOW_INTERVAL_MS) { 213 | t_last_updated = std::chrono::high_resolution_clock::now(); 214 | std::chrono::duration span = t2 - t1; 215 | float ratio = span.count() / 1000; 216 | std::cout << std::fixed << static_cast(gTotalNonce / ratio) << " h/s " << endl; 217 | } 218 | } 219 | 220 | static bool getwork_thread(std::seed_seq &seed) 221 | { 222 | std::independent_bits_engine randomBytesEngine(seed); 223 | 224 | unsigned char ctxBuf[0x70]; 225 | 226 | unsigned char *d_bhash = nullptr; 227 | unsigned char *d_nonce = nullptr; 228 | cudaMalloc(&d_bhash, 32); 229 | cudaMalloc(&d_nonce, 15); 230 | unsigned char * outCtx = nullptr; 231 | cudaMalloc(&outCtx, 0x70); 232 | 233 | while (true) 234 | { 235 | WorkData workDataNew; 236 | gPoolApi.GetWork(gPoolUrlW, &workDataNew, gMinerPublicKeyBase64); 237 | 238 | // Check if new work unit is actually different than what we currently have 239 | if (memcmp(&gWorkData.bhash[0], &workDataNew.bhash[0], 32) != 0) { 240 | mutexWorkData.lock(); 241 | std::generate(begin(gWorkData.nonce), end(gWorkData.nonce), std::ref(randomBytesEngine)); 242 | gWorkData.bhash = workDataNew.bhash; 243 | gWorkData.blockDifficulty = workDataNew.blockDifficulty; 244 | gWorkData.shareDifficulty = workDataNew.shareDifficulty; 245 | 246 | cudaMemcpy(d_bhash, &gWorkData.bhash[0], 32, cudaMemcpyHostToDevice); 247 | cudaMemcpy(d_nonce, &gWorkData.nonce[0], 15, cudaMemcpyHostToDevice); 248 | 249 | sha256Init_kernel << < 1, 1 >> > (outCtx, d_bhash, d_nonce); 250 | 251 | cudaError_t err = cudaDeviceSynchronize(); 252 | if (err != cudaSuccess) { 253 | std::cout << "getwork_thread Cuda Error: " << cudaGetErrorString(err) << std::endl; 254 | throw std::runtime_error("getwork_thread Device error"); 255 | } 256 | 257 | cudaMemcpy(ctxBuf, outCtx, 0x70, cudaMemcpyDeviceToHost); 258 | //SHA256_CTX ctx; 259 | //memcpy(&ctx, outCtx, sizeof(SHA256_CTX)); 260 | gWorkData.setCtx(ctxBuf); 261 | 262 | mutexWorkData.unlock(); 263 | 264 | std::cout << "New Work ||" << "BDiff:" << gWorkData.blockDifficulty << " SDiff:" << gWorkData.shareDifficulty << endl; 265 | } 266 | else { 267 | // Even if new work is not available, shareDiff will likely change. Need to adjust, else will get a "low diff share" error. 268 | gWorkData.shareDifficulty = workDataNew.shareDifficulty; 269 | } 270 | 271 | mySleep(2000); 272 | } 273 | 274 | cudaFree(outCtx); 275 | cudaFree(d_bhash); 276 | cudaFree(d_nonce); 277 | return true; 278 | } 279 | 280 | static void submitwork_thread(unsigned char * nonceSolution) 281 | { 282 | gPoolApi.SubmitWork(gPoolUrlW, base64_encode(nonceSolution, 23), gMinerPublicKeyBase64); 283 | cout << "--- Found Share --- " << endl; 284 | } 285 | 286 | int gBlockSize = 64; 287 | int gNumBlocks = 96; 288 | int gSuffixMax = 65536; 289 | std::string gSeedStr("ImAraNdOmStrInG"); 290 | 291 | int main(int argc, char* argv[]) 292 | { 293 | cout << TOOL_NAME << " v" << VERSION_STRING << endl; 294 | if (argc <= 1) { 295 | cout << "Example Template: " << endl; 296 | cout << argv[0] << " " << "" << " " << "" << " " << "" << " " << "" << " " << "" << " " << "" << " " << "" << endl; 297 | 298 | cout << endl; 299 | cout << "Example Usage: " << endl; 300 | cout << argv[0] << " " << MINER_ADDRESS << endl; 301 | 302 | cout << endl; 303 | cout << "Advanced Example Usage: " << endl; 304 | cout << argv[0] << " " << MINER_ADDRESS << " " << DEFAULT_DEVICE_ID << " " << gBlockSize << " " << gNumBlocks << " " << "RandomSeed" << " " << "65536" << " " << POOL_URL << endl; 305 | 306 | cout << endl; 307 | cout << endl; 308 | cout << "CudaDeviceId is optional. Default CudaDeviceId is 0" << endl; 309 | cout << "BlockSize is optional. Default BlockSize is 64" << endl; 310 | cout << "NumBlocks is optional. Default NumBlocks is 96" << endl; 311 | cout << "RandomSeed is optional. No default." << endl; 312 | cout << "SuffixMax is optional. Default is 65536" << endl; 313 | cout << "PoolUrl is optional. Default PoolUrl is http://amoveopool.com/work" << endl; 314 | return -1; 315 | } 316 | if (argc >= 2) { 317 | gMinerPublicKeyBase64 = argv[1]; 318 | } 319 | if (argc >= 3) { 320 | gDevicdeId = atoi(argv[2]); 321 | } 322 | if (argc >= 4) { 323 | gBlockSize = atoi(argv[3]); 324 | } 325 | if (argc >= 5) { 326 | gNumBlocks = atoi(argv[4]); 327 | } 328 | if (argc >= 6) { 329 | gSeedStr = argv[5]; 330 | } 331 | if (argc >= 7) { 332 | gSuffixMax = atoi(argv[6]); 333 | } 334 | if (argc >= 8) { 335 | gPoolUrl = argv[7]; 336 | } 337 | 338 | gPoolUrlW.resize(gPoolUrl.length(), L' '); 339 | std::copy(gPoolUrl.begin(), gPoolUrl.end(), gPoolUrlW.begin()); 340 | std::seed_seq seed(gSeedStr.begin(), gSeedStr.end()); 341 | 342 | cudaDeviceProp deviceProp; 343 | cudaGetDeviceProperties(&deviceProp, gDevicdeId); 344 | cout << "GPU Device Properties:" << endl; 345 | cout << "maxThreadsDim: " << deviceProp.maxThreadsDim << endl; 346 | cout << "maxThreadsPerBlock: " << deviceProp.maxThreadsPerBlock << endl; 347 | cout << "maxGridSize: " << deviceProp.maxGridSize << endl; 348 | 349 | cudaSetDevice(gDevicdeId); 350 | cudaDeviceSetCacheConfig(cudaFuncCachePreferShared); 351 | //cudaDeviceSetCacheConfig(cudaFuncCachePreferNone); 352 | 353 | unsigned char localCtx[0x70]; 354 | // Input string for the device 355 | SHA256_CTX * d_ctx = nullptr; 356 | // Output string by the device read by host 357 | unsigned char *g_out = nullptr; 358 | int *g_found = nullptr; 359 | 360 | cudaMalloc(&d_ctx, sizeof(SHA256_CTX)); // SHA256_CTX ctx to be used 361 | 362 | cudaMalloc(&g_out, 8); // partial nonce - last 8 bytes 363 | cudaMalloc(&g_found, 4); // "found" success flag 364 | 365 | //unsigned char *g_outhash = nullptr; 366 | //cudaMalloc(&g_outhash, 32); 367 | 368 | future getWorkThread = std::async(std::launch::async, getwork_thread, std::ref(seed)); 369 | 370 | const uint64_t blocksPerKernel = gNumBlocks * gBlockSize; 371 | const uint64_t hashesPerKernel = blocksPerKernel * gSuffixMax; 372 | cout << "blockSize: " << gBlockSize << endl; 373 | cout << "numBlocks: " << gNumBlocks << endl; 374 | cout << "suffixMax: " << gSuffixMax << endl; 375 | cout << "poolUrl: " << gPoolUrl << endl; 376 | 377 | pre_sha256(); 378 | 379 | uint64_t nonceOffset = 0; 380 | int shareDiff = 0; 381 | uint64_t nonceSolutionVal = 0; 382 | bool found = false; 383 | 384 | while (!gWorkData.HasNewWork()) 385 | { 386 | mySleep(100); 387 | } 388 | gWorkData.getCtx(localCtx); 389 | cudaMemcpy(d_ctx, localCtx, sizeof(SHA256_CTX), cudaMemcpyHostToDevice); 390 | int foundInit = 0; 391 | cudaMemcpy(g_found, &foundInit, 4, cudaMemcpyHostToDevice); 392 | gWorkData.clearNewWork(); 393 | shareDiff = gWorkData.shareDifficulty; 394 | 395 | t1 = std::chrono::high_resolution_clock::now(); 396 | t_last_updated = std::chrono::high_resolution_clock::now(); 397 | t_last_work_fetch = std::chrono::high_resolution_clock::now(); 398 | 399 | while (true) { 400 | sha256_kernel << < gNumBlocks, gBlockSize >> > (/*g_outhash,*/ g_out, g_found, d_ctx, nonceOffset, shareDiff, gSuffixMax); 401 | 402 | cudaError_t err = cudaDeviceSynchronize(); 403 | if (err != cudaSuccess) { 404 | std::cout << "Cuda Error: " << cudaGetErrorString(err) << std::endl; 405 | throw std::runtime_error("Device error"); 406 | } 407 | 408 | cudaMemcpy(&found, g_found, 1, cudaMemcpyDeviceToHost); 409 | 410 | if (found) { 411 | unsigned char nonceSolution[23]; 412 | mutexWorkData.lock(); 413 | memcpy(nonceSolution, &gWorkData.nonce[0], 15); 414 | mutexWorkData.unlock(); 415 | cudaMemcpy(&nonceSolutionVal, g_out, 8, cudaMemcpyDeviceToHost); 416 | memcpy(nonceSolution + 15, &nonceSolutionVal, 8); 417 | //print_nonce(nonceSolution); 418 | //unsigned char hashSolution[32]; 419 | //cudaMemcpy(hashSolution, g_outhash, 32, cudaMemcpyDeviceToHost); 420 | //print_hash(hashSolution); 421 | 422 | std::async(std::launch::async, submitwork_thread, std::ref(nonceSolution)); 423 | 424 | found = 0; 425 | cudaMemcpy(g_found, &found, 1, cudaMemcpyHostToDevice); 426 | } 427 | 428 | gTotalNonce += hashesPerKernel; 429 | nonceOffset += blocksPerKernel; 430 | 431 | if (gWorkData.HasNewWork()) 432 | { 433 | mutexWorkData.lock(); 434 | gWorkData.getCtx(localCtx); 435 | mutexWorkData.unlock(); 436 | 437 | cudaMemcpy(d_ctx, localCtx, sizeof(SHA256_CTX), cudaMemcpyHostToDevice); 438 | gWorkData.clearNewWork(); 439 | //nonceOffset = 0; 440 | } 441 | shareDiff = gWorkData.shareDifficulty; 442 | //print_state(); 443 | 444 | std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now(); 445 | 446 | std::chrono::duration last_show_interval = t2 - t_last_updated; 447 | if (last_show_interval.count() > SHOW_INTERVAL_MS) { 448 | t_last_updated = std::chrono::high_resolution_clock::now(); 449 | std::chrono::duration span = t2 - t1; 450 | float ratio = span.count() / 1000; 451 | //std::cout << std::fixed << static_cast(gTotalNonce / ratio) << " h/s S:" << totalSharesFound << " S/H:" << ((totalSharesFound *3600) / ratio) << std::endl; 452 | std::cout << std::fixed << static_cast(gTotalNonce / ratio) << " h/s " << endl; 453 | } 454 | } 455 | 456 | //cudaFree(g_outhash); 457 | cudaFree(g_out); 458 | cudaFree(g_found); 459 | 460 | cudaFree(d_ctx); 461 | 462 | cudaDeviceReset(); 463 | 464 | return 0; 465 | } 466 | --------------------------------------------------------------------------------