mirror of
https://github.com/GOSTSec/poolserver
synced 2025-01-29 16:04:14 +00:00
Finds blocks\!
This commit is contained in:
parent
1724c08d99
commit
ddd5fdeb2d
@ -81,11 +81,16 @@ int Server::Run()
|
||||
Stratum::Server srv(io_service);
|
||||
|
||||
// Init Bitcoin RPC
|
||||
JSONRPCConnectionInfo coninfo;
|
||||
/*JSONRPCConnectionInfo coninfo;
|
||||
coninfo.Host = "84.240.15.208";
|
||||
coninfo.Port = "8332";
|
||||
coninfo.User = "user";
|
||||
coninfo.Pass = "DYAL6bC4RUHksL6ikdx7";
|
||||
coninfo.Pass = "DYAL6bC4RUHksL6ikdx7";*/
|
||||
JSONRPCConnectionInfo coninfo;
|
||||
coninfo.Host = "127.0.0.1";
|
||||
coninfo.Port = "19001";
|
||||
coninfo.User = "test";
|
||||
coninfo.Pass = "123";
|
||||
|
||||
JSONRPC* bitcoinrpc = new JSONRPC();
|
||||
bitcoinrpc->Connect(coninfo);
|
||||
|
@ -53,7 +53,6 @@ namespace Stratum
|
||||
|
||||
void Client::OnMiningSubmit(JSON msg)
|
||||
{
|
||||
//msg = JSON::FromString("{\"params\": [\"slush.miner1\", \"00000000\", \"00000001\", \"504e86ed\", \"b2957c02\"], \"id\": 4, \"method\": \"mining.submit\"}");
|
||||
JSON params = msg["params"];
|
||||
|
||||
std::string username = params[0].GetString();
|
||||
@ -102,55 +101,61 @@ namespace Stratum
|
||||
return;
|
||||
}
|
||||
|
||||
// Get block we are working on
|
||||
// Copy block we are working on
|
||||
Bitcoin::Block block = *job.block;
|
||||
|
||||
// Start assembling the block
|
||||
timebuf >> block.time;
|
||||
noncebuf >> block.nonce;
|
||||
|
||||
// Assemble coinbase
|
||||
Bitcoin::Transaction coinbasetx;
|
||||
ByteBuffer coinbasebuf;
|
||||
coinbasebuf << job.coinbase1 << _extranonce << extranonce2 << job.coinbase2;
|
||||
coinbasebuf >> coinbasetx;
|
||||
|
||||
// Set coinbase tx
|
||||
block.tx[0] = coinbasetx;
|
||||
|
||||
ByteBuffer test;
|
||||
test << coinbasetx;
|
||||
sLog.Info(LOG_SERVER, "Coinbase: %s", Util::BinToASCII(test.Binary()).c_str());
|
||||
sLog.Info(LOG_SERVER, "Coinbase hash1: %s", Util::BinToASCII(Crypto::SHA256D(coinbasebuf.Binary())).c_str());
|
||||
sLog.Info(LOG_SERVER, "Coinbase hash2: %s", Util::BinToASCII(coinbasetx.GetHash()).c_str());
|
||||
|
||||
// Rebuilds only left side of merkle tree
|
||||
block.RebuildMerkleTree();
|
||||
sLog.Info(LOG_SERVER, "Merklehash: %s", Util::BinToASCII(block.merkleRootHash).c_str());
|
||||
|
||||
// Get block hash
|
||||
BinaryData hash = block.GetHash();
|
||||
|
||||
sLog.Info(LOG_SERVER, "Block hash: %s", Util::BinToASCII(hash).c_str());
|
||||
|
||||
// Get block target
|
||||
BigInt target(Util::BinToASCII(Util::Reverse(hash)), 16);
|
||||
|
||||
// Network target criteria
|
||||
BigInt criteria(Bitcoin::TargetFromBits(block.bits));
|
||||
BigInt diff = Bitcoin::TargetConvert(criteria);
|
||||
|
||||
BigInt diff = Bitcoin::TargetToDiff(criteria);
|
||||
std::cout << "Target: " << target << std::endl;
|
||||
std::cout << "Criteria: " << criteria << std::endl;
|
||||
std::cout << "Diff: " << diff << std::endl;
|
||||
|
||||
// Check if block meets criteria
|
||||
if (target <= criteria) {
|
||||
sLog.Info(LOG_SERVER, "We have found a block candidate!");
|
||||
|
||||
// Serialize block
|
||||
ByteBuffer blockbuf;
|
||||
blockbuf << block;
|
||||
|
||||
JSON params;
|
||||
params.Add(Util::BinToASCII(blockbuf.Binary()));
|
||||
JSON response = _bitcoinrpc->Query("submitblock", params);
|
||||
_server->SubmitBlock(block);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::OnMiningSubscribe(JSON msg)
|
||||
{
|
||||
_subscribed = true;
|
||||
|
||||
// Get extranonce from server
|
||||
_extranonce = _server->GetExtranonce();
|
||||
ByteBuffer noncebuf;
|
||||
noncebuf << _extranonce;
|
||||
|
||||
JSON notify;
|
||||
notify.Add("mining.notify");
|
||||
@ -158,8 +163,6 @@ namespace Stratum
|
||||
|
||||
JSON result;
|
||||
result.Add(notify);
|
||||
ByteBuffer noncebuf;
|
||||
noncebuf << _extranonce;
|
||||
result.Add(Util::BinToASCII(noncebuf.Binary()));
|
||||
result.Add(int64(4));
|
||||
|
||||
@ -170,14 +173,14 @@ namespace Stratum
|
||||
|
||||
SendMessage(response);
|
||||
|
||||
SendJob(true);
|
||||
SendJob(false);
|
||||
}
|
||||
|
||||
void Client::OnMiningAuthorize(JSON msg)
|
||||
{
|
||||
sLog.Info(LOG_SERVER, "Test: %s", msg["params"].ToString().c_str());
|
||||
std::string username = msg["params"][0].GetString();
|
||||
std::string password = msg["params"][1].GetString();
|
||||
|
||||
JSON response;
|
||||
response["id"] = msg["id"].GetInt();
|
||||
response["error"];
|
||||
@ -190,15 +193,51 @@ namespace Stratum
|
||||
Job job;
|
||||
job.block = _server->GetWork();
|
||||
|
||||
// Coinbase parts
|
||||
// Serialize transaction
|
||||
ByteBuffer coinbasebuf;
|
||||
coinbasebuf << job.block->tx[0];
|
||||
BinaryData coinbase = coinbasebuf.Binary();
|
||||
// tx.version + tx.in[0].outpoint.hash + tx.in[0].outpoint.n + tx.script (size) + tx.script (block height)
|
||||
|
||||
// Split coinbase
|
||||
// tx.version - 4 bytes
|
||||
// tx.in[0].outpoint.hash - 32 bytes
|
||||
// tx.in[0].outpoint.n - 4 bytes
|
||||
// tx.script (varint) - 2 bytes
|
||||
// tx.script (block height) - 4 bytes
|
||||
uint32 cbsplit = 4 + 32 + 4 + 2 + 4;
|
||||
job.coinbase1 = BinaryData(coinbase.begin(), coinbase.begin() + cbsplit);
|
||||
job.coinbase2 = BinaryData(coinbase.begin() + cbsplit + 8, coinbase.end()); // plus extranonce size
|
||||
|
||||
return job;
|
||||
}
|
||||
|
||||
void Client::_OnReceive(const boost::system::error_code& error, size_t bytes_transferred)
|
||||
{
|
||||
if (!error) {
|
||||
std::istream is(&_recvBuffer);
|
||||
std::stringstream iss;
|
||||
iss << is.rdbuf();
|
||||
sLog.Debug(LOG_SERVER, "Received: %s", iss.str().c_str());
|
||||
OnMessage(JSON::FromString(iss.str()));
|
||||
|
||||
StartRead();
|
||||
} else {
|
||||
// Client disconnected
|
||||
if ((error == asio::error::eof) || (error == asio::error::connection_reset)) {
|
||||
_server->Disconnect(shared_from_this());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client::_OnSend(const boost::system::error_code& error)
|
||||
{
|
||||
if (!error) {
|
||||
// Party
|
||||
} else {
|
||||
// Client disconnected
|
||||
if ((error == asio::error::eof) || (error == asio::error::connection_reset)) {
|
||||
_server->Disconnect(shared_from_this());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
|
||||
#define MAX_PACKET 2048
|
||||
|
||||
@ -19,7 +21,7 @@ namespace Stratum
|
||||
{
|
||||
class Server;
|
||||
|
||||
class Client
|
||||
class Client : public boost::enable_shared_from_this<Client>
|
||||
{
|
||||
public:
|
||||
Client(Server* server, asio::io_service& io_service) : _server(server), _socket(io_service), _subscribed(false), _jobid(0)
|
||||
@ -33,11 +35,13 @@ namespace Stratum
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Start reading socket
|
||||
StartRead();
|
||||
}
|
||||
|
||||
void StartRead()
|
||||
{
|
||||
// Read until newline
|
||||
boost::asio::async_read_until(
|
||||
_socket,
|
||||
_recvBuffer,
|
||||
@ -77,25 +81,17 @@ namespace Stratum
|
||||
sLog.Error(LOG_SERVER, "Method '%s' not found.", method.c_str());
|
||||
}
|
||||
|
||||
// Gets new job from the server
|
||||
Job GetJob();
|
||||
|
||||
void Disconnect()
|
||||
{
|
||||
_socket.close();
|
||||
}
|
||||
public:
|
||||
void _OnReceive(const boost::system::error_code& error, size_t bytes_transferred)
|
||||
{
|
||||
std::istream is(&_recvBuffer);
|
||||
std::stringstream iss;
|
||||
iss << is.rdbuf();
|
||||
sLog.Debug(LOG_SERVER, "Received: %s", iss.str().c_str());
|
||||
OnMessage(JSON::FromString(iss.str()));
|
||||
|
||||
StartRead();
|
||||
}
|
||||
void _OnSend(const boost::system::error_code& error)
|
||||
{
|
||||
if (error)
|
||||
sLog.Error(LOG_SERVER, "Failed to send data");
|
||||
else
|
||||
sLog.Debug(LOG_SERVER, "Data sent");
|
||||
}
|
||||
void _OnReceive(const boost::system::error_code& error, size_t bytes_transferred);
|
||||
void _OnSend(const boost::system::error_code& error);
|
||||
|
||||
private:
|
||||
// Networking
|
||||
asio::streambuf _recvBuffer;
|
||||
@ -113,6 +109,8 @@ namespace Stratum
|
||||
std::map<uint64, Job> _jobs;
|
||||
uint32 _jobid;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<Client> ClientPtr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -16,6 +16,8 @@ namespace Stratum
|
||||
BinaryData coinbase2;
|
||||
std::set<std::string> shares;
|
||||
|
||||
// Submits share to a job
|
||||
// Returns false if the same share already exists
|
||||
bool SubmitShare(BinaryData share)
|
||||
{
|
||||
std::string sharestr = Util::BinToASCII(Crypto::SHA256(share));
|
||||
|
56
src/server/poolserver/Stratum/Server.cpp
Normal file
56
src/server/poolserver/Stratum/Server.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
#include "Server.h"
|
||||
|
||||
namespace Stratum
|
||||
{
|
||||
void Server::Start(tcp::endpoint endpoint)
|
||||
{
|
||||
// Start block checking timer
|
||||
_CheckBlocksTimer();
|
||||
|
||||
_acceptor.open(endpoint.protocol());
|
||||
_acceptor.set_option(tcp::acceptor::reuse_address(true));
|
||||
_acceptor.bind(endpoint);
|
||||
_acceptor.listen();
|
||||
|
||||
_StartAccept();
|
||||
|
||||
sLog.Debug(LOG_STRATUM, "Stratum server started");
|
||||
}
|
||||
|
||||
void Server::SendToAll(JSON msg)
|
||||
{
|
||||
std::set<ClientPtr>::iterator it;
|
||||
for (it = _clients.begin(); it != _clients.end(); ++it)
|
||||
_io_service.post(boost::bind(&Client::SendMessage, (*it), msg));
|
||||
}
|
||||
|
||||
void Server::ResetWork()
|
||||
{
|
||||
std::set<ClientPtr>::iterator it;
|
||||
for (it = _clients.begin(); it != _clients.end(); ++it)
|
||||
_io_service.post(boost::bind(&Client::SendJob, (*it), true));
|
||||
}
|
||||
|
||||
bool Server::SubmitBlock(Bitcoin::Block block)
|
||||
{
|
||||
// Serialize block
|
||||
ByteBuffer blockbuf;
|
||||
blockbuf << block;
|
||||
|
||||
try {
|
||||
JSON params;
|
||||
params.Add(Util::BinToASCII(blockbuf.Binary()));
|
||||
JSON response = _bitcoinrpc->Query("submitblock", params);
|
||||
|
||||
if (response["result"].GetType() == JSON_NULL) {
|
||||
sLog.Info(LOG_STRATUM, "Block accepted! YAY!");
|
||||
_io_service.post(boost::bind(&Server::_CheckBlocks, this));
|
||||
return true;
|
||||
} else {
|
||||
sLog.Info(LOG_STRATUM, "Block rejected! Booooo");
|
||||
}
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -13,7 +13,8 @@
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <list>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <set>
|
||||
|
||||
using namespace boost;
|
||||
using namespace boost::asio::ip;
|
||||
@ -36,66 +37,64 @@ namespace Stratum
|
||||
|
||||
~Server()
|
||||
{
|
||||
std::list<Client*>::iterator it;
|
||||
std::set<ClientPtr>::iterator it;
|
||||
for (it = _clients.begin(); it != _clients.end(); ++it)
|
||||
delete *it;
|
||||
(*it)->Disconnect();
|
||||
}
|
||||
|
||||
void Start(tcp::endpoint endpoint)
|
||||
{
|
||||
_CheckBlocks();
|
||||
|
||||
_acceptor.open(endpoint.protocol());
|
||||
_acceptor.set_option(tcp::acceptor::reuse_address(true));
|
||||
_acceptor.bind(endpoint);
|
||||
_acceptor.listen();
|
||||
|
||||
_StartAccept();
|
||||
|
||||
sLog.Debug(LOG_STRATUM, "Stratum server started");
|
||||
}
|
||||
// Starts accepting connections
|
||||
void Start(tcp::endpoint endpoint);
|
||||
|
||||
void SetBitcoinRPC(JSONRPC* bitcoinrpc)
|
||||
{
|
||||
_bitcoinrpc = bitcoinrpc;
|
||||
}
|
||||
|
||||
void SendToAll(JSON msg)
|
||||
{
|
||||
std::list<Client*>::iterator it;
|
||||
for (it = _clients.begin(); it != _clients.end(); ++it)
|
||||
(*it)->SendMessage(msg);
|
||||
}
|
||||
// Sends message to all clients
|
||||
void SendToAll(JSON msg);
|
||||
|
||||
// Returns new extranonce
|
||||
uint32 GetExtranonce()
|
||||
{
|
||||
//return 134217730;
|
||||
return 33554440;
|
||||
//return _extranonce++;
|
||||
return _extranonce++;
|
||||
}
|
||||
|
||||
// Returns current work
|
||||
Bitcoin::BlockPtr GetWork()
|
||||
{
|
||||
boost::lock_guard<boost::mutex> guard(_mtx_workupdate);
|
||||
return _currentWork;
|
||||
}
|
||||
|
||||
// Resets work for all clients
|
||||
void ResetWork();
|
||||
|
||||
// Submits block to bitcoind
|
||||
bool SubmitBlock(Bitcoin::Block block);
|
||||
|
||||
// Disconnects client
|
||||
void Disconnect(ClientPtr client)
|
||||
{
|
||||
client->Disconnect();
|
||||
_clients.erase(client);
|
||||
}
|
||||
|
||||
private:
|
||||
void _StartAccept()
|
||||
{
|
||||
Client* client = new Client(this, _io_service);
|
||||
ClientPtr client = ClientPtr(new Client(this, _io_service));
|
||||
|
||||
_acceptor.async_accept(client->GetSocket(), boost::bind(&Server::_OnAccept, this, client, asio::placeholders::error));
|
||||
}
|
||||
|
||||
void _OnAccept(Client* client, const boost::system::error_code& error)
|
||||
void _OnAccept(ClientPtr client, const boost::system::error_code& error)
|
||||
{
|
||||
if (!error) {
|
||||
sLog.Debug(LOG_STRATUM, "New stratum client accepted");
|
||||
client->Start();
|
||||
_clients.push_back(client);
|
||||
_clients.insert(client);
|
||||
} else {
|
||||
sLog.Debug(LOG_STRATUM, "Failed to accept stratum client");
|
||||
delete client;
|
||||
}
|
||||
|
||||
_StartAccept();
|
||||
@ -118,30 +117,40 @@ namespace Stratum
|
||||
block->tx.push_back(CreateCoinbaseTX(_blockHeight, _pubkey, response["coinbasevalue"].GetInt()));
|
||||
|
||||
// Add other transactions
|
||||
/*JSON trans = response["transactions"];
|
||||
JSON trans = response["transactions"];
|
||||
for (uint64 i = 0; i < trans.Size(); ++i) {
|
||||
ByteBuffer txbuf(Util::ASCIIToBin(trans[i]["data"].GetString()));
|
||||
Bitcoin::Transaction tx;
|
||||
txbuf >> tx;
|
||||
block->tx.push_back(tx);
|
||||
}*/
|
||||
/*Bitcoin::BlockPtr block = Bitcoin::BlockPtr(new Bitcoin::Block());
|
||||
block->version = 2;
|
||||
block->prevBlockHash = Util::Reverse(Util::ASCIIToBin("00000000440b921e1b77c6c0487ae5616de67f788f44ae2a5af6e2194d16b6f8"));
|
||||
block->time = 1347323629;
|
||||
block->bits = 472564911;
|
||||
block->tx.push_back(CreateCoinbaseTX(25096, _pubkey, 50));*/
|
||||
}
|
||||
|
||||
// Genrate merkle tree
|
||||
block->BuildMerkleTree();
|
||||
|
||||
// Set current work
|
||||
_mtx_workupdate.lock();
|
||||
_currentWork = block;
|
||||
_mtx_workupdate.unlock();
|
||||
|
||||
// Requests all clients to reset work
|
||||
if (reset)
|
||||
ResetWork();
|
||||
}
|
||||
|
||||
void _CheckBlocksTimer()
|
||||
{
|
||||
_CheckBlocks();
|
||||
_blockCheckTimer.expires_from_now(boost::posix_time::milliseconds(sConfig.Get<uint32>("StratumBlockCheckTime")));
|
||||
_blockCheckTimer.async_wait(boost::bind(&Server::_CheckBlocksTimer, this));
|
||||
}
|
||||
|
||||
void _CheckBlocks()
|
||||
{
|
||||
sLog.Debug(LOG_STRATUM, "Checking for new blocks...");
|
||||
// Might be called twice from timer and when block is found
|
||||
boost::lock_guard<boost::mutex> guard(_mtx_checkblock);
|
||||
|
||||
sLog.Debug(LOG_STRATUM, "Clients: %u", _clients.size());
|
||||
|
||||
JSON response = _bitcoinrpc->Query("getinfo");
|
||||
uint32 curBlock = response["blocks"].GetInt();
|
||||
@ -151,9 +160,6 @@ namespace Stratum
|
||||
_blockHeight = curBlock;
|
||||
_UpdateWork(true);
|
||||
}
|
||||
|
||||
_blockCheckTimer.expires_from_now(boost::posix_time::milliseconds(sConfig.Get<uint32>("StratumBlockCheckTime")));
|
||||
_blockCheckTimer.async_wait(boost::bind(&Server::_CheckBlocks, this));
|
||||
}
|
||||
|
||||
Bitcoin::Transaction CreateCoinbaseTX(uint32 blockHeight, BinaryData pubkey, int64 value)
|
||||
@ -186,10 +192,14 @@ namespace Stratum
|
||||
}
|
||||
private:
|
||||
// Network
|
||||
std::list<Client*> _clients;
|
||||
std::set<ClientPtr> _clients;
|
||||
asio::io_service& _io_service;
|
||||
tcp::acceptor _acceptor;
|
||||
|
||||
// Mutexes
|
||||
boost::mutex _mtx_checkblock;
|
||||
boost::mutex _mtx_workupdate;
|
||||
|
||||
// RPC
|
||||
JSONRPC* _bitcoinrpc;
|
||||
|
||||
|
@ -10,12 +10,18 @@
|
||||
|
||||
namespace Bitcoin
|
||||
{
|
||||
inline BigInt TargetConvert(BigInt val)
|
||||
inline BigInt TargetToDiff(BigInt val)
|
||||
{
|
||||
static BigInt c("0x00000000ffff0000000000000000000000000000000000000000000000000000");
|
||||
return (c / val);
|
||||
}
|
||||
|
||||
inline BigInt DiffToTarget(BigInt val)
|
||||
{
|
||||
// Algebra says that it is the same!
|
||||
return TargetToDiff(val);
|
||||
}
|
||||
|
||||
inline BigInt TargetFromBits(uint32 bits)
|
||||
{
|
||||
uint8 nbytes = (bits >> 24) & 0xFF;
|
||||
|
Loading…
x
Reference in New Issue
Block a user