Browse Source

Something is working??

peercoin
Intel 11 years ago
parent
commit
1724c08d99
  1. 3
      src/server/poolserver/Server/Server.cpp
  2. 148
      src/server/poolserver/Stratum/Client.cpp
  3. 39
      src/server/poolserver/Stratum/Client.h
  4. 17
      src/server/poolserver/Stratum/Job.h
  5. 18
      src/server/poolserver/Stratum/Server.h
  6. 2
      src/server/shared/BigNum.h
  7. 20
      src/server/shared/Bitcoin/Bitcoin.h
  8. 65
      src/server/shared/Bitcoin/Block.cpp
  9. 35
      src/server/shared/Bitcoin/Block.h
  10. 5
      src/server/shared/ByteBuffer.h

3
src/server/poolserver/Server/Server.cpp

@ -35,7 +35,8 @@ int Server::Run()
//InitDatabase(); //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()); sLog.Info(LOG_SERVER, "Something: %s", node.ToString().c_str());
/*std::vector<byte> test = Util::ASCIIToBin("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); /*std::vector<byte> test = Util::ASCIIToBin("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");

148
src/server/poolserver/Stratum/Client.cpp

@ -1,5 +1,7 @@
#include "Server.h" #include "Server.h"
#include "Client.h" #include "Client.h"
#include "BigNum.h"
#include <iostream>
namespace Stratum namespace Stratum
{ {
@ -9,19 +11,10 @@ namespace Stratum
_jobs.clear(); _jobs.clear();
Job job = GetJob(); Job job = GetJob();
uint64 jobid = _jobid++; uint32 jobid = _jobid++;
_jobs[jobid] = job; _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 // Build merkle branch array
JSON merkle_branch(JSON_ARRAY); JSON merkle_branch(JSON_ARRAY);
uint64 branches = job.block->merkleBranches; uint64 branches = job.block->merkleBranches;
@ -32,11 +25,18 @@ namespace Stratum
branches /= 2; 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; JSON params;
params.Add("bf"); params.Add(Util::BinToASCII(ByteBuffer(jobid).Binary()));
params.Add(Util::BinToASCII(Util::Reverse(job.block->prevBlockHash))); params.Add(Util::BinToASCII(prevhashfixed.Binary()));
params.Add(Util::BinToASCII(coinbase1)); params.Add(Util::BinToASCII(job.coinbase1));
params.Add(Util::BinToASCII(coinbase2)); params.Add(Util::BinToASCII(job.coinbase2));
params.Add(merkle_branch); params.Add(merkle_branch);
params.Add(Util::BinToASCII(Util::Reverse(ByteBuffer(job.block->version).Binary()))); params.Add(Util::BinToASCII(Util::Reverse(ByteBuffer(job.block->version).Binary())));
params.Add(Util::BinToASCII(Util::Reverse(ByteBuffer(job.block->bits).Binary()))); params.Add(Util::BinToASCII(Util::Reverse(ByteBuffer(job.block->bits).Binary())));
@ -51,6 +51,102 @@ namespace Stratum
SendMessage(msg); 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) void Client::OnMiningSubscribe(JSON msg)
{ {
_subscribed = true; _subscribed = true;
@ -74,13 +170,35 @@ namespace Stratum
SendMessage(response); 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 Client::GetJob()
{ {
Job job; Job job;
job.block = _server->GetWork(); 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; return job;
} }
} }

39
src/server/poolserver/Stratum/Client.h

@ -32,6 +32,11 @@ namespace Stratum
} }
void Start() void Start()
{
StartRead();
}
void StartRead()
{ {
boost::asio::async_read_until( boost::asio::async_read_until(
_socket, _socket,
@ -47,27 +52,24 @@ namespace Stratum
std::string data = msg.ToString(); std::string data = msg.ToString();
data += '\n'; data += '\n';
sLog.Debug(LOG_SERVER, "Sending: %s", data.c_str()); 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 OnMiningSubscribe(JSON msg);
void OnMiningAuthorize(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 OnMessage(JSON msg) void OnMessage(JSON msg)
{ {
std::string method = msg["method"].GetString(); 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); OnMiningSubscribe(msg);
else if (method.compare("mining.authorize") == 0) else if (method.compare("mining.authorize") == 0)
OnMiningAuthorize(msg); OnMiningAuthorize(msg);
@ -84,6 +86,15 @@ namespace Stratum
iss << is.rdbuf(); iss << is.rdbuf();
sLog.Debug(LOG_SERVER, "Received: %s", iss.str().c_str()); sLog.Debug(LOG_SERVER, "Received: %s", iss.str().c_str());
OnMessage(JSON::FromString(iss.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: private:
// Networking // Networking
@ -100,7 +111,7 @@ namespace Stratum
bool _subscribed; bool _subscribed;
uint32 _extranonce; uint32 _extranonce;
std::map<uint64, Job> _jobs; std::map<uint64, Job> _jobs;
uint64 _jobid; uint32 _jobid;
}; };
} }

17
src/server/poolserver/Stratum/Job.h

@ -2,6 +2,9 @@
#define STRATUM_JOB_H_ #define STRATUM_JOB_H_
#include "Bitcoin.h" #include "Bitcoin.h"
#include "Crypto.h"
#include "Util.h"
#include <set>
namespace Stratum namespace Stratum
{ {
@ -9,6 +12,20 @@ namespace Stratum
{ {
public: public:
Bitcoin::BlockPtr block; 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;
}
}; };
} }

18
src/server/poolserver/Stratum/Server.h

@ -69,7 +69,9 @@ namespace Stratum
uint32 GetExtranonce() uint32 GetExtranonce()
{ {
return _extranonce++; //return 134217730;
return 33554440;
//return _extranonce++;
} }
Bitcoin::BlockPtr GetWork() Bitcoin::BlockPtr GetWork()
@ -106,23 +108,29 @@ namespace Stratum
Bitcoin::BlockPtr block = Bitcoin::BlockPtr(new Bitcoin::Block()); Bitcoin::BlockPtr block = Bitcoin::BlockPtr(new Bitcoin::Block());
block->version = response["version"].GetInt(); 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(); block->time = response["curtime"].GetInt();
// Set bits // Set bits
ByteBuffer bitbuf(Util::ASCIIToBin(response["bits"].GetString())); ByteBuffer bitbuf(Util::Reverse(Util::ASCIIToBin(response["bits"].GetString())));
bitbuf >> block->bits; bitbuf >> block->bits;
// Add coinbase tx // Add coinbase tx
block->tx.push_back(CreateCoinbaseTX(_blockHeight, _pubkey, response["coinbasevalue"].GetInt())); block->tx.push_back(CreateCoinbaseTX(_blockHeight, _pubkey, response["coinbasevalue"].GetInt()));
// Add other transactions // Add other transactions
JSON trans = response["transactions"]; /*JSON trans = response["transactions"];
for (uint64 i = 0; i < trans.Size(); ++i) { for (uint64 i = 0; i < trans.Size(); ++i) {
ByteBuffer txbuf(Util::ASCIIToBin(trans[i]["data"].GetString())); ByteBuffer txbuf(Util::ASCIIToBin(trans[i]["data"].GetString()));
Bitcoin::Transaction tx; Bitcoin::Transaction tx;
txbuf >> tx; txbuf >> tx;
block->tx.push_back(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 // Genrate merkle tree
block->BuildMerkleTree(); block->BuildMerkleTree();

2
src/server/shared/BigNum.h

@ -3,6 +3,6 @@
#include <gmpxx.h> #include <gmpxx.h>
typedef mpz_class BigNum; typedef mpz_class BigInt;
#endif #endif

20
src/server/shared/Bitcoin/Bitcoin.h

@ -5,5 +5,25 @@
#include "Transaction.h" #include "Transaction.h"
#include "VarInt.h" #include "VarInt.h"
#include "Script.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 #endif

65
src/server/shared/Bitcoin/Block.cpp

@ -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());
}
}

35
src/server/shared/Bitcoin/Block.h

@ -30,37 +30,10 @@ namespace Bitcoin
std::vector<BinaryData> merkleTree; std::vector<BinaryData> merkleTree;
uint64 merkleBranches; uint64 merkleBranches;
void BuildMerkleTree() void BuildMerkleTree();
{ // Rebuilds only left side of merkle tree
merkleTree.clear(); void RebuildMerkleTree();
BinaryData GetHash();
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];
}
}; };
typedef boost::shared_ptr<Block> BlockPtr; typedef boost::shared_ptr<Block> BlockPtr;

5
src/server/shared/ByteBuffer.h

@ -85,6 +85,11 @@ public:
return vec; return vec;
} }
uint64 Size()
{
return vec.size();
}
uint64 pointer; uint64 pointer;
BinaryData vec; BinaryData vec;
}; };

Loading…
Cancel
Save