Implemented verification on CPU.

This commit is contained in:
XMRig 2019-09-01 19:31:25 +07:00
parent e2d2591281
commit eef5d91606
15 changed files with 1164 additions and 999 deletions

View file

@ -56,6 +56,7 @@ public:
inline const uint8_t *result() const { return m_result; }
inline uint64_t actualDiff() const { return Job::toDiff(reinterpret_cast<const uint64_t*>(m_result)[3]); }
inline uint8_t *result() { return m_result; }
const Algorithm algorithm;
const String clientId;

View file

@ -29,73 +29,205 @@
#include <uv.h>
#include "base/io/log/Log.h"
#include "base/tools/Handle.h"
#include "net/interfaces/IJobResultListener.h"
#include "net/JobResult.h"
#include "net/JobResults.h"
#if defined(XMRIG_FEATURE_OPENCL) || defined(XMRIG_FEATURE_CUDA)
# include "base/tools/Baton.h"
# include "crypto/cn/CnCtx.h"
# include "crypto/cn/CnHash.h"
# include "crypto/cn/CryptoNight.h"
# include "crypto/common/VirtualMemory.h"
#endif
#include "base/tools/Buffer.h"
namespace xmrig {
#if defined(XMRIG_FEATURE_OPENCL) || defined(XMRIG_FEATURE_CUDA)
class JobBundle
{
public:
inline JobBundle(const Job &job, uint32_t *results, size_t count) :
job(job),
nonces(count)
{
memcpy(nonces.data(), results, sizeof(uint32_t) * count);
}
Job job;
std::vector<uint32_t> nonces;
};
class JobBaton : public Baton<uv_work_t>
{
public:
inline JobBaton(std::list<JobBundle> &&bundles, IJobResultListener *listener, bool hwAES) :
hwAES(hwAES),
listener(listener),
bundles(std::move(bundles))
{}
const bool hwAES;
IJobResultListener *listener;
std::list<JobBundle> bundles;
std::vector<JobResult> results;
uint32_t errors = 0;
};
static void getResults(JobBundle &bundle, std::vector<JobResult> &results, uint32_t &errors, bool hwAES)
{
const Algorithm &algorithm = bundle.job.algorithm();
VirtualMemory *memory = new VirtualMemory(algorithm.l3(), false);
uint8_t hash[32];
if (algorithm.family() == Algorithm::RANDOM_X) {
errors += bundle.nonces.size(); // TODO RANDOM_X
}
else if (algorithm.family() == Algorithm::ARGON2) {
errors += bundle.nonces.size(); // TODO ARGON2
}
else {
cryptonight_ctx *ctx[1];
CnCtx::create(ctx, memory->scratchpad(), memory->size(), 1);
for (uint32_t nonce : bundle.nonces) {
*bundle.job.nonce() = nonce;
CnHash::fn(algorithm, hwAES ? CnHash::AV_SINGLE : CnHash::AV_SINGLE_SOFT, Assembly::NONE)(bundle.job.blob(), bundle.job.size(), hash, ctx, bundle.job.height());
if (*reinterpret_cast<uint64_t*>(hash + 24) < bundle.job.target()) {
results.push_back(JobResult(bundle.job, nonce, hash));
}
else {
LOG_ERR("COMPUTE ERROR"); // TODO Extend information.
errors++;
}
}
}
delete memory;
}
#endif
class JobResultsPrivate
{
public:
inline JobResultsPrivate(IJobResultListener *listener) :
listener(listener)
inline JobResultsPrivate(IJobResultListener *listener, bool hwAES) :
m_hwAES(hwAES),
m_listener(listener)
{
async = new uv_async_t;
async->data = this;
m_async = new uv_async_t;
m_async->data = this;
uv_async_init(uv_default_loop(), async, JobResultsPrivate::onResult);
uv_async_init(uv_default_loop(), m_async, JobResultsPrivate::onResult);
}
inline ~JobResultsPrivate()
{
Handle::close(async);
Handle::close(m_async);
}
void submit(const JobResult &result)
inline void submit(const JobResult &result)
{
mutex.lock();
queue.push_back(result);
mutex.unlock();
std::lock_guard<std::mutex> lock(m_mutex);
m_results.push_back(result);
uv_async_send(async);
uv_async_send(m_async);
}
# if defined(XMRIG_FEATURE_OPENCL) || defined(XMRIG_FEATURE_CUDA)
inline void submit(const Job &job, uint32_t *results, size_t count)
{
std::lock_guard<std::mutex> lock(m_mutex);
m_bundles.push_back(JobBundle(job, results, count));
uv_async_send(m_async);
}
# endif
private:
static void onResult(uv_async_t *handle) { static_cast<JobResultsPrivate*>(handle->data)->submit(); }
# if defined(XMRIG_FEATURE_OPENCL) || defined(XMRIG_FEATURE_CUDA)
inline void submit()
{
std::list<JobBundle> bundles;
std::list<JobResult> results;
m_mutex.lock();
m_bundles.swap(bundles);
m_results.swap(results);
m_mutex.unlock();
for (auto result : results) {
m_listener->onJobResult(result);
}
if (bundles.empty()) {
return;
}
JobBaton *baton = new JobBaton(std::move(bundles), m_listener, m_hwAES);
uv_queue_work(uv_default_loop(), &baton->req,
[](uv_work_t *req) {
JobBaton *baton = static_cast<JobBaton*>(req->data);
for (JobBundle &bundle : baton->bundles) {
getResults(bundle, baton->results, baton->errors, baton->hwAES);
}
},
[](uv_work_t *req, int) {
JobBaton *baton = static_cast<JobBaton*>(req->data);
for (auto result : baton->results) {
baton->listener->onJobResult(result);
}
delete baton;
}
);
}
# else
inline void submit()
{
std::list<JobResult> results;
mutex.lock();
while (!queue.empty()) {
results.push_back(std::move(queue.front()));
queue.pop_front();
}
mutex.unlock();
m_mutex.lock();
m_results.swap(results);
m_mutex.unlock();
for (auto result : results) {
listener->onJobResult(result);
m_listener->onJobResult(result);
}
results.clear();
}
# endif
IJobResultListener *listener;
std::list<JobResult> queue;
std::mutex mutex;
uv_async_t *async;
private:
const bool m_hwAES;
IJobResultListener *m_listener;
std::list<JobResult> m_results;
std::mutex m_mutex;
uv_async_t *m_async;
# if defined(XMRIG_FEATURE_OPENCL) || defined(XMRIG_FEATURE_CUDA)
std::list<JobBundle> m_bundles;
# endif
};
@ -106,11 +238,11 @@ static JobResultsPrivate *handler = nullptr;
void xmrig::JobResults::setListener(IJobResultListener *listener)
void xmrig::JobResults::setListener(IJobResultListener *listener, bool hwAES)
{
assert(handler == nullptr);
handler = new JobResultsPrivate(listener);
handler = new JobResultsPrivate(listener, hwAES);
}
@ -124,6 +256,12 @@ void xmrig::JobResults::stop()
}
void xmrig::JobResults::submit(const Job &job, uint32_t nonce, const uint8_t *result)
{
submit(JobResult(job, nonce, result));
}
void xmrig::JobResults::submit(const JobResult &result)
{
assert(handler != nullptr);
@ -132,3 +270,13 @@ void xmrig::JobResults::submit(const JobResult &result)
handler->submit(result);
}
}
#if defined(XMRIG_FEATURE_OPENCL) || defined(XMRIG_FEATURE_CUDA)
void xmrig::JobResults::submit(const Job &job, uint32_t *results, size_t count)
{
if (handler) {
handler->submit(job, results, count);
}
}
#endif

View file

@ -27,19 +27,28 @@
#define XMRIG_JOBRESULTS_H
#include <stdint.h>
namespace xmrig {
class IJobResultListener;
class Job;
class JobResult;
class JobResults
{
public:
static void setListener(IJobResultListener *listener);
static void setListener(IJobResultListener *listener, bool hwAES);
static void stop();
static void submit(const Job &job, uint32_t nonce, const uint8_t *result);
static void submit(const JobResult &result);
# if defined(XMRIG_FEATURE_OPENCL) || defined(XMRIG_FEATURE_CUDA)
static void submit(const Job &job, uint32_t *results, size_t count);
# endif
};

View file

@ -60,7 +60,7 @@ xmrig::Network::Network(Controller *controller) :
m_donate(nullptr),
m_timer(nullptr)
{
JobResults::setListener(this);
JobResults::setListener(this, controller->config()->cpu().isHwAES());
controller->addListener(this);
# ifdef XMRIG_FEATURE_API