mirror of
https://github.com/GOSTSec/poolserver
synced 2025-03-12 21:41:08 +00:00
Something is working??
This commit is contained in:
parent
8dca8f0932
commit
1724c08d99
@ -35,7 +35,8 @@ int Server::Run()
|
||||
|
||||
//InitDatabase();
|
||||
|
||||
JSON node = JSON::FromString("{\"test\":{\"omg\":\"smth\"},\"other\":\"smth2\"}");
|
||||
JSON node = JSON::FromString("{\"test\":{\"omg\":\"smth\"},\"other\":[\"smth2\", \"smth3\"] }");
|
||||
sLog.Info(LOG_SERVER, "Something2: %s", node["other"][0].GetString().c_str());
|
||||
sLog.Info(LOG_SERVER, "Something: %s", node.ToString().c_str());
|
||||
|
||||
/*std::vector<byte> test = Util::ASCIIToBin("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "Server.h"
|
||||
#include "Client.h"
|
||||
#include "BigNum.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace Stratum
|
||||
{
|
||||
@ -9,19 +11,10 @@ namespace Stratum
|
||||
_jobs.clear();
|
||||
|
||||
Job job = GetJob();
|
||||
uint64 jobid = _jobid++;
|
||||
uint32 jobid = _jobid++;
|
||||
|
||||
_jobs[jobid] = job;
|
||||
|
||||
// Coinbase parts
|
||||
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 (block height)
|
||||
uint32 cbsplit = 4 + 32 + 4 + 4;
|
||||
BinaryData coinbase1 = BinaryData(coinbase.begin(), coinbase.begin() + cbsplit);
|
||||
BinaryData coinbase2 = BinaryData(coinbase.begin() + cbsplit + 8, coinbase.end()); // plus extranonce size
|
||||
|
||||
// Build merkle branch array
|
||||
JSON merkle_branch(JSON_ARRAY);
|
||||
uint64 branches = job.block->merkleBranches;
|
||||
@ -32,11 +25,18 @@ namespace Stratum
|
||||
branches /= 2;
|
||||
}
|
||||
|
||||
// Reverse prev block hash every 4 bytes... Makes a lot of sense...
|
||||
ByteBuffer prevhashbuf(Util::Reverse(job.block->prevBlockHash));
|
||||
std::vector<uint32> prevhash(8);
|
||||
prevhashbuf >> prevhash[7] >> prevhash[6] >> prevhash[5] >> prevhash[4] >> prevhash[3] >> prevhash[2] >> prevhash[1] >> prevhash[0];
|
||||
ByteBuffer prevhashfixed;
|
||||
prevhashfixed << prevhash[0] << prevhash[1] << prevhash[2] << prevhash[3] << prevhash[4] << prevhash[5] << prevhash[6] << prevhash[7];
|
||||
|
||||
JSON params;
|
||||
params.Add("bf");
|
||||
params.Add(Util::BinToASCII(Util::Reverse(job.block->prevBlockHash)));
|
||||
params.Add(Util::BinToASCII(coinbase1));
|
||||
params.Add(Util::BinToASCII(coinbase2));
|
||||
params.Add(Util::BinToASCII(ByteBuffer(jobid).Binary()));
|
||||
params.Add(Util::BinToASCII(prevhashfixed.Binary()));
|
||||
params.Add(Util::BinToASCII(job.coinbase1));
|
||||
params.Add(Util::BinToASCII(job.coinbase2));
|
||||
params.Add(merkle_branch);
|
||||
params.Add(Util::BinToASCII(Util::Reverse(ByteBuffer(job.block->version).Binary())));
|
||||
params.Add(Util::BinToASCII(Util::Reverse(ByteBuffer(job.block->bits).Binary())));
|
||||
@ -51,6 +51,102 @@ namespace Stratum
|
||||
SendMessage(msg);
|
||||
}
|
||||
|
||||
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();
|
||||
uint32 jobid;
|
||||
ByteBuffer jobbuf(Util::ASCIIToBin(params[1].GetString()));
|
||||
jobbuf >> jobid;
|
||||
|
||||
if (!_jobs.count(jobid)) {
|
||||
JSON response;
|
||||
response["id"] = msg["id"];
|
||||
response["result"];
|
||||
response["error"].Add(int64(21));
|
||||
response["error"].Add("Job not found");
|
||||
response["error"].Add(JSON());
|
||||
SendMessage(response);
|
||||
return;
|
||||
}
|
||||
|
||||
// check username
|
||||
|
||||
BinaryData extranonce2 = Util::ASCIIToBin(params[2].GetString());
|
||||
if (extranonce2.size() != 4) {
|
||||
sLog.Error(LOG_SERVER, "Wrong extranonce size");
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuffer timebuf(Util::Reverse(Util::ASCIIToBin(params[3].GetString())));
|
||||
if (timebuf.Size() != 4) {
|
||||
sLog.Error(LOG_SERVER, "Wrong ntime size");
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuffer noncebuf(Util::Reverse(Util::ASCIIToBin(params[4].GetString())));
|
||||
if (noncebuf.Size() != 4) {
|
||||
sLog.Error(LOG_SERVER, "Wrong nonce size");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get job
|
||||
Job& job = _jobs[jobid];
|
||||
|
||||
ByteBuffer share;
|
||||
share << extranonce2 << timebuf << noncebuf;
|
||||
if (!job.SubmitShare(share.Binary())) {
|
||||
sLog.Error(LOG_SERVER, "Duplicate share");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get block we are working on
|
||||
Bitcoin::Block block = *job.block;
|
||||
|
||||
timebuf >> block.time;
|
||||
noncebuf >> block.nonce;
|
||||
|
||||
Bitcoin::Transaction coinbasetx;
|
||||
ByteBuffer coinbasebuf;
|
||||
coinbasebuf << job.coinbase1 << _extranonce << extranonce2 << job.coinbase2;
|
||||
coinbasebuf >> coinbasetx;
|
||||
|
||||
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());
|
||||
|
||||
block.RebuildMerkleTree();
|
||||
sLog.Info(LOG_SERVER, "Merklehash: %s", Util::BinToASCII(block.merkleRootHash).c_str());
|
||||
BinaryData hash = block.GetHash();
|
||||
|
||||
sLog.Info(LOG_SERVER, "Block hash: %s", Util::BinToASCII(hash).c_str());
|
||||
|
||||
BigInt target(Util::BinToASCII(Util::Reverse(hash)), 16);
|
||||
BigInt criteria(Bitcoin::TargetFromBits(block.bits));
|
||||
BigInt diff = Bitcoin::TargetConvert(criteria);
|
||||
std::cout << "Target: " << target << std::endl;
|
||||
std::cout << "Criteria: " << criteria << std::endl;
|
||||
std::cout << "Diff: " << diff << std::endl;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::OnMiningSubscribe(JSON msg)
|
||||
{
|
||||
_subscribed = true;
|
||||
@ -74,13 +170,35 @@ namespace Stratum
|
||||
|
||||
SendMessage(response);
|
||||
|
||||
SendJob(false);
|
||||
SendJob(true);
|
||||
}
|
||||
|
||||
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"];
|
||||
response["result"] = true;
|
||||
SendMessage(response);
|
||||
}
|
||||
|
||||
Job Client::GetJob()
|
||||
{
|
||||
Job job;
|
||||
job.block = _server->GetWork();
|
||||
|
||||
// Coinbase parts
|
||||
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)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,11 @@ namespace Stratum
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
StartRead();
|
||||
}
|
||||
|
||||
void StartRead()
|
||||
{
|
||||
boost::asio::async_read_until(
|
||||
_socket,
|
||||
@ -47,27 +52,24 @@ namespace Stratum
|
||||
std::string data = msg.ToString();
|
||||
data += '\n';
|
||||
sLog.Debug(LOG_SERVER, "Sending: %s", data.c_str());
|
||||
_socket.send(boost::asio::buffer(data.c_str(), data.length()));
|
||||
boost::asio::async_write(
|
||||
_socket,
|
||||
boost::asio::buffer(data.c_str(), data.length()),
|
||||
boost::bind(&Client::_OnSend, this, boost::asio::placeholders::error));
|
||||
}
|
||||
|
||||
void OnMiningSubmit(JSON msg);
|
||||
void OnMiningSubscribe(JSON msg);
|
||||
|
||||
void OnMiningAuthorize(JSON msg)
|
||||
{
|
||||
std::string username = msg["result"][0].GetString();
|
||||
JSON response;
|
||||
response["id"] = msg["id"].GetInt();
|
||||
response["error"];
|
||||
response["result"] = true;
|
||||
SendMessage(response);
|
||||
}
|
||||
void OnMiningAuthorize(JSON msg);
|
||||
|
||||
void OnMessage(JSON msg)
|
||||
{
|
||||
std::string method = msg["method"].GetString();
|
||||
sLog.Debug(LOG_SERVER, "Method: %s", method.c_str());
|
||||
sLog.Debug(LOG_SERVER, "Decoded: %s", msg.ToString().c_str());
|
||||
|
||||
if (method.compare("mining.subscribe") == 0)
|
||||
if (method.compare("mining.submit") == 0)
|
||||
OnMiningSubmit(msg);
|
||||
else if (method.compare("mining.subscribe") == 0)
|
||||
OnMiningSubscribe(msg);
|
||||
else if (method.compare("mining.authorize") == 0)
|
||||
OnMiningAuthorize(msg);
|
||||
@ -84,6 +86,15 @@ namespace Stratum
|
||||
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");
|
||||
}
|
||||
private:
|
||||
// Networking
|
||||
@ -100,7 +111,7 @@ namespace Stratum
|
||||
bool _subscribed;
|
||||
uint32 _extranonce;
|
||||
std::map<uint64, Job> _jobs;
|
||||
uint64 _jobid;
|
||||
uint32 _jobid;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,9 @@
|
||||
#define STRATUM_JOB_H_
|
||||
|
||||
#include "Bitcoin.h"
|
||||
#include "Crypto.h"
|
||||
#include "Util.h"
|
||||
#include <set>
|
||||
|
||||
namespace Stratum
|
||||
{
|
||||
@ -9,6 +12,20 @@ namespace Stratum
|
||||
{
|
||||
public:
|
||||
Bitcoin::BlockPtr block;
|
||||
BinaryData coinbase1;
|
||||
BinaryData coinbase2;
|
||||
std::set<std::string> shares;
|
||||
|
||||
bool SubmitShare(BinaryData share)
|
||||
{
|
||||
std::string sharestr = Util::BinToASCII(Crypto::SHA256(share));
|
||||
std::set<std::string>::iterator it = shares.find(sharestr);
|
||||
if (it == shares.end()) {
|
||||
shares.insert(sharestr);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,9 @@ namespace Stratum
|
||||
|
||||
uint32 GetExtranonce()
|
||||
{
|
||||
return _extranonce++;
|
||||
//return 134217730;
|
||||
return 33554440;
|
||||
//return _extranonce++;
|
||||
}
|
||||
|
||||
Bitcoin::BlockPtr GetWork()
|
||||
@ -106,23 +108,29 @@ namespace Stratum
|
||||
Bitcoin::BlockPtr block = Bitcoin::BlockPtr(new Bitcoin::Block());
|
||||
|
||||
block->version = response["version"].GetInt();
|
||||
block->prevBlockHash = Util::ASCIIToBin(response["previousblockhash"].GetString());
|
||||
block->prevBlockHash = Util::Reverse(Util::ASCIIToBin(response["previousblockhash"].GetString()));
|
||||
block->time = response["curtime"].GetInt();
|
||||
// Set bits
|
||||
ByteBuffer bitbuf(Util::ASCIIToBin(response["bits"].GetString()));
|
||||
ByteBuffer bitbuf(Util::Reverse(Util::ASCIIToBin(response["bits"].GetString())));
|
||||
bitbuf >> block->bits;
|
||||
|
||||
// Add coinbase tx
|
||||
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();
|
||||
|
@ -3,6 +3,6 @@
|
||||
|
||||
#include <gmpxx.h>
|
||||
|
||||
typedef mpz_class BigNum;
|
||||
typedef mpz_class BigInt;
|
||||
|
||||
#endif
|
||||
|
@ -5,5 +5,25 @@
|
||||
#include "Transaction.h"
|
||||
#include "VarInt.h"
|
||||
#include "Script.h"
|
||||
#include "BigNum.h"
|
||||
#include <gmpxx.h>
|
||||
|
||||
namespace Bitcoin
|
||||
{
|
||||
inline BigInt TargetConvert(BigInt val)
|
||||
{
|
||||
static BigInt c("0x00000000ffff0000000000000000000000000000000000000000000000000000");
|
||||
return (c / val);
|
||||
}
|
||||
|
||||
inline BigInt TargetFromBits(uint32 bits)
|
||||
{
|
||||
uint8 nbytes = (bits >> 24) & 0xFF;
|
||||
mpz_t power;
|
||||
mpz_init(power);
|
||||
mpz_ui_pow_ui(power, 2, 8 * (nbytes - 3));
|
||||
return BigInt(bits & 0xFFFFFF) * BigInt(power);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
65
src/server/shared/Bitcoin/Block.cpp
Normal file
65
src/server/shared/Bitcoin/Block.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
#include "Block.h"
|
||||
|
||||
namespace Bitcoin
|
||||
{
|
||||
void Block::BuildMerkleTree()
|
||||
{
|
||||
merkleTree.clear();
|
||||
|
||||
uint64 branches = 1;
|
||||
uint32 levels = 0;
|
||||
while (branches < tx.size()) {
|
||||
branches *= 2;
|
||||
++levels;
|
||||
}
|
||||
|
||||
// Used when sending merkle branches
|
||||
merkleBranches = branches;
|
||||
|
||||
// Add transactions
|
||||
for (uint64 i = 0; i < branches; ++i)
|
||||
merkleTree.push_back(tx[std::min(i, tx.size()-1)].GetHash());
|
||||
|
||||
uint32 merkleIndex = 0;
|
||||
for (uint32 level = levels; level > 0; --level)
|
||||
{
|
||||
// Decrease before calculating because bottom level is transactions
|
||||
branches /= 2;
|
||||
|
||||
for (uint32 branch = 0; branch < branches; ++branch)
|
||||
merkleTree.push_back(Crypto::SHA256D(Util::Join(merkleTree[merkleIndex++], merkleTree[merkleIndex++])));
|
||||
}
|
||||
|
||||
// Last hash is merkle root
|
||||
merkleRootHash = merkleTree[merkleTree.size()-1];
|
||||
}
|
||||
|
||||
void Block::RebuildMerkleTree()
|
||||
{
|
||||
// Set coinbase tx hash
|
||||
merkleTree[0] = tx[0].GetHash();
|
||||
|
||||
uint64 branches = merkleBranches;
|
||||
uint64 index = 0;
|
||||
while (branches > 1) {
|
||||
merkleTree[index+branches] = Crypto::SHA256D(Util::Join(merkleTree[index], merkleTree[index+1]));
|
||||
index += branches;
|
||||
branches /= 2;
|
||||
}
|
||||
|
||||
// Last hash is merkle root
|
||||
merkleRootHash = merkleTree[merkleTree.size()-1];
|
||||
}
|
||||
|
||||
BinaryData Block::GetHash()
|
||||
{
|
||||
ByteBuffer buf;
|
||||
buf << version;
|
||||
buf << prevBlockHash;
|
||||
buf << merkleRootHash;
|
||||
buf << time;
|
||||
buf << bits;
|
||||
buf << nonce;
|
||||
return Crypto::SHA256D(buf.Binary());
|
||||
}
|
||||
}
|
@ -30,37 +30,10 @@ namespace Bitcoin
|
||||
std::vector<BinaryData> merkleTree;
|
||||
uint64 merkleBranches;
|
||||
|
||||
void BuildMerkleTree()
|
||||
{
|
||||
merkleTree.clear();
|
||||
|
||||
uint64 branches = 1;
|
||||
uint32 levels = 0;
|
||||
while (branches < tx.size()) {
|
||||
branches *= 2;
|
||||
++levels;
|
||||
}
|
||||
|
||||
// Used when sending merkle branches
|
||||
merkleBranches = branches;
|
||||
|
||||
// Add transactions
|
||||
for (uint64 i = 0; i < branches; ++i)
|
||||
merkleTree.push_back(tx[std::min(i, tx.size()-1)].GetHash());
|
||||
|
||||
uint32 merkleIndex = 0;
|
||||
for (uint32 level = levels; level > 0; --level)
|
||||
{
|
||||
// Decrease before calculating because bottom level is transactions
|
||||
branches /= 2;
|
||||
|
||||
for (uint32 branch = 0; branch < branches; ++branch)
|
||||
merkleTree.push_back(Crypto::SHA256D(Util::Join(merkleTree[merkleIndex++], merkleTree[merkleIndex++])));
|
||||
}
|
||||
|
||||
// Last hash is merkle root
|
||||
merkleRootHash = merkleTree[merkleTree.size()-1];
|
||||
}
|
||||
void BuildMerkleTree();
|
||||
// Rebuilds only left side of merkle tree
|
||||
void RebuildMerkleTree();
|
||||
BinaryData GetHash();
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<Block> BlockPtr;
|
||||
|
@ -85,6 +85,11 @@ public:
|
||||
return vec;
|
||||
}
|
||||
|
||||
uint64 Size()
|
||||
{
|
||||
return vec.size();
|
||||
}
|
||||
|
||||
uint64 pointer;
|
||||
BinaryData vec;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user