diff --git a/src/server/poolserver/Server/Server.cpp b/src/server/poolserver/Server/Server.cpp index 5cdeddc..3e263b5 100644 --- a/src/server/poolserver/Server/Server.cpp +++ b/src/server/poolserver/Server/Server.cpp @@ -34,7 +34,8 @@ int Server::Run() sLog.Info(LOG_SERVER, "Server is starting..."); //InitDatabase(); - std::vector test = Util::ASCIIToBin("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + + /*std::vector test = Util::ASCIIToBin("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); sLog.Info(LOG_SERVER, "Hash: %s", Util::BinToASCII(Crypto::SHA256D(test)).c_str()); sLog.Info(LOG_SERVER, "RevHash: %s", Util::BinToASCII(Crypto::SHA256D(Util::Reverse(test))).c_str()); @@ -56,7 +57,7 @@ int Server::Run() block.tx.resize(1); block.tx[0] = trans; block.BuildMerkleTree(); - sLog.Info(LOG_SERVER, "Hash: %s", Util::BinToASCII(block.merkleRootHash).c_str()); + sLog.Info(LOG_SERVER, "Hash: %s", Util::BinToASCII(block.merkleRootHash).c_str());*/ /*ByteBuffer buf(Util::ASCIIToBin("01000000010c432f4fb3e871a8bda638350b3d5c698cf431db8d6031b53e3fb5159e59d4a90000000000ffffffff0100f2052a010000001976a9143744841e13b90b4aca16fe793a7f88da3a23cc7188ac00000000")); @@ -78,8 +79,8 @@ int Server::Run() // Init Bitcoin RPC JSONRPCConnectionInfo coninfo; coninfo.Host = "84.240.15.208"; - coninfo.Port = "9902"; - coninfo.User = "ppcuser"; + coninfo.Port = "8332"; + coninfo.User = "user"; coninfo.Pass = "DYAL6bC4RUHksL6ikdx7"; JSONRPC* bitcoinrpc = new JSONRPC(); diff --git a/src/server/poolserver/Stratum/Client.cpp b/src/server/poolserver/Stratum/Client.cpp new file mode 100644 index 0000000..7508b17 --- /dev/null +++ b/src/server/poolserver/Stratum/Client.cpp @@ -0,0 +1,54 @@ +#include "Server.h" +#include "Client.h" + +namespace Stratum +{ + void Client::OnMiningSubscribe(JSON msg) + { + _subscribed = true; + _extranonce = _server->GetExtranonce(); + + Job job = GetJob(); + _jobs.push_back(job); + + JSON response; + response.Set("id", msg["id"].Get()); + response.Set("error", NULL); + + JSON miningdiff; + miningdiff.Add("mining.set_difficulty"); + JSON lala; + lala.Set("", 1); + miningdiff.Add(lala); + + JSON notify; + notify.Add("mining.notify"); + notify.Add("abc"); + + JSON something; + something.Add(miningdiff); + something.Add(notify); + + JSON result; + result.Add(something); + ByteBuffer noncebuf; + noncebuf << _extranonce; + JSON omg; + omg.Set("", Util::BinToASCII(noncebuf.Binary())); + result.Add(omg); + JSON shit; + shit.Set("", 4); + result.Add(shit); + + response.Set("result", result); + + SendMessage(response); + } + + Job Client::GetJob() + { + Job job; + job.work = _server->GetWork(); + return job; + } +} diff --git a/src/server/poolserver/Stratum/Client.h b/src/server/poolserver/Stratum/Client.h index 26820ed..bad99ba 100644 --- a/src/server/poolserver/Stratum/Client.h +++ b/src/server/poolserver/Stratum/Client.h @@ -4,6 +4,8 @@ #include "Common.h" #include "Log.h" #include "JSON.h" +#include "Server.h" +#include "Job.h" #include #include @@ -15,10 +17,12 @@ using namespace boost::asio::ip; namespace Stratum { + class Server; + class Client { public: - Client(asio::io_service& io_service) : _socket(io_service) + Client(Server* server, asio::io_service& io_service) : _server(server), _socket(io_service), _subscribed(false) { } @@ -36,17 +40,43 @@ namespace Stratum boost::bind(&Client::_OnReceive, this, asio::placeholders::error, asio::placeholders::bytes_transferred)); } + void SendJob() + { + } + void SendMessage(JSON msg) { std::string data = msg.ToString(); + sLog.Debug(LOG_SERVER, "Sending: %s", data.c_str()); _socket.send(boost::asio::buffer(data.c_str(), data.length())); } + void OnMiningSubscribe(JSON msg); + + void OnMiningAuthorize(JSON msg) + { + std::string username = msg["result"][0].Get(); + JSON response; + response.Set("id", msg["id"].Get()); + response.Set("error", NULL); + response.Set("result", true); + SendMessage(response); + } + void OnMessage(JSON msg) { - std::string method = msg.Get("method"); + std::string method = msg["method"].Get(); sLog.Debug(LOG_SERVER, "Method: %s", method.c_str()); + + if (method.compare("mining.subscribe") == 0) + OnMiningSubscribe(msg); + else if (method.compare("mining.authorize") == 0) + OnMiningAuthorize(msg); + else + sLog.Error(LOG_SERVER, "Method '%s' not found.", method.c_str()); } + + Job GetJob(); public: void _OnReceive(const boost::system::error_code& error, size_t bytes_transferred) { @@ -57,8 +87,20 @@ namespace Stratum OnMessage(JSON::FromString(iss.str())); } private: + // Networking asio::streambuf _recvBuffer; tcp::socket _socket; + + // Pointer to server + Stratum::Server* _server; + + // Authorization + std::vector _workers; + + // Jobs + bool _subscribed; + uint32 _extranonce; + std::vector _jobs; }; } diff --git a/src/server/poolserver/Stratum/Job.h b/src/server/poolserver/Stratum/Job.h new file mode 100644 index 0000000..673a17e --- /dev/null +++ b/src/server/poolserver/Stratum/Job.h @@ -0,0 +1,15 @@ +#ifndef STRATUM_JOB_H_ +#define STRATUM_JOB_H_ + +#include "Bitcoin.h" + +namespace Stratum +{ + class Job + { + public: + Bitcoin::BlockPtr work; + }; +} + +#endif diff --git a/src/server/poolserver/Stratum/Server.h b/src/server/poolserver/Stratum/Server.h index 7879e7e..b7e3d14 100644 --- a/src/server/poolserver/Stratum/Server.h +++ b/src/server/poolserver/Stratum/Server.h @@ -9,6 +9,7 @@ #include "JSONRPC.h" #include "Bitcoin.h" #include "Util.h" +#include "ByteBuffer.h" #include #include @@ -28,7 +29,7 @@ namespace Stratum class Server { public: - Server(asio::io_service& io_service) : _io_service(io_service), _acceptor(io_service), _blockCheckTimer(io_service), _blockHeight(0) + Server(asio::io_service& io_service) : _io_service(io_service), _acceptor(io_service), _blockCheckTimer(io_service), _blockHeight(0), _extranonce(0) { } @@ -65,10 +66,20 @@ namespace Stratum (*it)->SendMessage(msg); } + uint32 GetExtranonce() + { + return _extranonce++; + } + + Bitcoin::BlockPtr GetWork() + { + return _currentWork; + } + private: void _StartAccept() { - Client* client = new Client(_io_service); + Client* client = new Client(this, _io_service); _acceptor.async_accept(client->GetSocket(), boost::bind(&Server::_OnAccept, this, client, asio::placeholders::error)); } @@ -91,10 +102,32 @@ namespace Stratum { JSON response = _bitcoinrpc->Query("getblocktemplate"); - Bitcoin::Block* block = new Bitcoin::Block(); - block->version = response.Get("version"); - block->prevBlockHash = Util::ASCIIToBin(response.Get("previousblockhash")); + Bitcoin::BlockPtr block = Bitcoin::BlockPtr(new Bitcoin::Block()); + + block->version = response["version"].Get();; + block->prevBlockHash = Util::ASCIIToBin(response["previousblockhash"].Get()); + + // Set bits + ByteBuffer bitbuf(Util::ASCIIToBin(response["bits"].Get())); + bitbuf >> block->bits; + + // Add coinbase tx + block->tx.push_back(CreateCoinbaseTX(_blockHeight, _pubkey, response["coinbasevalue"].Get())); + + // Add other transactions + JSON trans = response["transactions"]; + for (uint64 i = 0; i < trans.Size(); ++i) { + ByteBuffer txbuf(Util::ASCIIToBin(trans[i]["data"].Get())); + Bitcoin::Transaction tx; + txbuf >> tx; + block->tx.push_back(tx); + } + + // Genrate merkle tree + block->BuildMerkleTree(); + // Set current work + _currentWork = block; } void _CheckBlocks() @@ -102,7 +135,7 @@ namespace Stratum sLog.Debug(LOG_STRATUM, "Checking for new blocks..."); JSON response = _bitcoinrpc->Query("getinfo"); - uint32 curBlock = response.Get("blocks"); + uint32 curBlock = response["blocks"].Get(); if (curBlock > _blockHeight) { sLog.Debug(LOG_STRATUM, "New block on network! Height: %u", curBlock); @@ -113,6 +146,33 @@ namespace Stratum _blockCheckTimer.expires_from_now(boost::posix_time::milliseconds(sConfig.Get("StratumBlockCheckTime"))); _blockCheckTimer.async_wait(boost::bind(&Server::_CheckBlocks, this)); } + + Bitcoin::Transaction CreateCoinbaseTX(uint32 blockHeight, BinaryData pubkey, int64 value) + { + ByteBuffer scriptsig; + scriptsig << _blockHeight; + + Bitcoin::OutPoint outpoint; + outpoint.hash.resize(32, 0); + outpoint.n = 0xFFFFFFFF; + + Bitcoin::TxIn txin; + txin.prevout = outpoint; + txin.script = scriptsig.Binary(); + txin.n = 0; + + Bitcoin::TxOut txout; + txout.value = value; + txout.scriptPubKey = Bitcoin::Script(pubkey) + Bitcoin::OP_CHECKSIG; + + Bitcoin::Transaction tx; + tx.version = 1; + tx.in.push_back(txin); + tx.out.push_back(txout); + tx.lockTime = 0; + + return tx; + } private: // Network std::list _clients; @@ -123,11 +183,13 @@ namespace Stratum JSONRPC* _bitcoinrpc; // Bitcoin info + BinaryData _pubkey; asio::deadline_timer _blockCheckTimer; uint32 _blockHeight; // Work - Bitcoin::Block* _currentWork; + Bitcoin::BlockPtr _currentWork; + uint32 _extranonce; }; } diff --git a/src/server/shared/Bitcoin/Bitcoin.h b/src/server/shared/Bitcoin/Bitcoin.h index 3b10650..721e52c 100644 --- a/src/server/shared/Bitcoin/Bitcoin.h +++ b/src/server/shared/Bitcoin/Bitcoin.h @@ -3,5 +3,7 @@ #include "Block.h" #include "Transaction.h" +#include "VarInt.h" +#include "Script.h" #endif diff --git a/src/server/shared/Bitcoin/Block.h b/src/server/shared/Bitcoin/Block.h index 862e1c4..6736996 100644 --- a/src/server/shared/Bitcoin/Block.h +++ b/src/server/shared/Bitcoin/Block.h @@ -7,16 +7,14 @@ #include #include -#include "Log.h" - namespace Bitcoin { class BlockHeader { public: uint32 version; - std::vector prevBlockHash; - std::vector merkleRootHash; + BinaryData prevBlockHash; + BinaryData merkleRootHash; uint32 time; uint32 bits; uint32 nonce; @@ -29,7 +27,7 @@ namespace Bitcoin std::vector tx; // Other data - std::vector > merkleTree; + std::vector merkleTree; void BuildMerkleTree() { @@ -61,6 +59,8 @@ namespace Bitcoin } }; + typedef boost::shared_ptr BlockPtr; + // Block Serialization (Implementation in Serialization.cpp) ByteBuffer& operator<<(ByteBuffer& a, Block& b); ByteBuffer& operator>>(ByteBuffer& a, Block& b); diff --git a/src/server/shared/Bitcoin/Script.h b/src/server/shared/Bitcoin/Script.h index 859cbe2..df58ad2 100644 --- a/src/server/shared/Bitcoin/Script.h +++ b/src/server/shared/Bitcoin/Script.h @@ -23,18 +23,18 @@ namespace Bitcoin { public: Script() {} - Script(std::vector data) : script(data) {} + Script(BinaryData data) : script(data) {} - std::vector script; + BinaryData script; const Script operator+(const Script& other) { - std::vector tmp = script; + BinaryData tmp = script; tmp.insert(tmp.end(), other.script.begin(), other.script.end()); return Script(tmp); } - const Script operator+(const std::vector data) + const Script operator+(const BinaryData data) { Script tmp(script); diff --git a/src/server/shared/Bitcoin/Serialization.cpp b/src/server/shared/Bitcoin/Serialization.cpp index a8d5096..a54756f 100644 --- a/src/server/shared/Bitcoin/Serialization.cpp +++ b/src/server/shared/Bitcoin/Serialization.cpp @@ -48,7 +48,7 @@ ByteBuffer& Bitcoin::operator>>(ByteBuffer& a, Script& b) { VarInt size; a >> size; - b.script = a.ReadBytes(size); + b.script = a.ReadBinary(size); return a; } @@ -61,7 +61,7 @@ ByteBuffer& Bitcoin::operator<<(ByteBuffer& a, OutPoint& b) } ByteBuffer& Bitcoin::operator>>(ByteBuffer& a, OutPoint& b) { - b.hash = a.ReadBytes(32); + b.hash = a.ReadBinary(32); a >> b.n; return a; } @@ -163,8 +163,8 @@ ByteBuffer& Bitcoin::operator<<(ByteBuffer& a, Block& b) ByteBuffer& Bitcoin::operator>>(ByteBuffer& a, Block& b) { a >> b.version; - b.prevBlockHash = a.ReadBytes(32); - b.merkleRootHash = a.ReadBytes(32); + b.prevBlockHash = a.ReadBinary(32); + b.merkleRootHash = a.ReadBinary(32); a >> b.time; a >> b.bits; a >> b.nonce; diff --git a/src/server/shared/Bitcoin/Transaction.cpp b/src/server/shared/Bitcoin/Transaction.cpp index 7568798..307d44e 100644 --- a/src/server/shared/Bitcoin/Transaction.cpp +++ b/src/server/shared/Bitcoin/Transaction.cpp @@ -3,10 +3,10 @@ namespace Bitcoin { - std::vector Transaction::GetHash() + BinaryData Transaction::GetHash() { ByteBuffer buf; buf << *this; - return Crypto::SHA256D(buf.Bytes()); + return Crypto::SHA256D(buf.Binary()); } } diff --git a/src/server/shared/Bitcoin/Transaction.h b/src/server/shared/Bitcoin/Transaction.h index 1fe8014..9b6c584 100644 --- a/src/server/shared/Bitcoin/Transaction.h +++ b/src/server/shared/Bitcoin/Transaction.h @@ -12,7 +12,7 @@ namespace Bitcoin class OutPoint { public: - std::vector hash; + BinaryData hash; uint32 n; }; @@ -51,7 +51,7 @@ namespace Bitcoin std::vector out; uint32 lockTime; - std::vector GetHash(); + BinaryData GetHash(); }; // Transaction Serialization (Implementation in Serialization.cpp) diff --git a/src/server/shared/ByteBuffer.h b/src/server/shared/ByteBuffer.h index bec2094..792c854 100644 --- a/src/server/shared/ByteBuffer.h +++ b/src/server/shared/ByteBuffer.h @@ -8,14 +8,14 @@ class ByteBuffer { public: ByteBuffer(): pointer(0) {} - ByteBuffer(std::vector data): pointer(0), vec(data) {} + ByteBuffer(BinaryData data): pointer(0), vec(data) {} ByteBuffer& operator<<(ByteBuffer& b) { Append(b.vec); return *this; } - ByteBuffer& operator<<(std::vector& b) + ByteBuffer& operator<<(BinaryData& b) { Append(b); return *this; @@ -42,18 +42,18 @@ public: vec.push_back(data >> (i * 8)); } - void Append(std::vector data) + void Append(BinaryData data) { vec.insert(vec.end(), data.begin(), data.end()); } - std::vector ReadBytes(size_t size) + BinaryData ReadBinary(size_t size) { if (vec.size() < pointer+size) - return std::vector(); + return BinaryData(); pointer += size; - return std::vector(vec.begin()+pointer-size, vec.begin()+pointer); + return BinaryData(vec.begin()+pointer-size, vec.begin()+pointer); } template @@ -73,13 +73,13 @@ public: return data; } - std::vector Bytes() + BinaryData Binary() { return vec; } uint64 pointer; - std::vector vec; + BinaryData vec; }; #endif diff --git a/src/server/shared/Common.h b/src/server/shared/Common.h index 579491b..8fdbd30 100644 --- a/src/server/shared/Common.h +++ b/src/server/shared/Common.h @@ -2,6 +2,7 @@ #define COMMON_H_ #include +#include typedef uint8_t uint8; typedef uint16_t uint16; @@ -15,4 +16,6 @@ typedef int64_t int64; typedef uint8_t byte; +typedef std::vector BinaryData; + #endif diff --git a/src/server/shared/Crypto.cpp b/src/server/shared/Crypto.cpp index 52253eb..f29aabe 100644 --- a/src/server/shared/Crypto.cpp +++ b/src/server/shared/Crypto.cpp @@ -2,7 +2,7 @@ namespace Crypto { - std::vector SHA256(std::vector data) + BinaryData SHA256(BinaryData data) { std::vector hash; hash.resize(SHA256_DIGEST_LENGTH); @@ -13,12 +13,12 @@ namespace Crypto return std::vector(hash.begin(), hash.end()); } - std::vector SHA256(std::string data) + BinaryData SHA256(std::string data) { - return SHA256(std::vector(data.begin(), data.end())); + return SHA256(BinaryData(data.begin(), data.end())); } - std::vector SHA256D(std::vector data) + BinaryData SHA256D(BinaryData data) { return SHA256(SHA256(data)); } diff --git a/src/server/shared/Crypto.h b/src/server/shared/Crypto.h index 55b4037..46d2743 100644 --- a/src/server/shared/Crypto.h +++ b/src/server/shared/Crypto.h @@ -9,9 +9,9 @@ namespace Crypto { - std::vector SHA256(std::vector data); - std::vector SHA256(std::string data); - std::vector SHA256D(std::vector data); + BinaryData SHA256(BinaryData data); + BinaryData SHA256(std::string data); + BinaryData SHA256D(BinaryData data); } #endif diff --git a/src/server/shared/JSON/JSON.h b/src/server/shared/JSON/JSON.h index b8c0349..382d319 100644 --- a/src/server/shared/JSON/JSON.h +++ b/src/server/shared/JSON/JSON.h @@ -1,6 +1,7 @@ #ifndef JSON_H_ #define JSON_H_ +#include "Common.h" #include #include #include @@ -25,9 +26,9 @@ public: } template - T Get(std::string key) + T Get() { - return pt->get(key); + return pt->get_value(); } JSON operator[] (std::string key) @@ -37,7 +38,7 @@ public: return json; } - JSON operator[] (int index) + JSON operator[] (uint32 index) { JSON json(false); boost::property_tree::ptree::iterator it = pt->begin(); @@ -71,6 +72,7 @@ public: bool _base; }; + template<> inline void JSON::Set(std::string key, JSON value) { diff --git a/src/server/shared/JSONRPC/JSONRPC.cpp b/src/server/shared/JSONRPC/JSONRPC.cpp index d18a21b..a8fd2f5 100644 --- a/src/server/shared/JSONRPC/JSONRPC.cpp +++ b/src/server/shared/JSONRPC/JSONRPC.cpp @@ -107,18 +107,21 @@ JSON JSONRPC::Query(std::string method, JSON params) std::string jsonresponse = ""; + if (_sock.available()) + boost::asio::read_until(_sock, response, '\n'); + if (response.size() > 0) { std::ostringstream oss; oss << &response; jsonresponse += oss.str(); } - + // Read until EOF, writing data to output as we go. - while(boost::asio::read(_sock, response, boost::asio::transfer_at_least(1), error)){ + /*while (_sock.available() && boost::asio::read(_sock, response, error)){ std::ostringstream oss; oss << &response; jsonresponse += oss.str(); - } + }*/ _sock.close(); diff --git a/src/server/shared/Util.cpp b/src/server/shared/Util.cpp index ee71452..9fed2ac 100644 --- a/src/server/shared/Util.cpp +++ b/src/server/shared/Util.cpp @@ -18,6 +18,19 @@ std::string Util::Date(const char* format, bool utc) return ss.str(); } +uint32 Util::Date(bool utc) +{ + boost::posix_time::ptime now; + if (utc) + now = boost::posix_time::second_clock::universal_time(); + else + now = boost::posix_time::second_clock::local_time(); + + boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1)); + boost::posix_time::time_duration diff = now - epoch; + return diff.total_seconds(); +} + std::string Util::ToBase64(std::string input, bool linebreaks) { uint32_t writePaddChars = (3 - input.length() % 3) % 3; @@ -55,9 +68,9 @@ uint8 Util::ASCIIToHex(char ch) return 0; // Invalid } -std::vector Util::ASCIIToBin(std::string str) +BinaryData Util::ASCIIToBin(std::string str) { - std::vector data; + BinaryData data; data.resize(str.size()/2, 0); for (uint64 i = 0; i < str.size(); ++i) { if (i%2) @@ -68,7 +81,7 @@ std::vector Util::ASCIIToBin(std::string str) return data; } -std::string Util::BinToASCII(std::vector data) +std::string Util::BinToASCII(BinaryData data) { std::string str; for (uint64 i = 0; i < data.size(); ++i) @@ -79,16 +92,16 @@ std::string Util::BinToASCII(std::vector data) return str; } -std::vector Util::Reverse(std::vector data) +BinaryData Util::Reverse(BinaryData data) { - std::vector out = data; + BinaryData out = data; std::reverse(out.begin(), out.end()); return out; } -std::vector Util::Join(std::vector v1, std::vector v2) +BinaryData Util::Join(BinaryData v1, BinaryData v2) { - std::vector v3 = v1; + BinaryData v3 = v1; v3.insert(v3.end(), v2.begin(), v2.end()); return v3; } diff --git a/src/server/shared/Util.h b/src/server/shared/Util.h index 2163ad0..5163b2b 100644 --- a/src/server/shared/Util.h +++ b/src/server/shared/Util.h @@ -18,6 +18,7 @@ namespace Util { std::string Date(const char* format, bool utc = false); + uint32 Date(bool utc = true); template class SynchronisedQueue