Skip to content

Commit

Permalink
Add a first Segwit implementation, and Rules option for GetBlockTemplate
Browse files Browse the repository at this point in the history
Signed-off-by: Pttn <28868425+Pttn@users.noreply.github.com>
  • Loading branch information
Pttn committed Dec 5, 2018
1 parent e568d24 commit 62cf9ef
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 20 deletions.
67 changes: 50 additions & 17 deletions GBTClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ bool GBTClient::connect() {

void GetBlockTemplateData::coinBaseGen() {
coinbase = std::vector<uint8_t>();
std::vector<uint8_t> scriptSig(hexStrToV8("7269654d696e6572"));
std::vector<uint8_t> scriptSig(hexStrToV8("7269654d696e6572")),
dwc(hexStrToV8(default_witness_commitment)); // For SegWit
// Randomization to avoid 2 threads working on the same problem
for (uint32_t i(0) ; i < 4 ; i++) scriptSig.push_back(rand(0x00, 0xFF));

Expand Down Expand Up @@ -57,12 +58,14 @@ void GetBlockTemplateData::coinBaseGen() {

// Output Count [s + 4]
coinbase.push_back(1);
if (dwc.size() > 0) coinbase[coinbase.size() - 1]++; // Dummy Output for SegWit if needed
// Output Value [s + 5 -> s + 12]
uint64_t reward(coinbasevalue);
for (uint32_t i(0) ; i < 8 ; i++) {
coinbase.push_back(reward % 256);
reward /= 256;
}

coinbase.push_back(25); // Output Length [s + 13]
coinbase.push_back(0x76); // OP_DUP [s + 14]
coinbase.push_back(0xA9); // OP_HASH160 [s + 15]
Expand All @@ -71,14 +74,39 @@ void GetBlockTemplateData::coinBaseGen() {
for (uint32_t i(0) ; i < 20 ; i++) coinbase.push_back(scriptPubKey[i]);
coinbase.push_back(0x88); // OP_EQUALVERIFY [s + 37]
coinbase.push_back(0xAC); // OP_CHECKSIG [s + 38]
// Lock Time [s + 39 -> s + 42] (00000000)

// Default witness commitment for SegWit if applicable, contained in another output
if (dwc.size() > 0) {
for (uint32_t i(0) ; i < 8 ; i++) coinbase.push_back(0x00); // No reward
coinbase.push_back(dwc.size()); // Output Length
// default_witness_commitment from GetBlockTemplate
for (uint32_t i(0) ; i < dwc.size() ; i++) coinbase.push_back(dwc[i]);
}

// Lock Time (00000000)
for (uint32_t i(0) ; i < 4 ; i++) coinbase.push_back(0);
}

bool GBTClient::getWork() {
json_t *jsonGbt(sendRPCCall("{\"method\": \"getblocktemplate\", \"params\": [], \"id\": 0}\n")),
std::vector<std::string> rules(_manager->options().rules());
std::string req;
if (rules.size() == 0) req = "{\"method\": \"getblocktemplate\", \"params\": [], \"id\": 0}\n";
else {
std::ostringstream oss;
oss << "{\"method\": \"getblocktemplate\", \"params\": [{\"rules\":[";
for (uint32_t i(0) ; i < rules.size() ; i++) {
oss << "\"" << rules[i] << "\"";
if (i < rules.size() - 1) oss << ", ";
}
oss << "]}], \"id\": 0}\n";
req = oss.str();
}

json_t *jsonGbt(sendRPCCall(req.c_str())),
*jsonGbt_Res(json_object_get(jsonGbt, "result")),
*jsonGbt_Res_Txs(json_object_get(jsonGbt_Res, "transactions"));
*jsonGbt_Res_Txs(json_object_get(jsonGbt_Res, "transactions")),
*jsonGbt_Res_Rules(json_object_get(jsonGbt_Res, "rules")),
*jsonGbt_Res_Dwc(json_object_get(jsonGbt_Res, "default_witness_commitment"));

// Failure to GetBlockTemplate
if (jsonGbt == NULL || jsonGbt_Res == NULL || jsonGbt_Res_Txs == NULL) return false;
Expand All @@ -88,7 +116,9 @@ bool GBTClient::getWork() {
hexStrToBin(json_string_value(json_object_get(jsonGbt_Res, "bits")), bitsTmp);
_gbtd.bh = BlockHeader();
_gbtd.transactions = std::string();
_gbtd.rules = std::vector<std::string>();
_gbtd.txHashes = std::vector<std::array<uint8_t, 32>>();
_gbtd.default_witness_commitment = std::string();

// Extract and build GetBlockTemplate data
_gbtd.bh.version = json_integer_value(json_object_get(jsonGbt_Res, "version"));
Expand All @@ -97,11 +127,20 @@ bool GBTClient::getWork() {
_gbtd.coinbasevalue = json_integer_value(json_object_get(jsonGbt_Res, "coinbasevalue"));
_gbtd.bh.bits = ((uint32_t*) &bitsTmp)[0];
_gbtd.bh.curtime = json_integer_value(json_object_get(jsonGbt_Res, "curtime"));

for (uint32_t i(0) ; i < json_array_size(jsonGbt_Res_Rules) ; i++)
_gbtd.rules.push_back(json_string_value(json_array_get(jsonGbt_Res_Rules, i)));
if (jsonGbt_Res_Dwc != NULL)
_gbtd.default_witness_commitment = json_string_value(jsonGbt_Res_Dwc);

_gbtd.transactions += binToHexStr(_gbtd.coinbase.data(), _gbtd.coinbase.size());
for (uint32_t i(0) ; i < json_array_size(jsonGbt_Res_Txs) ; i++) {
std::array<uint8_t, 32> txHash;
uint8_t txHashInv[32];
hexStrToBin(json_string_value(json_object_get(json_array_get(jsonGbt_Res_Txs, i), "hash")), txHashInv);
if (_gbtd.segwitActive())
hexStrToBin(json_string_value(json_object_get(json_array_get(jsonGbt_Res_Txs, i), "txid")), txHashInv);
else
hexStrToBin(json_string_value(json_object_get(json_array_get(jsonGbt_Res_Txs, i), "hash")), txHashInv);
for (uint8_t j(0) ; j < 32 ; j++) txHash[j] = txHashInv[31 - j];
_gbtd.transactions += json_string_value(json_object_get(json_array_get(jsonGbt_Res_Txs, i), "data"));
_gbtd.txHashes.push_back(txHash);
Expand All @@ -117,10 +156,9 @@ bool GBTClient::getWork() {

void GBTClient::sendWork(const std::pair<WorkData, uint8_t>& share) const {
WorkData wdToSend(share.first);
json_t *jsonSb(NULL), *jsonSb_Res(NULL), *jsonSb_Err(NULL); // SubmitBlock response

std::ostringstream oss;
std::string req;

oss << "{\"method\": \"submitblock\", \"params\": [\"" << binToHexStr(&wdToSend.bh, (32 + 256 + 256 + 32 + 64 + 256)/8);
// Using the Variable Length Integer format
if (wdToSend.txCount < 0xFD)
Expand All @@ -129,29 +167,24 @@ void GBTClient::sendWork(const std::pair<WorkData, uint8_t>& share) const {
oss << "fd" << binToHexStr((uint8_t*) &wdToSend.txCount, 2);
oss << wdToSend.transactions << "\"], \"id\": 0}\n";
req = oss.str();
jsonSb = sendRPCCall(req);

uint16_t k(share.second);
_manager->printTime();
std::cout << " " << k << "-tuple found";
if (k < _gbtd.primes) std::cout << std::endl;
else {
std::cout << ", this is a block!" << std::endl;
json_t *jsonSb(sendRPCCall(req)); // SubmitBlock response
std::cout << "Sent: " << req;
if (jsonSb == NULL) std::cerr << "Failure submiting block :|" << std::endl;
else {
jsonSb_Res = json_object_get(jsonSb, "result");
jsonSb_Err = json_object_get(jsonSb, "error");
json_t *jsonSb_Res(json_object_get(jsonSb, "result")),
*jsonSb_Err(json_object_get(jsonSb, "error"));
if (json_is_null(jsonSb_Res) && json_is_null(jsonSb_Err)) std::cout << "Submission accepted :D !" << std::endl;
else {
std::cout << "Submission rejected :| ! ";
if (json_is_null(jsonSb_Err)) std::cout << "No reason given" << std::endl;
else std::cout << "Reason: " << json_string_value(json_object_get(jsonSb_Err, "message")) << std::endl;
}
else std::cout << "Submission rejected :| ! Received: " << json_dumps(jsonSb, JSON_COMPACT) << std::endl;
json_decref(jsonSb);
}
}

if (jsonSb != NULL) json_decref(jsonSb);
}

WorkData GBTClient::workData() const {
Expand Down
10 changes: 10 additions & 0 deletions GBTClient.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ struct GetBlockTemplateData {
uint32_t primes;
std::vector<uint8_t> coinbase, // Store Coinbase Transaction here
scriptPubKey; // Calculated from custom payout address for Coinbase Transaction
std::vector<std::string> rules; // From GetBlockTemplate response
std::string default_witness_commitment; // In hex format

GetBlockTemplateData() {
bh = BlockHeader();
Expand All @@ -25,6 +27,8 @@ struct GetBlockTemplateData {
primes = 6;
coinbase = std::vector<uint8_t>();
scriptPubKey = std::vector<uint8_t>(20, 0);
rules = std::vector<std::string>();
default_witness_commitment = std::string();
}

void coinBaseGen();
Expand All @@ -38,6 +42,12 @@ struct GetBlockTemplateData {
std::array<uint8_t, 32> mr(calculateMerkleRoot(txHashes));
memcpy(bh.merkleRoot, mr.data(), 32);
}
bool segwitActive() {
for (uint32_t i(0) ; i < rules.size() ; i++) {
if (rules[i] == "segwit") return true;
}
return false;
}
};

class GBTClient : public RPCClient {
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# rieMiner 0.9RC3
# rieMiner 0.9RC3.5

rieMiner is a Riecoin miner supporting both solo and pooled mining. It was originally adapted and refactored from gatra's cpuminer-rminerd (https://github.com/gatra/cpuminer-rminerd) and dave-andersen's fastrie (https://github.com/dave-andersen/fastrie), though there is no remaining code from rminerd anymore.

Expand Down Expand Up @@ -125,7 +125,8 @@ It is case sensitive, but spaces and invalid lines are ignored. **Do not put ; a
* Address : custom payout address for solo mining (GetBlockTemplate only). Default: a donation address;
* Threads : number of threads used for mining. Default: 8;
* Sieve : size of the sieve table used for mining. Use a bigger number if you have 16 GiB of RAM or more, as you will obtain better results: this will usually reduce the ratio between the n-tuple and n+1-tuples counts. Reduce if you have less than 8 GiB of RAM (or if you want to reduce memory usage). It can go up to 2^64 - 1, but setting this at more than a few billions will be too much and decrease performance. Default: 2^31;
* Tuples : for solo mining, submit not only blocks (6-tuples) but also k-tuples of at least the given length. Additionally, the base prime of such tuple will be shown in the Benchmark Mode. Default: 6.
* Tuples : for solo mining, submit not only blocks (6-tuples) but also k-tuples of at least the given length. Additionally, the base prime of such tuple will be shown in the Benchmark Mode. Default: 6;
* Rules : for solo mining, add consensus rules in the GetBlockTemplate RPC call, each separated by a comma. Useful for softforks, for example, to mine SegWit transactions, you would need the line "Rules = segwit". Default: no rule.

It is also possible to use custom configuration file paths, examples:

Expand Down
15 changes: 15 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,13 @@ void Options::loadConf() {
std::cout << "Too short or invalid tuple offsets, ignoring." << std::endl;
else _consType = primeTupleOffset;
}
else if (key == "Rules") {
for (uint16_t i(0) ; i < value.size() ; i++) {if (value[i] == ',') value[i] = ' ';}
std::stringstream offsets(value);
_rules = std::vector<std::string>();
std::string tmp;
while (offsets >> tmp) _rules.push_back(tmp);
}
else if (key == "Error")
std::cout << "Ignoring invalid line" << std::endl;
else
Expand Down Expand Up @@ -286,6 +293,14 @@ void Options::loadConf() {
else std::cout << "User.worker = " << _user << std::endl;
std::cout << "Pass = ..." << std::endl;
std::cout << "Protocol = " << _protocol << std::endl;
if (_rules.size() > 0 && _protocol == "GetBlockTemplate") {
std::cout << "Consensus Rules = ";
for (std::vector<std::string>::size_type i(0) ; i < _rules.size() ; i++) {
std::cout << _rules[i];
if (i != _rules.size() - 1) std::cout << ", ";
}
std::cout << std::endl;
}
}
if (_protocol == "GetBlockTemplate")
std::cout << "Payout address = " << _address << std::endl;
Expand Down
5 changes: 4 additions & 1 deletion main.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#ifndef HEADER_main_hpp
#define HEADER_main_hpp

#define versionString "rieMiner 0.9RC3"
#define versionString "rieMiner 0.9RC3.5"

#include <unistd.h>
#include <string>
Expand Down Expand Up @@ -32,6 +32,7 @@ class Options {
uint32_t _refresh, _testDiff, _testTime, _test2t;
uint64_t _sieve, _pn;
std::vector<uint64_t> _consType, _pOff;
std::vector<std::string> _rules;

void parseLine(std::string, std::string&, std::string&) const;

Expand All @@ -58,6 +59,7 @@ class Options {
7452755407ull, 7452758767ull, 7452762127ull, 7452765487ull}; // Primorial Offsets
_sieveBits = 25;
_consType = {0, 4, 2, 4, 2, 4}; // What type of constellations are we mining (offsets)
_rules = std::vector<std::string>();
}

void loadConf();
Expand All @@ -82,6 +84,7 @@ class Options {
std::vector<uint64_t> pOff() const {return _pOff;}
uint8_t sieveBits() const {return _sieveBits;}
std::vector<uint64_t> consType() const {return _consType;}
std::vector<std::string> rules() const {return _rules;}
};

#endif

0 comments on commit 62cf9ef

Please sign in to comment.