Skip to content
This repository was archived by the owner on Oct 21, 2019. It is now read-only.

Commit b6362bc

Browse files
Add support for EthereumStratum/1.0.0 mode (see -ES option). This adds compatibility with NiceHash.com.
1 parent 05473d7 commit b6362bc

19 files changed

Lines changed: 469 additions & 107 deletions

cmake/scripts/macdeployfix.sh

100755100644
File mode changed.

ethminer/MinerAux.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ class MinerCLI
201201
BOOST_THROW_EXCEPTION(BadArgument());
202202
}
203203
}
204+
else if (arg == "-ES" || arg == "--ethereum-stratum")
205+
{
206+
m_ethereumStratum = true;
207+
}
204208
else if ((arg == "-FO" || arg == "--failover-userpass") && i + 1 < argc)
205209
{
206210
string userpass = string(argv[++i]);
@@ -330,6 +334,11 @@ class MinerCLI
330334
string mode = argv[++i];
331335
if (mode == "parallel") m_dagLoadMode = DAG_LOAD_MODE_PARALLEL;
332336
else if (mode == "sequential") m_dagLoadMode = DAG_LOAD_MODE_SEQUENTIAL;
337+
else if (mode == "single")
338+
{
339+
m_dagLoadMode = DAG_LOAD_MODE_SINGLE;
340+
m_dagCreateDevice = stol(argv[++i]);
341+
}
333342
else
334343
{
335344
cerr << "Bad " << arg << " option: " << argv[i] << endl;
@@ -531,7 +540,8 @@ class MinerCLI
531540
m_clAllowCPU,
532541
m_extraGPUMemory,
533542
0,
534-
m_dagLoadMode
543+
m_dagLoadMode,
544+
m_dagCreateDevice
535545
))
536546
exit(1);
537547
EthashGPUMiner::setNumInstances(m_miningThreads);
@@ -557,7 +567,8 @@ class MinerCLI
557567
m_extraGPUMemory,
558568
m_cudaSchedule,
559569
0,
560-
m_dagLoadMode
570+
m_dagLoadMode,
571+
m_dagCreateDevice
561572
))
562573
exit(1);
563574
#else
@@ -592,7 +603,8 @@ class MinerCLI
592603
<< " -O, --userpass <username.workername:password> Stratum login credentials" << endl
593604
<< " -FO, --failover-userpass <username.workername:password> Failover stratum login credentials (optional, will use normal credentials when omitted)" << endl
594605
<< " --work-timeout <n> reconnect/failover after n seconds of working on the same (stratum) job. Defaults to 180. Don't set lower than max. avg. block time" << endl
595-
<< " -SV, --stratum-version <n> Stratum client version. Defaults to 1 (async client). Use 2 to test new synchronous client."
606+
<< " -SV, --stratum-version <n> Stratum client version. Defaults to 1 (async client). Use 2 to test new synchronous client." << endl
607+
<< " -ES, --ethereum-stratum Use EthereumStratum/1.0.0 mode." << endl
596608
#endif
597609
#if ETH_JSONRPC || ETH_STRATUM || !ETH_TRUE
598610
<< " --farm-recheck <n> Leave n ms between checks for changed work (default: 500). When using stratum, use a high value (i.e. 2000) to get more stable hashrate output" << endl
@@ -618,6 +630,7 @@ class MinerCLI
618630
<< " -L, --dag-load-mode <mode> DAG generation mode." << endl
619631
<< " parallel - load DAG on all GPUs at the same time (default)" << endl
620632
<< " sequential - load DAG on GPUs one after another. Use this when the miner crashes during DAG generation" << endl
633+
<< " single <n> - generate DAG on device n, then copy to other devices" << endl
621634
#if ETH_ETHASHCL || !ETH_TRUE
622635
<< " --cl-extragpu-mem Set the memory (in MB) you believe your GPU requires for stuff other than mining. default: 0" << endl
623636
<< " --cl-local-work Set the OpenCL local work size. Default is " << toString(ethash_cl_miner::c_defaultLocalWorkSize) << endl
@@ -992,7 +1005,7 @@ class MinerCLI
9921005

