Stabilize nodejs facade submissions
This commit is contained in:
@@ -111,7 +111,10 @@ private:
|
||||
#ifdef P2POOL_UNIT_TESTS
|
||||
BlockTemplate* m_oldTemplates[1] = {};
|
||||
#else
|
||||
BlockTemplate* m_oldTemplates[4] = {};
|
||||
// Nodejs-pool submits can arrive noticeably later than native stratum
|
||||
// submits. Keep enough old templates to rebuild aux proofs for delayed
|
||||
// shares instead of failing with stale_template after a few rotations.
|
||||
BlockTemplate* m_oldTemplates[512] = {};
|
||||
#endif
|
||||
|
||||
std::atomic<uint64_t> m_finalReward;
|
||||
|
||||
@@ -50,6 +50,11 @@ public:
|
||||
[[nodiscard]] virtual bool get_params(ChainParameters& out_params) const = 0;
|
||||
virtual void on_external_block(const PoolBlock& block) = 0;
|
||||
virtual void submit_solution(const std::vector<uint8_t>& coinbase_merkle_proof, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path) = 0;
|
||||
virtual void submit_solution(const ChainParameters& chain_params, const std::vector<uint8_t>& coinbase_merkle_proof, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path)
|
||||
{
|
||||
(void)chain_params;
|
||||
submit_solution(coinbase_merkle_proof, hashing_blob, nonce_offset, seed_hash, blob, merkle_proof, merkle_proof_path);
|
||||
}
|
||||
|
||||
virtual void print_status() const = 0;
|
||||
virtual void api_status(log::Stream&) const = 0;
|
||||
|
||||
@@ -317,7 +317,18 @@ void MergeMiningClientJSON_RPC::submit_solution(const std::vector<uint8_t>& /*co
|
||||
|
||||
const std::vector<uint8_t>& aux_blob = (index < NUM_PREVIOUS_HASHES) ? m_previousAuxBlobs[index] : m_chainParams.aux_blob;
|
||||
const hash& aux_hash = (index < NUM_PREVIOUS_HASHES) ? m_previousAuxHashes[index] : m_chainParams.aux_hash;
|
||||
const ChainParameters chain_params = m_chainParams;
|
||||
|
||||
submit_solution_with_params(chain_params, aux_hash, aux_blob, seed_hash, blob, merkle_proof, merkle_proof_path);
|
||||
}
|
||||
|
||||
void MergeMiningClientJSON_RPC::submit_solution(const ChainParameters& chain_params, const std::vector<uint8_t>& /*coinbase_merkle_proof*/, const uint8_t (&/*hashing_blob*/)[128], size_t /*nonce_offset*/, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path)
|
||||
{
|
||||
submit_solution_with_params(chain_params, chain_params.aux_hash, chain_params.aux_blob, seed_hash, blob, merkle_proof, merkle_proof_path);
|
||||
}
|
||||
|
||||
void MergeMiningClientJSON_RPC::submit_solution_with_params(const ChainParameters& /*chain_params*/, const hash& aux_hash, const std::vector<uint8_t>& aux_blob, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path)
|
||||
{
|
||||
std::vector<char> buf((aux_blob.size() + HASH_SIZE + blob.size()) * 2 + merkle_proof.size() * (HASH_SIZE * 2 + 3) + 256);
|
||||
log::Stream s(buf.data(), buf.size());
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
|
||||
bool get_params(ChainParameters& out_params) const override;
|
||||
void submit_solution(const std::vector<uint8_t>& coinbase_merkle_proof, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path) override;
|
||||
void submit_solution(const ChainParameters& chain_params, const std::vector<uint8_t>& coinbase_merkle_proof, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path) override;
|
||||
|
||||
void print_status() const override;
|
||||
void api_status(log::Stream&) const override;
|
||||
@@ -51,6 +52,7 @@ private:
|
||||
bool parse_merge_mining_get_aux_block(const char* data, size_t size, bool& changed);
|
||||
|
||||
bool parse_merge_mining_submit_solution(const char* data, size_t size) const;
|
||||
void submit_solution_with_params(const ChainParameters& chain_params, const hash& aux_hash, const std::vector<uint8_t>& aux_blob, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path);
|
||||
|
||||
std::vector<uint8_t> m_previousAuxBlobs[NUM_PREVIOUS_HASHES];
|
||||
|
||||
|
||||
+1
-1
@@ -256,7 +256,7 @@ void Miner::run(WorkerData* data)
|
||||
for (const AuxChainData& aux_data : j.m_auxChains) {
|
||||
if (aux_data.difficulty.check_pow(h)) {
|
||||
LOGINFO(0, log::Green() << "AUX BLOCK FOUND: chain_id " << aux_data.unique_id << ", diff " << aux_data.difficulty << ", worker thread " << data->m_index << '/' << data->m_count);
|
||||
aux_blocks.emplace_back(p2pool::SubmitAuxBlockData{ aux_data.unique_id, j.m_templateId, j.m_nonce, j.m_extraNonce });
|
||||
aux_blocks.emplace_back(p2pool::SubmitAuxBlockData{ aux_data.unique_id, j.m_templateId, j.m_nonce, j.m_extraNonce, {} });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+130
-27
@@ -27,7 +27,7 @@ LOG_CATEGORY(NodejsPoolRpc)
|
||||
namespace p2pool {
|
||||
|
||||
static constexpr int DEFAULT_BACKLOG = 64;
|
||||
static constexpr size_t MAX_CACHED_WORK_ITEMS = 8;
|
||||
static constexpr size_t MAX_CACHED_WORK_ITEMS = 512;
|
||||
static constexpr size_t NODEJS_POOL_RPC_CALLBACK_BUF_SIZE = 65536;
|
||||
static constexpr size_t EXTERNAL_EXTRA_NONCE_SIZE = 4;
|
||||
static constexpr uint32_t MIN_HASHING_BLOB_BATCH_COUNT = 128;
|
||||
@@ -147,12 +147,43 @@ const char* jsonrpc_id_to_cstr(const rapidjson::Value& id, std::string& tmp)
|
||||
return "0";
|
||||
}
|
||||
|
||||
bool extract_submitblock_blob(const rapidjson::Value& params, std::vector<uint8_t>& blob)
|
||||
bool extract_submitblock_request(const rapidjson::Value& params, std::vector<uint8_t>& blob, uint32_t& template_id, bool& has_template_id)
|
||||
{
|
||||
if (params.IsArray() && !params.Empty() && params[0].IsString()) {
|
||||
has_template_id = false;
|
||||
return from_hex(params[0].GetString(), params[0].GetStringLength(), blob);
|
||||
}
|
||||
|
||||
if (params.IsArray() && !params.Empty() && params[0].IsObject()) {
|
||||
const rapidjson::Value& req = params[0];
|
||||
auto blob_it = req.FindMember("blob");
|
||||
if ((blob_it == req.MemberEnd()) || !blob_it->value.IsString()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
has_template_id = false;
|
||||
auto template_it = req.FindMember("template_id");
|
||||
if (template_it != req.MemberEnd()) {
|
||||
if (template_it->value.IsUint()) {
|
||||
template_id = template_it->value.GetUint();
|
||||
has_template_id = true;
|
||||
}
|
||||
else if (template_it->value.IsUint64() && (template_it->value.GetUint64() <= std::numeric_limits<uint32_t>::max())) {
|
||||
template_id = static_cast<uint32_t>(template_it->value.GetUint64());
|
||||
has_template_id = true;
|
||||
}
|
||||
else if (template_it->value.IsInt64() && (template_it->value.GetInt64() >= 0) && (template_it->value.GetInt64() <= std::numeric_limits<uint32_t>::max())) {
|
||||
template_id = static_cast<uint32_t>(template_it->value.GetInt64());
|
||||
has_template_id = true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return from_hex(blob_it->value.GetString(), blob_it->value.GetStringLength(), blob);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -220,12 +251,14 @@ void NodejsPoolRpc::remember_work_snapshot(const WorkSnapshot& work) const
|
||||
return;
|
||||
}
|
||||
|
||||
WorkSnapshot cached = work;
|
||||
|
||||
MutexLock lock(m_recentWorkLock);
|
||||
|
||||
auto same_template = [&work](const WorkSnapshot& item) {
|
||||
return (item.template_id == work.template_id)
|
||||
&& (item.work_hash == work.work_hash)
|
||||
&& (item.sidechain_height == work.sidechain_height);
|
||||
auto same_template = [&cached](const WorkSnapshot& item) {
|
||||
return (item.template_id == cached.template_id)
|
||||
&& (item.work_hash == cached.work_hash)
|
||||
&& (item.sidechain_height == cached.sidechain_height);
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < m_recentWork.size(); ++i) {
|
||||
@@ -235,7 +268,7 @@ void NodejsPoolRpc::remember_work_snapshot(const WorkSnapshot& work) const
|
||||
}
|
||||
}
|
||||
|
||||
m_recentWork.insert(m_recentWork.begin(), work);
|
||||
m_recentWork.insert(m_recentWork.begin(), std::move(cached));
|
||||
if (m_recentWork.size() > MAX_CACHED_WORK_ITEMS) {
|
||||
m_recentWork.resize(MAX_CACHED_WORK_ITEMS);
|
||||
}
|
||||
@@ -273,6 +306,50 @@ bool NodejsPoolRpc::find_cached_work_by_block_blob(const std::vector<uint8_t>& b
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NodejsPoolRpc::find_cached_work_by_template_id(uint32_t template_id, WorkSnapshot& out) const
|
||||
{
|
||||
MutexLock lock(m_recentWorkLock);
|
||||
|
||||
for (const WorkSnapshot& work : m_recentWork) {
|
||||
if (!work.ready) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (work.template_id == template_id) {
|
||||
out = work;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t NodejsPoolRpc::copy_cached_hashing_blob(const WorkSnapshot& work, uint32_t extra_nonce, uint8_t (&blob)[128], size_t& nonce_offset) const
|
||||
{
|
||||
if (!work.hashing_blob_size || !work.hashing_blob_count || work.hashing_blobs.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (extra_nonce < work.hashing_blob_extra_nonce_start) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint32_t index = extra_nonce - work.hashing_blob_extra_nonce_start;
|
||||
if (index >= work.hashing_blob_count) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const size_t blob_size = work.hashing_blob_size;
|
||||
const size_t offset = static_cast<size_t>(index) * blob_size;
|
||||
if ((blob_size > sizeof(blob)) || (offset + blob_size > work.hashing_blobs.size())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(blob, work.hashing_blobs.data() + offset, blob_size);
|
||||
nonce_offset = work.hashing_nonce_offset;
|
||||
return static_cast<uint32_t>(blob_size);
|
||||
}
|
||||
|
||||
bool NodejsPoolRpc::make_work_snapshot(WorkSnapshot& out, uint32_t hashing_blob_batch_count) const
|
||||
{
|
||||
const MinerData miner_data = m_pool->miner_data();
|
||||
@@ -327,6 +404,15 @@ bool NodejsPoolRpc::make_work_snapshot(WorkSnapshot& out, uint32_t hashing_blob_
|
||||
out.submit_difficulty = aux_diff.empty() ? sidechain_diff : aux_diff;
|
||||
out.block_template_blob = std::move(block_template_blob);
|
||||
out.hashing_blob.assign(hashing_blob, hashing_blob + hashing_blob_size);
|
||||
out.aux_chains = m_pool->block_template().get_aux_chains(template_id);
|
||||
out.aux_chain_params.clear();
|
||||
out.aux_chain_params.reserve(out.aux_chains.size());
|
||||
for (const AuxChainData& aux_data : out.aux_chains) {
|
||||
IMergeMiningClient::ChainParameters chain_params;
|
||||
if (m_pool->get_merge_mining_chain_params(aux_data.unique_id, chain_params) && (chain_params.aux_hash == aux_data.data) && !chain_params.aux_blob.empty()) {
|
||||
out.aux_chain_params.push_back(std::move(chain_params));
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t batch_height = 0;
|
||||
difficulty_type batch_mainchain_diff, batch_aux_diff, batch_sidechain_diff;
|
||||
@@ -582,12 +668,17 @@ std::string NodejsPoolRpc::build_json_rpc_response(const std::string& body) cons
|
||||
}
|
||||
|
||||
std::vector<uint8_t> blob;
|
||||
if (!extract_submitblock_blob(params_it->value, blob) || blob.empty()) {
|
||||
uint32_t requested_template_id = 0;
|
||||
bool has_requested_template_id = false;
|
||||
if (!extract_submitblock_request(params_it->value, blob, requested_template_id, has_requested_template_id) || blob.empty()) {
|
||||
return json_error_response(id, -32602, "invalid blob");
|
||||
}
|
||||
|
||||
WorkSnapshot work;
|
||||
if (!find_cached_work_by_block_blob(blob, work)) {
|
||||
const bool found_work = has_requested_template_id
|
||||
? find_cached_work_by_template_id(requested_template_id, work)
|
||||
: find_cached_work_by_block_blob(blob, work);
|
||||
if (!found_work) {
|
||||
return json_error_response(id, 0, "unknown_or_stale_template");
|
||||
}
|
||||
|
||||
@@ -601,16 +692,21 @@ std::string NodejsPoolRpc::build_json_rpc_response(const std::string& body) cons
|
||||
}
|
||||
const uint32_t extra_nonce = read_u32_le(blob.data() + work.extra_nonce_offset);
|
||||
|
||||
uint8_t hashing_blob[128] = {};
|
||||
uint64_t height = 0;
|
||||
difficulty_type mainchain_diff, aux_diff, sidechain_diff;
|
||||
hash seed_hash;
|
||||
size_t nonce_offset = 0;
|
||||
uint8_t hashing_blob[128] = {};
|
||||
uint64_t height = work.mining_height;
|
||||
difficulty_type mainchain_diff = work.mainchain_difficulty;
|
||||
difficulty_type aux_diff = work.aux_difficulty;
|
||||
difficulty_type sidechain_diff = work.sidechain_difficulty;
|
||||
hash seed_hash = work.seed_hash;
|
||||
size_t nonce_offset = 0;
|
||||
|
||||
const uint32_t hashing_blob_size = m_pool->block_template().get_hashing_blob(work.template_id, extra_nonce, hashing_blob, height, mainchain_diff, aux_diff, sidechain_diff, seed_hash, nonce_offset);
|
||||
if (!hashing_blob_size || (nonce_offset + NONCE_SIZE > hashing_blob_size)) {
|
||||
return json_error_response(id, 0, "stale_template");
|
||||
}
|
||||
uint32_t hashing_blob_size = copy_cached_hashing_blob(work, extra_nonce, hashing_blob, nonce_offset);
|
||||
if (!hashing_blob_size) {
|
||||
hashing_blob_size = m_pool->block_template().get_hashing_blob(work.template_id, extra_nonce, hashing_blob, height, mainchain_diff, aux_diff, sidechain_diff, seed_hash, nonce_offset);
|
||||
}
|
||||
if (!hashing_blob_size || (nonce_offset + NONCE_SIZE > hashing_blob_size)) {
|
||||
return json_error_response(id, 0, "stale_template");
|
||||
}
|
||||
|
||||
memcpy(hashing_blob + nonce_offset, blob.data() + work.nonce_offset, NONCE_SIZE);
|
||||
|
||||
@@ -647,17 +743,24 @@ std::string NodejsPoolRpc::build_json_rpc_response(const std::string& body) cons
|
||||
parent_submitted = true;
|
||||
}
|
||||
|
||||
if (meets_aux) {
|
||||
const std::vector<AuxChainData> aux_chains = m_pool->block_template().get_aux_chains(work.template_id);
|
||||
if (meets_aux) {
|
||||
std::vector<p2pool::SubmitAuxBlockData> aux_blocks;
|
||||
aux_blocks.reserve(work.aux_chains.size());
|
||||
|
||||
std::vector<p2pool::SubmitAuxBlockData> aux_blocks;
|
||||
aux_blocks.reserve(aux_chains.size());
|
||||
|
||||
for (const AuxChainData& aux_data : aux_chains) {
|
||||
if (aux_data.difficulty.check_pow(result_hash)) {
|
||||
aux_blocks.emplace_back(p2pool::SubmitAuxBlockData{ aux_data.unique_id, work.template_id, nonce, extra_nonce });
|
||||
for (const AuxChainData& aux_data : work.aux_chains) {
|
||||
if (aux_data.difficulty.check_pow(result_hash)) {
|
||||
auto params_it = std::find_if(work.aux_chain_params.begin(), work.aux_chain_params.end(),
|
||||
[&aux_data](const IMergeMiningClient::ChainParameters& params) {
|
||||
return (params.aux_id == aux_data.unique_id) && (params.aux_hash == aux_data.data);
|
||||
});
|
||||
if (params_it == work.aux_chain_params.end()) {
|
||||
LOGWARN(3, "NodejsPoolRpc submitblock: missing cached aux params for chain_id = " << aux_data.unique_id
|
||||
<< ", aux_hash = " << aux_data.data);
|
||||
continue;
|
||||
}
|
||||
aux_blocks.emplace_back(p2pool::SubmitAuxBlockData{ aux_data.unique_id, work.template_id, nonce, extra_nonce, *params_it });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aux_submitted = aux_blocks.size();
|
||||
if (!aux_blocks.empty()) {
|
||||
|
||||
+24
-19
@@ -18,6 +18,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "tcp_server.h"
|
||||
#include "merge_mining_client.h"
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
@@ -32,30 +33,32 @@ public:
|
||||
void on_shutdown() override;
|
||||
|
||||
private:
|
||||
struct WorkSnapshot
|
||||
{
|
||||
bool ready = false;
|
||||
uint64_t mainchain_height = 0;
|
||||
uint64_t mining_height = 0;
|
||||
uint64_t sidechain_height = 0;
|
||||
struct WorkSnapshot
|
||||
{
|
||||
bool ready = false;
|
||||
uint64_t mainchain_height = 0;
|
||||
uint64_t mining_height = 0;
|
||||
uint64_t sidechain_height = 0;
|
||||
hash parent_prev_id;
|
||||
hash seed_hash;
|
||||
hash work_hash;
|
||||
uint32_t template_id = 0;
|
||||
size_t nonce_offset = 0;
|
||||
size_t hashing_nonce_offset = 0;
|
||||
size_t extra_nonce_offset = 0;
|
||||
size_t extra_nonce_size = 4;
|
||||
uint32_t hashing_blob_extra_nonce_start = 0;
|
||||
uint32_t hashing_blob_count = 0;
|
||||
uint32_t hashing_blob_size = 0;
|
||||
difficulty_type mainchain_difficulty;
|
||||
difficulty_type sidechain_difficulty;
|
||||
difficulty_type aux_difficulty;
|
||||
difficulty_type submit_difficulty;
|
||||
std::vector<uint8_t> block_template_blob;
|
||||
uint32_t template_id = 0;
|
||||
size_t nonce_offset = 0;
|
||||
size_t hashing_nonce_offset = 0;
|
||||
size_t extra_nonce_offset = 0;
|
||||
size_t extra_nonce_size = 4;
|
||||
uint32_t hashing_blob_extra_nonce_start = 0;
|
||||
uint32_t hashing_blob_count = 0;
|
||||
uint32_t hashing_blob_size = 0;
|
||||
difficulty_type mainchain_difficulty;
|
||||
difficulty_type sidechain_difficulty;
|
||||
difficulty_type aux_difficulty;
|
||||
difficulty_type submit_difficulty;
|
||||
std::vector<uint8_t> block_template_blob;
|
||||
std::vector<uint8_t> hashing_blob;
|
||||
std::vector<uint8_t> hashing_blobs;
|
||||
std::vector<AuxChainData> aux_chains;
|
||||
std::vector<IMergeMiningClient::ChainParameters> aux_chain_params;
|
||||
};
|
||||
|
||||
struct RpcClient : public Client
|
||||
@@ -87,7 +90,9 @@ private:
|
||||
|
||||
bool make_work_snapshot(WorkSnapshot& out, uint32_t hashing_blob_batch_count) const;
|
||||
void remember_work_snapshot(const WorkSnapshot& work) const;
|
||||
bool find_cached_work_by_template_id(uint32_t template_id, WorkSnapshot& out) const;
|
||||
bool find_cached_work_by_block_blob(const std::vector<uint8_t>& blob, WorkSnapshot& out) const;
|
||||
uint32_t copy_cached_hashing_blob(const WorkSnapshot& work, uint32_t extra_nonce, uint8_t (&blob)[128], size_t& nonce_offset) const;
|
||||
bool handle_http_request(RpcClient* client);
|
||||
std::string build_get_height_response() const;
|
||||
std::string build_json_rpc_response(const std::string& body) const;
|
||||
|
||||
+27
-6
@@ -658,6 +658,21 @@ void p2pool::set_aux_job_donation(const std::vector<IMergeMiningClient::ChainPar
|
||||
}
|
||||
#endif
|
||||
|
||||
bool p2pool::get_merge_mining_chain_params(const hash& chain_id, IMergeMiningClient::ChainParameters& out_params) const
|
||||
{
|
||||
ReadLock lock(m_mergeMiningClientsLock);
|
||||
|
||||
IMergeMiningClient::ChainParameters chain_params;
|
||||
for (const IMergeMiningClient* c : m_mergeMiningClients) {
|
||||
if (c->get_params(chain_params) && (chain_params.aux_id == chain_id)) {
|
||||
out_params = chain_params;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void p2pool::update_aux_data(const hash& chain_id)
|
||||
{
|
||||
if (m_stopped) {
|
||||
@@ -965,12 +980,13 @@ bool p2pool::remember_recent_aux_submit(const SubmitAuxBlockData& data) const
|
||||
if ((item.chain_id == data.chain_id)
|
||||
&& (item.template_id == data.template_id)
|
||||
&& (item.nonce == data.nonce)
|
||||
&& (item.extra_nonce == data.extra_nonce)) {
|
||||
&& (item.extra_nonce == data.extra_nonce)
|
||||
&& (data.chain_params.aux_hash.empty() || item.aux_hash.empty() || (item.aux_hash == data.chain_params.aux_hash))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_recentAuxSubmits.push_back(RecentAuxSubmit{ data.chain_id, data.template_id, data.nonce, data.extra_nonce, now });
|
||||
m_recentAuxSubmits.push_back(RecentAuxSubmit{ data.chain_id, data.chain_params.aux_hash, data.template_id, data.nonce, data.extra_nonce, now });
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1025,24 +1041,29 @@ void p2pool::submit_aux_block() const
|
||||
}
|
||||
|
||||
if (chain_id == chain_params.aux_id) {
|
||||
IMergeMiningClient::ChainParameters submit_chain_params = submit_data[i].chain_params;
|
||||
if (submit_chain_params.aux_id.empty() || submit_chain_params.aux_hash.empty() || submit_chain_params.aux_blob.empty()) {
|
||||
submit_chain_params = chain_params;
|
||||
}
|
||||
|
||||
std::vector<hash> proof;
|
||||
uint32_t path;
|
||||
|
||||
if (m_blockTemplate->get_aux_proof(template_id, extra_nonce, chain_params.aux_hash, proof, path)) {
|
||||
if (m_blockTemplate->get_aux_proof(template_id, extra_nonce, submit_chain_params.aux_hash, proof, path)) {
|
||||
if (pool_block_debug()) {
|
||||
const MinerData data = miner_data();
|
||||
const uint32_t n_aux_chains = static_cast<uint32_t>(data.aux_chains.size() + 1);
|
||||
const uint32_t index = get_aux_slot(chain_params.aux_id, data.aux_nonce, n_aux_chains);
|
||||
|
||||
if (!verify_merkle_proof(chain_params.aux_hash, proof, index, n_aux_chains, merge_mining_root)) {
|
||||
if (!verify_merkle_proof(submit_chain_params.aux_hash, proof, index, n_aux_chains, merge_mining_root)) {
|
||||
LOGERR(0, "submit_aux_block: verify_merkle_proof (1) failed for chain_id " << chain_id);
|
||||
}
|
||||
if (!verify_merkle_proof(chain_params.aux_hash, proof, path, merge_mining_root)) {
|
||||
if (!verify_merkle_proof(submit_chain_params.aux_hash, proof, path, merge_mining_root)) {
|
||||
LOGERR(0, "submit_aux_block: verify_merkle_proof (2) failed for chain_id " << chain_id);
|
||||
}
|
||||
}
|
||||
|
||||
c->submit_solution(block_tpl->get_coinbase_merkle_proof(), hashing_blob, nonce_offset, seed_hash, blob, proof, path);
|
||||
c->submit_solution(submit_chain_params, block_tpl->get_coinbase_merkle_proof(), hashing_blob, nonce_offset, seed_hash, blob, proof, path);
|
||||
}
|
||||
else {
|
||||
LOGWARN(3, "submit_aux_block: failed to get merkle proof for chain_id " << chain_id);
|
||||
|
||||
@@ -96,6 +96,7 @@ public:
|
||||
#endif
|
||||
|
||||
void update_aux_data(const hash& chain_id);
|
||||
bool get_merge_mining_chain_params(const hash& chain_id, IMergeMiningClient::ChainParameters& out_params) const;
|
||||
|
||||
void submit_block_async(uint32_t template_id, uint32_t nonce, uint32_t extra_nonce);
|
||||
void submit_block_async(std::vector<uint8_t>&& blob);
|
||||
@@ -106,6 +107,7 @@ public:
|
||||
uint32_t template_id = 0;
|
||||
uint32_t nonce = 0;
|
||||
uint32_t extra_nonce = 0;
|
||||
IMergeMiningClient::ChainParameters chain_params;
|
||||
};
|
||||
|
||||
void submit_aux_block_async(const std::vector<SubmitAuxBlockData>& aux_blocks);
|
||||
@@ -258,6 +260,7 @@ private:
|
||||
struct RecentAuxSubmit
|
||||
{
|
||||
hash chain_id;
|
||||
hash aux_hash;
|
||||
uint32_t template_id = 0;
|
||||
uint32_t nonce = 0;
|
||||
uint32_t extra_nonce = 0;
|
||||
|
||||
@@ -445,7 +445,7 @@ bool StratumServer::on_submit(StratumClient* client, uint32_t id, const char* jo
|
||||
if (aux_data.difficulty.check_pow(resultHash)) {
|
||||
const char* s = client->m_customUser;
|
||||
LOGINFO(0, log::Green() << "client " << static_cast<char*>(client->m_addrString) << (*s ? " user " : "") << s << " found an aux block for chain_id " << aux_data.unique_id << ", diff " << aux_data.difficulty << ", submitting it");
|
||||
aux_blocks.emplace_back(p2pool::SubmitAuxBlockData{ aux_data.unique_id, template_id, nonce, extra_nonce });
|
||||
aux_blocks.emplace_back(p2pool::SubmitAuxBlockData{ aux_data.unique_id, template_id, nonce, extra_nonce, {} });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user