Added command line for merge mining

Start a merge mining client for each of the aux chains
merge-mining
SChernykh 2023-11-10 15:52:38 +01:00
parent abd9c80e4d
commit e6b8292d5b
13 changed files with 77 additions and 25 deletions

View File

@ -29,6 +29,7 @@
--no-upnp Disable UPnP port forwarding
--no-igd An alias for --no-upnp
--upnp-stratum Port forward Stratum port (it's not forwarded by default)
--merge-mine IP:port and wallet address for another blockchain to merge mine with
--version Print p2pool's version and build details
```
@ -50,3 +51,9 @@ In this example, you have local Monero host running on ports 18081/18083 (RPC/zm
```
p2pool.exe --host 127.0.0.1 --host xmr1.rs.me --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --host xmr3.rs.me --wallet YOUR_WALLET_ADDRESS
```
### Merge mining
```
p2pool.exe --wallet YOUR_WALLET_ADDRESS --merge-mine IP:port YOUR_WALLET_ADDRESS_ON_ANOTHER_BLOCKCHAIN
```

View File

@ -86,6 +86,8 @@ Example response 2: `{"jsonrpc":"2.0","id":"0","result":{}}`
### merge_mining_submit_solution
Example request: `{"jsonrpc":"2.0","id":"0","method":"merge_mining_submit_solution","params":{"aux_blob":"4c6f72656d20697073756d","aux_hash":"f6952d6eef555ddd87aca66e56b91530222d6e318414816f3ba7cf5bf694bf0f","blob":"...","merkle_proof":["hash1","hash2","hash3"]}}`
Request: a JSON containing these fields:
Field|Description
-|-

View File

@ -385,6 +385,8 @@ struct TxMempoolData
struct AuxChainData
{
FORCEINLINE AuxChainData(const hash& _id, const hash& _data, const difficulty_type& _difficulty) : unique_id(_id), data(_data), difficulty(_difficulty) {}
hash unique_id;
hash data;
difficulty_type difficulty;

View File

@ -42,18 +42,6 @@ FORCEINLINE void keccak(const uint8_t* in, int inlen, uint8_t (&md)[N])
template<typename T>
FORCEINLINE void keccak_custom(T&& in, int inlen, uint8_t* md, int mdlen)
{
// TODO: remove after testing
#if 0
if (inlen > 100) {
printf("\nkeccak_custom %d", inlen);
for (int i = 0; i < inlen; ++i) {
if ((i & 31) == 0) printf("\n");
printf("%02X ", static_cast<uint8_t>(in(i)));
}
printf("\n");
}
#endif
uint64_t st[25] = {};
const int rsiz = sizeof(st) == mdlen ? KeccakParams::HASH_DATA_AREA : 200 - 2 * mdlen;

View File

@ -62,6 +62,7 @@ void p2pool_usage()
"--no-igd An alias for --no-upnp\n"
"--upnp-stratum Port forward Stratum port (it's not forwarded by default)\n"
#endif
"--merge-mine IP:port and wallet address for another blockchain to merge mine with"
"--version Print p2pool's version and build details\n"
"--help Show this help message\n\n"
"Example command line:\n\n"

View File

@ -27,10 +27,10 @@ LOG_CATEGORY(MergeMiningClient)
namespace p2pool {
MergeMiningClient::MergeMiningClient(p2pool* pool, const std::string& host, const std::string& address)
MergeMiningClient::MergeMiningClient(p2pool* pool, const std::string& host, const std::string& wallet)
: m_host(host)
, m_port(80)
, m_auxAddress(address)
, m_auxWallet(wallet)
, m_ping(0.0)
, m_pool(pool)
, m_loop{}
@ -42,7 +42,7 @@ MergeMiningClient::MergeMiningClient(p2pool* pool, const std::string& host, cons
const size_t k = host.find_last_of(':');
if (k != std::string::npos) {
m_host = host.substr(0, k);
m_port = strtoul(host.substr(k + 1).c_str(), nullptr, 10);
m_port = std::stoul(host.substr(k + 1), nullptr, 10);
}
if (m_host.empty() || (m_port == 0) || (m_port >= 65536)) {
@ -95,7 +95,7 @@ MergeMiningClient::~MergeMiningClient()
void MergeMiningClient::on_timer()
{
MinerData data = m_pool->miner_data();
merge_mining_get_job(data.height, data.prev_id, m_auxAddress, m_auxHash);
merge_mining_get_job(data.height, data.prev_id, m_auxWallet, m_auxHash);
}
void MergeMiningClient::merge_mining_get_chain_id()
@ -157,7 +157,7 @@ bool MergeMiningClient::parse_merge_mining_get_chain_id(const char* data, size_t
return true;
}
void MergeMiningClient::merge_mining_get_job(uint64_t height, const hash& prev_id, const std::string& address, const hash& aux_hash)
void MergeMiningClient::merge_mining_get_job(uint64_t height, const hash& prev_id, const std::string& wallet, const hash& aux_hash)
{
if (m_getJobRunning) {
return;
@ -169,7 +169,7 @@ void MergeMiningClient::merge_mining_get_job(uint64_t height, const hash& prev_i
log::Stream s(buf);
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"merge_mining_get_job\",\"params\":{"
<< "\"address\":\"" << address << '"'
<< "\"address\":\"" << wallet << '"'
<< ",\"aux_hash\":\"" << aux_hash << '"'
<< ",\"height\":" << height
<< ",\"prev_id\":\"" << prev_id << '"'

View File

@ -26,11 +26,15 @@ class p2pool;
class MergeMiningClient
{
public:
MergeMiningClient(p2pool* pool, const std::string& host, const std::string& address);
MergeMiningClient(p2pool* pool, const std::string& host, const std::string& wallet);
~MergeMiningClient();
void merge_mining_submit_solution(const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof);
FORCEINLINE const hash& aux_id() const { return m_chainID; }
FORCEINLINE const hash& aux_data() const { return m_auxHash; }
FORCEINLINE const difficulty_type& aux_diff() const { return m_auxDiff; }
private:
static void loop(void* data);
@ -40,7 +44,7 @@ private:
void merge_mining_get_chain_id();
bool parse_merge_mining_get_chain_id(const char* data, size_t size);
void merge_mining_get_job(uint64_t height, const hash& prev_id, const std::string& address, const hash& aux_hash);
void merge_mining_get_job(uint64_t height, const hash& prev_id, const std::string& wallet, const hash& aux_hash);
bool parse_merge_mining_get_job(const char* data, size_t size);
bool parse_merge_mining_submit_solution(const char* data, size_t size);
@ -48,7 +52,7 @@ private:
std::string m_host;
uint32_t m_port;
std::string m_auxAddress;
std::string m_auxWallet;
std::vector<uint8_t> m_auxBlob;
hash m_auxHash;
difficulty_type m_auxDiff;

View File

@ -37,6 +37,7 @@
#include "pool_block.h"
#include "keccak.h"
#include "merkle.h"
#include "merge_mining_client.h"
#include <thread>
#include <fstream>
#include <numeric>
@ -186,6 +187,11 @@ p2pool::~p2pool()
}
#endif
for (const MergeMiningClient* c : m_mergeMiningClients) {
delete c;
}
m_mergeMiningClients.clear();
uv_rwlock_destroy(&m_mainchainLock);
uv_rwlock_destroy(&m_minerDataLock);
uv_rwlock_destroy(&m_ZMQReaderLock);
@ -334,6 +340,25 @@ void p2pool::handle_miner_data(MinerData& data)
cleanup_mainchain_data(data.height);
}
data.aux_chains.clear();
if (!m_mergeMiningClients.empty()) {
data.aux_chains.reserve(m_mergeMiningClients.size());
std::vector<hash> tmp;
tmp.reserve(m_mergeMiningClients.size());
for (const MergeMiningClient* c : m_mergeMiningClients) {
data.aux_chains.emplace_back(c->aux_id(), c->aux_data(), c->aux_diff());
tmp.emplace_back(c->aux_data());
}
if (!find_aux_nonce(tmp, data.aux_nonce)) {
LOGERR(1, "Failed to find the aux nonce for merge mining. Merge mining will be off this round.");
data.aux_chains.clear();
}
}
// TODO: remove after testing
#if 0
{
@ -840,6 +865,10 @@ void p2pool::download_block_headers(uint64_t current_height)
}
}
for (const auto& h : m_params->m_mergeMiningHosts) {
m_mergeMiningClients.push_back(new MergeMiningClient(this, h.m_host, h.m_wallet));
}
m_startupFinished = true;
}
}
@ -1136,11 +1165,10 @@ void p2pool::get_miner_data(bool retry)
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
m_getMinerDataPending = false;
get_miner_data();
return;
}
}
else {
m_getMinerDataPending = false;
}
m_getMinerDataPending = false;
});
}

View File

@ -33,6 +33,7 @@ class Miner;
class ConsoleCommands;
class p2pool_api;
class ZMQReader;
class MergeMiningClient;
struct PoolBlock;
class p2pool : public MinerCallbackHandler, public nocopy_nomove
@ -226,6 +227,8 @@ private:
mutable uv_rwlock_t m_ZMQReaderLock;
ZMQReader* m_ZMQReader = nullptr;
std::vector<MergeMiningClient*> m_mergeMiningClients;
hash m_getMinerDataHash;
bool m_getMinerDataPending = false;

View File

@ -189,6 +189,12 @@ Params::Params(int argc, char* const argv[])
}
#endif
if ((strcmp(argv[i], "--merge-mine") == 0) && (i + 2 < argc)) {
m_mergeMiningHosts.emplace_back(argv[i + 1], argv[i + 2]);
i += 2;
ok = true;
}
if (!ok) {
fprintf(stderr, "Unknown command line parameter %s\n\n", argv[i]);
p2pool_usage();

View File

@ -53,6 +53,16 @@ struct Params
std::vector<Host> m_hosts;
struct MergeMiningHost
{
MergeMiningHost(const char* host, const char* wallet) : m_host(host), m_wallet(wallet) {}
std::string m_host;
std::string m_wallet;
};
std::vector<MergeMiningHost> m_mergeMiningHosts;
bool m_lightMode = false;
Wallet m_wallet{ nullptr };
std::string m_stratumAddresses;

View File

@ -113,7 +113,7 @@ void TCPServer::parse_address_list_internal(const std::string& address_list, Cal
}
}
const int port = strtol(address.substr(k2 + 1).c_str(), nullptr, 10);
const uint32_t port = std::stoul(address.substr(k2 + 1), nullptr, 10);
if ((port > 0) && (port < 65536)) {
callback(is_v6, address, ip, port);
}

View File

@ -53,6 +53,7 @@ set(SOURCES
../src/log.cpp
../src/memory_leak_debug.cpp
../src/mempool.cpp
../src/merge_mining_client.cpp
../src/merkle.cpp
../src/miner.cpp
../src/p2p_server.cpp