9931006
// this is very ugly, but if Stratum Client V2 tunrs out to be a success, V1 will be completely removed anyway
9941007
if (m_stratumClientVersion == 1) {
995-
EthStratumClient client(&f, m_minerType, m_farmURL, m_port, m_user, m_pass, m_maxFarmRetries, m_worktimeout);
1008+
EthStratumClient client(&f, m_minerType, m_farmURL, m_port, m_user, m_pass, m_maxFarmRetries, m_worktimeout, m_ethereumStratum);
9961009
if (m_farmFailOverURL != "")
9971010
{
9981011
if (m_fuser != "")
@@ -1032,7 +1045,7 @@ class MinerCLI
10321045
}
10331046
}
10341047
else if (m_stratumClientVersion == 2) {
1035-
EthStratumClientV2 client(&f, m_minerType, m_farmURL, m_port, m_user, m_pass, m_maxFarmRetries, m_worktimeout);
1048+
EthStratumClientV2 client(&f, m_minerType, m_farmURL, m_port, m_user, m_pass, m_maxFarmRetries, m_worktimeout, m_ethereumStratum);
10361049
if (m_farmFailOverURL != "")
10371050
{
10381051
if (m_fuser != "")
@@ -1100,6 +1113,7 @@ class MinerCLI
11001113
// default value was 350MB of GPU memory for other stuff (windows system rendering, e.t.c.)
11011114
unsigned m_extraGPUMemory = 0;// 350000000; don't assume miners run desktops...
11021115
unsigned m_dagLoadMode = 0; // parallel
1116+
unsigned m_dagCreateDevice = 0;
11031117
/// Benchmarking params
11041118
bool m_phoneHome = false;
11051119
unsigned m_benchmarkWarmup = 15;
@@ -1121,6 +1135,7 @@ class MinerCLI
11211135

11221136
#if ETH_STRATUM || !ETH_TRUE
11231137
int m_stratumClientVersion = 1;
1138+
bool m_ethereumStratum = false;
11241139
string m_user;
11251140
string m_pass;
11261141
string m_port;

extdep/getstuff.bat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,4 @@ cd ..
3636

3737
goto :EOF
3838

39+

libethash-cl/ethash_cl_miner.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ typedef struct
504504
unsigned buf;
505505
} pending_batch;
506506

507-
void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook& hook)
507+
void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook& hook, bool _ethStratum, uint64_t _startN)
508508
{
509509
try
510510
{
@@ -531,7 +531,9 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook
531531

532532
unsigned buf = 0;
533533
random_device engine;
534-
uint64_t start_nonce = uniform_int_distribution<uint64_t>()(engine);
534+
uint64_t start_nonce;
535+
if (_ethStratum) start_nonce = _startN;
536+
else start_nonce = uniform_int_distribution<uint64_t>()(engine);
535537
for (;; start_nonce += m_globalWorkSize)
536538
{
537539
// supply output buffer to kernel

libethash-cl/ethash_cl_miner.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class ethash_cl_miner
5959
unsigned _deviceId
6060
);
6161
void finish();
62-
void search(uint8_t const* _header, uint64_t _target, search_hook& _hook);
62+
void search(uint8_t const* _header, uint64_t _target, search_hook& _hook, bool _ethStratum, uint64_t _startN);
6363

6464
/* -- default values -- */
6565
/// Default value of the local work size. Also known as workgroup size.

libethash-cuda/ethash_cuda_miner.cpp

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ void ethash_cuda_miner::finish()
199199
CUDA_SAFE_CALL(cudaDeviceReset());
200200
}
201201

202-
bool ethash_cuda_miner::init(ethash_light_t _light, uint8_t const* _lightData, uint64_t _lightSize, unsigned _deviceId)
202+
bool ethash_cuda_miner::init(ethash_light_t _light, uint8_t const* _lightData, uint64_t _lightSize, unsigned _deviceId, bool _cpyToHost, volatile void** hostDAG)
203203
{
204204
try
205205
{
@@ -229,10 +229,14 @@ bool ethash_cuda_miner::init(ethash_light_t _light, uint8_t const* _lightData, u
229229
uint32_t lightSize64 = (unsigned)(_lightSize / sizeof(node));
230230

231231
// create buffer for cache
232-
hash64_t * light;
233-
CUDA_SAFE_CALL(cudaMalloc(reinterpret_cast<void**>(&light), _lightSize));
234-
// copy dag cache to CPU.
235-
CUDA_SAFE_CALL(cudaMemcpy(reinterpret_cast<void*>(light), _lightData, _lightSize, cudaMemcpyHostToDevice));
232+
hash64_t * light = NULL;
233+
234+
if (!*hostDAG)
235+
{
236+
CUDA_SAFE_CALL(cudaMalloc(reinterpret_cast<void**>(&light), _lightSize));
237+
// copy dag cache to CPU.
238+
CUDA_SAFE_CALL(cudaMemcpy(reinterpret_cast<void*>(light), _lightData, _lightSize, cudaMemcpyHostToDevice));
239+
}
236240

237241
// create buffer for dag
238242
hash128_t * dag;
@@ -252,9 +256,28 @@ bool ethash_cuda_miner::init(ethash_light_t _light, uint8_t const* _lightData, u
252256

253257
m_sharedBytes = device_props.major * 100 < SHUFFLE_MIN_VER ? (64 * s_blockSize) / 8 : 0 ;
254258

259+
if (!*hostDAG)
260+
{
261+
cout << "Generating DAG for GPU #" << device_num << endl;
262+
ethash_generate_dag(dagSize, s_gridSize, s_blockSize, m_streams[0], device_num);
263+
264+
if (_cpyToHost)
265+
{
266+
uint8_t* memoryDAG = new uint8_t[dagSize];
267+
if (!memoryDAG) throw std::runtime_error("Failed to init host memory for DAG, not enough memory?");
268+
269+
cout << "Copying DAG from GPU #" << device_num << " to host" << endl;
270+
CUDA_SAFE_CALL(cudaMemcpy(reinterpret_cast<void*>(memoryDAG), dag, dagSize, cudaMemcpyDeviceToHost));
255271

256-
cout << "Generating DAG for GPU #" << device_num << endl;
257-
ethash_generate_dag(dagSize, s_gridSize, s_blockSize, m_streams[0], device_num);
272+
*hostDAG = (void*)memoryDAG;
273+
}
274+
}
275+
else
276+
{
277+
cout << "Copying DAG from host to GPU #" << device_num << endl;
278+
const void* hdag = (const void*)(*hostDAG);
279+
CUDA_SAFE_CALL(cudaMemcpy(reinterpret_cast<void*>(dag), hdag, dagSize, cudaMemcpyHostToDevice));
280+
}
258281

259282
return true;
260283
}
@@ -264,7 +287,7 @@ bool ethash_cuda_miner::init(ethash_light_t _light, uint8_t const* _lightData, u
264287
}
265288
}
266289

267-
void ethash_cuda_miner::search(uint8_t const* header, uint64_t target, search_hook& hook)
290+
void ethash_cuda_miner::search(uint8_t const* header, uint64_t target, search_hook& hook, bool _ethStratum, uint64_t _startN)
268291
{
269292
bool initialize = false;
270293
bool exit = false;
@@ -280,14 +303,34 @@ void ethash_cuda_miner::search(uint8_t const* header, uint64_t target, search_ho
280303
set_target(m_current_target);
281304
initialize = true;
282305
}
283-
if (initialize)
306+
if (_ethStratum)
284307
{
285-
random_device engine;
286-
m_current_nonce = uniform_int_distribution<uint64_t>()(engine);
287-
m_current_index = 0;
288-
CUDA_SAFE_CALL(cudaDeviceSynchronize());
289-
for (unsigned int i = 0; i < s_numStreams; i++)
290-
m_search_buf[i][0] = 0;
308+
if (initialize)
309+
{
310+
m_starting_nonce = 0;
311+
m_current_index = 0;
312+
CUDA_SAFE_CALL(cudaDeviceSynchronize());
313+
for (unsigned int i = 0; i < s_numStreams; i++)
314+
m_search_buf[i][0] = 0;
315+
}
316+
if (m_starting_nonce != _startN)
317+
{
318+
// reset nonce counter
319+
m_starting_nonce = _startN;
320+
m_current_nonce = m_starting_nonce;
321+
}
322+
}
323+
else
324+
{
325+
if (initialize)
326+
{
327+
random_device engine;
328+
m_current_nonce = uniform_int_distribution<uint64_t>()(engine);
329+
m_current_index = 0;
330+
CUDA_SAFE_CALL(cudaDeviceSynchronize());
331+
for (unsigned int i = 0; i < s_numStreams; i++)
332+
m_search_buf[i][0] = 0;
333+
}
291334
}
292335
uint64_t batch_size = s_gridSize * s_blockSize;
293336
for (; !exit; m_current_index++, m_current_nonce += batch_size)

libethash-cuda/ethash_cuda_miner.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ class ethash_cuda_miner
3535
uint64_t _currentBlock
3636
);
3737

38-
bool init(ethash_light_t _light, uint8_t const* _lightData, uint64_t _lightSize, unsigned _deviceId);
38+
bool init(ethash_light_t _light, uint8_t const* _lightData, uint64_t _lightSize, unsigned _deviceId, bool _cpyToHost, volatile void** hostDAG);
3939

4040
void finish();
41-
void search(uint8_t const* header, uint64_t target, search_hook& hook);
41+
void search(uint8_t const* header, uint64_t target, search_hook& hook, bool _ethStratum, uint64_t _startN);
4242

4343
/* -- default values -- */
4444
/// Default value of the block size. Also known as workgroup size.
@@ -52,6 +52,7 @@ class ethash_cuda_miner
5252
hash32_t m_current_header;
5353
uint64_t m_current_target;
5454
uint64_t m_current_nonce;
55+
uint64_t m_starting_nonce;
5556
uint64_t m_current_index;
5657

5758
uint32_t m_sharedBytes;

libethcore/EthashAux.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,20 @@ struct EthashProofOfWork
5353
struct WorkPackage
5454
{
5555
WorkPackage() = default;
56-
WorkPackage(Ethash::BlockHeader const& _bh):
56+
WorkPackage(Ethash::BlockHeader const& _bh) :
5757
boundary(_bh.boundary()),
5858
headerHash(_bh.hashWithout()),
5959
seedHash(_bh.seedHash())
60-
{}
60+
{ }
6161
void reset() { headerHash = h256(); }
6262
operator bool() const { return headerHash != h256(); }
6363

6464
h256 boundary;
6565
h256 headerHash; ///< When h256() means "pause until notified a new work package is available".
6666
h256 seedHash;
67+
68+
uint64_t startNonce = 0;
69+
int exSizeBits = -1;
6770
};
6871

6972
static const WorkPackage NullWorkPackage;

libethcore/EthashCUDAMiner.cpp

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,32 +144,62 @@ void EthashCUDAMiner::workLoop()
144144
cnote << "set work; seed: " << "#" + w.seedHash.hex().substr(0, 8) + ", target: " << "#" + w.boundary.hex().substr(0, 16);
145145
if (!m_miner || m_minerSeed != w.seedHash)
146146
{
147+
unsigned device = s_devices[index()] > -1 ? s_devices[index()] : index();
148+
147149
if (s_dagLoadMode == DAG_LOAD_MODE_SEQUENTIAL)
148150
{
149151
while (s_dagLoadIndex < index()) {
150152
this_thread::sleep_for(chrono::seconds(1));
151153
}
152154
}
155+
else if (s_dagLoadMode == DAG_LOAD_MODE_SINGLE)
156+
{
157+
if (device != s_dagCreateDevice)
158+
{
159+
// wait until DAG is created on selected device
160+
while (s_dagInHostMemory == NULL) {
161+
this_thread::sleep_for(chrono::seconds(1));
162+
}
163+
}
164+
else
165+
{
166+
// reset load index
167+
s_dagLoadIndex = 0;
168+
}
169+
}
153170

154171
cnote << "Initialising miner...";
155172
m_minerSeed = w.seedHash;
156173

157174
delete m_miner;
158175
m_miner = new ethash_cuda_miner;
159176

160-
unsigned device = s_devices[index()] > -1 ? s_devices[index()] : index();
161-
162177
EthashAux::LightType light;
163178
light = EthashAux::light(w.seedHash);
164179
//bytesConstRef dagData = dag->data();
165180
bytesConstRef lightData = light->data();
166181

167-
m_miner->init(light->light, lightData.data(), lightData.size(), device);
182+
m_miner->init(light->light, lightData.data(), lightData.size(), device, (s_dagLoadMode == DAG_LOAD_MODE_SINGLE), &s_dagInHostMemory);
168183
s_dagLoadIndex++;
184+
185+
if (s_dagLoadMode == DAG_LOAD_MODE_SINGLE)
186+
{
187+
if (s_dagLoadIndex >= s_numInstances && s_dagInHostMemory)
188+
{
189+
// all devices have loaded DAG, we can free now
190+
delete[] s_dagInHostMemory;
191+
s_dagInHostMemory = NULL;
192+
193+
cout << "Freeing DAG from host" << endl;
194+
}
195+
}
169196
}
170197

171198
uint64_t upper64OfBoundary = (uint64_t)(u64)((u256)w.boundary >> 192);
172-
m_miner->search(w.headerHash.data(), upper64OfBoundary, *m_hook);
199+
uint64_t startN;
200+
if (w.exSizeBits >= 0)
201+
startN = w.startNonce | ((uint64_t)index() << (64 - 4 - w.exSizeBits)); // this can support up to 16 devices
202+
m_miner->search(w.headerHash.data(), upper64OfBoundary, *m_hook, (w.exSizeBits >= 0), startN);
173203
}
174204
catch (std::runtime_error const& _e)
175205
{
@@ -207,10 +237,12 @@ bool EthashCUDAMiner::configureGPU(
207237
unsigned _extraGPUMemory,
208238
unsigned _scheduleFlag,
209239
uint64_t _currentBlock,
210-
unsigned _dagLoadMode
240+
unsigned _dagLoadMode,
241+
unsigned _dagCreateDevice
211242
)
212243
{
213244
s_dagLoadMode = _dagLoadMode;
245+
s_dagCreateDevice = _dagCreateDevice;
214246
_blockSize = ((_blockSize + 7) / 8) * 8;
215247

216248
if (!ethash_cuda_miner::configureGPU(

libethcore/EthashCUDAMiner.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ namespace eth
5454
unsigned _extraGPUMemory,
5555
unsigned _scheduleFlag,
5656
uint64_t _currentBlock,
57-
unsigned _dagLoadMode
57+
unsigned _dagLoadMode,
58+
unsigned _dagCreateDevice
5859
);
5960
static void setNumInstances(unsigned _instances)
6061
{

0 commit comments

Comments
 (0)