You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

211 lines
5.8 KiB

9 years ago
#include "EthStratumClient.h"
9 years ago
using boost::asio::ip::tcp;
9 years ago
EthStratumClient::EthStratumClient(GenericFarm<EthashProofOfWork> * f, string const & host, string const & port, string const & user, string const & pass)
9 years ago
: m_socket(m_io_service)
{
m_host = host;
m_port = port;
m_user = user;
m_pass = pass;
9 years ago
m_authorized = false;
m_running = true;
m_precompute = true;
p_farm = f;
9 years ago
connect();
}
EthStratumClient::~EthStratumClient()
{
}
void EthStratumClient::connect()
{
9 years ago
tcp::resolver r(m_io_service);
tcp::resolver::query q(m_host, m_port);
9 years ago
r.async_resolve(q, boost::bind(&EthStratumClient::resolve_handler,
this, boost::asio::placeholders::error,
boost::asio::placeholders::iterator));
9 years ago
boost::thread t(boost::bind(&boost::asio::io_service::run, &m_io_service));
}
9 years ago
void EthStratumClient::disconnect()
{
cnote << "Disconnecting";
m_running = false;
m_socket.close();
m_io_service.stop();
}
void EthStratumClient::resolve_handler(const boost::system::error_code& ec, tcp::resolver::iterator i)
{
if (!ec)
{
async_connect(m_socket, i, boost::bind(&EthStratumClient::connect_handler,
this, boost::asio::placeholders::error,
boost::asio::placeholders::iterator));
}
else
{
9 years ago
cerr << "Could not resolve host" << m_host + ":" + m_port + ", " << ec.message();
disconnect();
}
}
void EthStratumClient::connect_handler(const boost::system::error_code& ec, tcp::resolver::iterator i)
{
if (!ec)
{
cnote << "Connected to stratum server " << m_host << ":" << m_port;
std::ostream os(&m_requestBuffer);
os << "{\"id\": 1, \"method\": \"mining.subscribe\", \"params\": []}\n";
9 years ago
async_write(m_socket, m_requestBuffer,
9 years ago
boost::bind(&EthStratumClient::handleResponse, this,
boost::asio::placeholders::error));
}
else
{
9 years ago
cwarn << "Could not connect to stratum server " << m_host << ":" << m_port << ", " << ec.message();
disconnect();
}
}
9 years ago
void EthStratumClient::handleResponse(const boost::system::error_code& ec) {
if (!ec)
{
async_read_until(m_socket, m_responseBuffer, "\n",
boost::bind(&EthStratumClient::readResponse, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
else
{
9 years ago
cwarn << "Handle response failed: " << ec.message();
9 years ago
}
}
void EthStratumClient::readResponse(const boost::system::error_code& ec, std::size_t bytes_transferred)
{
if (!ec)
{
std::istream is(&m_responseBuffer);
std::string response;
getline(is, response);
9 years ago
//cnote << response;
9 years ago
Json::Value responseObject;
Json::Reader reader;
if (reader.parse(response.c_str(), responseObject))
{
9 years ago
Json::Value error = responseObject.get("error", NULL);
if (error.isArray())
9 years ago
{
9 years ago
string msg = error.get(1, "Unknown error").asString();
cnote << msg;
9 years ago
}
std::ostream os(&m_requestBuffer);
9 years ago
Json::Value params;
9 years ago
int id = responseObject.get("id", NULL).asInt();
switch (id)
{
case 1:
9 years ago
cnote << "Subscribed to stratum server";
9 years ago
os << "{\"id\": 2, \"method\": \"mining.authorize\", \"params\": [\"" << m_user << "\",\"" << m_pass << "\"]}\n";
9 years ago
async_write(m_socket, m_requestBuffer,
boost::bind(&EthStratumClient::handleResponse, this,
boost::asio::placeholders::error));
9 years ago
break;
case 2:
9 years ago
m_authorized = responseObject.get("result", NULL).asBool();
if (!m_authorized)
{
disconnect();
return;
}
cnote << "Authorized worker " << m_user;
9 years ago
break;
default:
string method = responseObject.get("method", "").asString();
9 years ago
if (method == "mining.notify")
{
params = responseObject.get("params", NULL);
if (params.isArray())
{
string jobNumber = params.get((Json::Value::ArrayIndex)0, "").asString();
string sHeaderHash = params.get((Json::Value::ArrayIndex)1, "").asString();
string sSeedHash = params.get((Json::Value::ArrayIndex)2, "").asString();
string sShareTarget = params.get((Json::Value::ArrayIndex)3, "").asString();
bool cleanJobs = params.get((Json::Value::ArrayIndex)4, "").asBool();
if (sHeaderHash != "" && sSeedHash != "" && sShareTarget != "")
{
cnote << "Received new job #" + jobNumber;
cnote << "Header hash: 0x" + sHeaderHash;
cnote << "Seed hash: 0x" + sSeedHash;
cnote << "Share target: 0x" + sShareTarget;
h256 seedHash = h256(sSeedHash);
h256 headerHash = h256(sHeaderHash);
EthashAux::FullType dag;
if (seedHash != m_current.seedHash)
cnote << "Grabbing DAG for" << seedHash;
if (!(dag = EthashAux::full(seedHash, true, [&](unsigned _pc){ cout << "\rCreating DAG. " << _pc << "% done..." << flush; return 0; })))
BOOST_THROW_EXCEPTION(DAGCreationFailure());
if (m_precompute)
EthashAux::computeFull(sha3(seedHash), true);
if (headerHash != m_current.headerHash)
{
m_current.headerHash = h256(sHeaderHash);
m_current.seedHash = seedHash;
m_current.boundary = h256(sShareTarget, h256::AlignRight);
p_farm->setWork(m_current);
}
}
}
}
else if (method == "mining.set_difficulty")
{
}
else if (method == "client.get_version")
{
os << "{\"error\": null, \"id\" : "<< id <<", \"result\" : \"" << ETH_PROJECT_VERSION << "\"}";
async_write(m_socket, m_requestBuffer,
boost::bind(&EthStratumClient::handleResponse, this,
boost::asio::placeholders::error));
}
9 years ago
break;
}
async_read_until(m_socket, m_responseBuffer, "\n",
boost::bind(&EthStratumClient::readResponse, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
else
{
9 years ago
cwarn << "Parse response failed: " << reader.getFormattedErrorMessages();
9 years ago
}
}
else
{
9 years ago
cwarn << "Read response failed: " << ec.message();
9 years ago
}
}