diff --git a/src/block_template.cpp b/src/block_template.cpp index 159bb1f..44eba34 100644 --- a/src/block_template.cpp +++ b/src/block_template.cpp @@ -51,6 +51,7 @@ BlockTemplate::BlockTemplate(SideChain* sidechain, RandomX_Hasher_Base* hasher) , m_prevId{} , m_height(0) , m_difficulty{} + , m_auxDifficulty{} , m_seedHash{} , m_timestamp(0) , m_poolBlockTemplate(new PoolBlock()) @@ -133,6 +134,7 @@ BlockTemplate& BlockTemplate::operator=(const BlockTemplate& b) m_prevId = b.m_prevId; m_height = b.m_height.load(); m_difficulty = b.m_difficulty; + m_auxDifficulty = b.m_auxDifficulty; m_seedHash = b.m_seedHash; m_timestamp = b.m_timestamp; *m_poolBlockTemplate = *b.m_poolBlockTemplate; @@ -1155,7 +1157,7 @@ void BlockTemplate::calc_merkle_tree_main_branch() } } -bool BlockTemplate::get_difficulties(const uint32_t template_id, uint64_t& height, uint64_t& sidechain_height, difficulty_type& mainchain_difficulty, difficulty_type& sidechain_difficulty) const +bool BlockTemplate::get_difficulties(const uint32_t template_id, uint64_t& height, uint64_t& sidechain_height, difficulty_type& mainchain_difficulty, difficulty_type& aux_diff, difficulty_type& sidechain_difficulty) const { ReadLock lock(m_lock); @@ -1163,6 +1165,7 @@ bool BlockTemplate::get_difficulties(const uint32_t template_id, uint64_t& heigh height = m_height; sidechain_height = m_poolBlockTemplate->m_sidechainHeight; mainchain_difficulty = m_difficulty; + aux_diff = m_auxDifficulty; sidechain_difficulty = m_poolBlockTemplate->m_difficulty; return true; } @@ -1170,19 +1173,20 @@ bool BlockTemplate::get_difficulties(const uint32_t template_id, uint64_t& heigh const BlockTemplate* old = m_oldTemplates[template_id % array_size(&BlockTemplate::m_oldTemplates)]; if (old && (template_id == old->m_templateId)) { - return old->get_difficulties(template_id, height, sidechain_height, mainchain_difficulty, sidechain_difficulty); + return old->get_difficulties(template_id, height, sidechain_height, mainchain_difficulty, aux_diff, sidechain_difficulty); } return false; } -uint32_t BlockTemplate::get_hashing_blob(const uint32_t template_id, uint32_t extra_nonce, uint8_t (&blob)[128], uint64_t& height, difficulty_type& difficulty, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset) const +uint32_t BlockTemplate::get_hashing_blob(const uint32_t template_id, uint32_t extra_nonce, uint8_t (&blob)[128], uint64_t& height, difficulty_type& difficulty, difficulty_type& aux_diff, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset) const { ReadLock lock(m_lock); if (template_id == m_templateId) { height = m_height; difficulty = m_difficulty; + aux_diff = m_auxDifficulty; sidechain_difficulty = m_poolBlockTemplate->m_difficulty; seed_hash = m_seedHash; nonce_offset = m_nonceOffset; @@ -1193,19 +1197,20 @@ uint32_t BlockTemplate::get_hashing_blob(const uint32_t template_id, uint32_t ex const BlockTemplate* old = m_oldTemplates[template_id % array_size(&BlockTemplate::m_oldTemplates)]; if (old && (template_id == old->m_templateId)) { - return old->get_hashing_blob(template_id, extra_nonce, blob, height, difficulty, sidechain_difficulty, seed_hash, nonce_offset); + return old->get_hashing_blob(template_id, extra_nonce, blob, height, difficulty, aux_diff, sidechain_difficulty, seed_hash, nonce_offset); } return 0; } -uint32_t BlockTemplate::get_hashing_blob(uint32_t extra_nonce, uint8_t (&blob)[128], uint64_t& height, uint64_t& sidechain_height, difficulty_type& difficulty, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset, uint32_t& template_id) const +uint32_t BlockTemplate::get_hashing_blob(uint32_t extra_nonce, uint8_t (&blob)[128], uint64_t& height, uint64_t& sidechain_height, difficulty_type& difficulty, difficulty_type& aux_diff, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset, uint32_t& template_id) const { ReadLock lock(m_lock); height = m_height; sidechain_height = m_poolBlockTemplate->m_sidechainHeight; difficulty = m_difficulty; + aux_diff = m_auxDifficulty; sidechain_difficulty = m_poolBlockTemplate->m_difficulty; seed_hash = m_seedHash; nonce_offset = m_nonceOffset; @@ -1243,7 +1248,7 @@ uint32_t BlockTemplate::get_hashing_blob_nolock(uint32_t extra_nonce, uint8_t* b return static_cast(p - blob); } -uint32_t BlockTemplate::get_hashing_blobs(uint32_t extra_nonce_start, uint32_t count, std::vector& blobs, uint64_t& height, difficulty_type& difficulty, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset, uint32_t& template_id) const +uint32_t BlockTemplate::get_hashing_blobs(uint32_t extra_nonce_start, uint32_t count, std::vector& blobs, uint64_t& height, difficulty_type& difficulty, difficulty_type& aux_diff, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset, uint32_t& template_id) const { blobs.clear(); @@ -1258,6 +1263,7 @@ uint32_t BlockTemplate::get_hashing_blobs(uint32_t extra_nonce_start, uint32_t c height = m_height; difficulty = m_difficulty; + aux_diff = m_auxDifficulty; sidechain_difficulty = m_poolBlockTemplate->m_difficulty; seed_hash = m_seedHash; nonce_offset = m_nonceOffset; @@ -1382,6 +1388,7 @@ void BlockTemplate::init_merge_mining_merkle_proof() const uint32_t n_aux_chains = static_cast(m_poolBlockTemplate->m_auxChains.size() + 1); m_poolBlockTemplate->m_merkleProof.clear(); + m_auxDifficulty = diff_max; if (n_aux_chains == 1) { return; @@ -1394,6 +1401,10 @@ void BlockTemplate::init_merge_mining_merkle_proof() const uint32_t aux_slot = get_aux_slot(aux_data.unique_id, m_poolBlockTemplate->m_auxNonce, n_aux_chains); hashes[aux_slot] = aux_data.data; used[aux_slot] = true; + + if (aux_data.difficulty < m_auxDifficulty) { + m_auxDifficulty = aux_data.difficulty; + } } const uint32_t aux_slot = get_aux_slot(m_sidechain->consensus_hash(), m_poolBlockTemplate->m_auxNonce, n_aux_chains); diff --git a/src/block_template.h b/src/block_template.h index 0eb8b3b..2a66a61 100644 --- a/src/block_template.h +++ b/src/block_template.h @@ -42,11 +42,11 @@ public: void update(const MinerData& data, const Mempool& mempool, const Wallet* miner_wallet); uint64_t last_updated() const { return m_lastUpdated.load(); } - bool get_difficulties(const uint32_t template_id, uint64_t& height, uint64_t& sidechain_height, difficulty_type& mainchain_difficulty, difficulty_type& sidechain_difficulty) const; - uint32_t get_hashing_blob(const uint32_t template_id, uint32_t extra_nonce, uint8_t (&blob)[128], uint64_t& height, difficulty_type& difficulty, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset) const; + bool get_difficulties(const uint32_t template_id, uint64_t& height, uint64_t& sidechain_height, difficulty_type& mainchain_difficulty, difficulty_type& aux_diff, difficulty_type& sidechain_difficulty) const; + uint32_t get_hashing_blob(const uint32_t template_id, uint32_t extra_nonce, uint8_t (&blob)[128], uint64_t& height, difficulty_type& difficulty, difficulty_type& aux_diff, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset) const; - uint32_t get_hashing_blob(uint32_t extra_nonce, uint8_t (&blob)[128], uint64_t& height, uint64_t& sidechain_height, difficulty_type& difficulty, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset, uint32_t& template_id) const; - uint32_t get_hashing_blobs(uint32_t extra_nonce_start, uint32_t count, std::vector& blobs, uint64_t& height, difficulty_type& difficulty, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset, uint32_t& template_id) const; + uint32_t get_hashing_blob(uint32_t extra_nonce, uint8_t (&blob)[128], uint64_t& height, uint64_t& sidechain_height, difficulty_type& difficulty, difficulty_type& aux_diff, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset, uint32_t& template_id) const; + uint32_t get_hashing_blobs(uint32_t extra_nonce_start, uint32_t count, std::vector& blobs, uint64_t& height, difficulty_type& difficulty, difficulty_type& aux_diff, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset, uint32_t& template_id) const; std::vector get_block_template_blob(uint32_t template_id, uint32_t sidechain_extra_nonce, size_t& nonce_offset, size_t& extra_nonce_offset, size_t& sidechain_id_offset, hash& sidechain_id) const; @@ -94,6 +94,7 @@ private: hash m_prevId; std::atomic m_height; difficulty_type m_difficulty; + difficulty_type m_auxDifficulty; hash m_seedHash; uint64_t m_timestamp; diff --git a/src/miner.cpp b/src/miner.cpp index 50fcc32..ba7b9fe 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -107,7 +107,7 @@ void Miner::on_block(const BlockTemplate& block) hash seed; const uint32_t extra_nonce = static_cast(m_rng() >> 32); - j.m_blobSize = block.get_hashing_blob(extra_nonce, j.m_blob, j.m_height, j.m_sidechainHeight, j.m_diff, j.m_sidechainDiff, seed, j.m_nonceOffset, j.m_templateId); + j.m_blobSize = block.get_hashing_blob(extra_nonce, j.m_blob, j.m_height, j.m_sidechainHeight, j.m_diff, j.m_auxDiff, j.m_sidechainDiff, seed, j.m_nonceOffset, j.m_templateId); const uint64_t next_full_nonce = (static_cast(extra_nonce) << 32) | std::numeric_limits::max(); const uint32_t hash_count = std::numeric_limits::max() - static_cast(m_fullNonce.exchange(next_full_nonce)); @@ -240,6 +240,10 @@ void Miner::run(WorkerData* data) m_pool->submit_block_async(j.m_templateId, j.m_nonce, j.m_extraNonce); } + if (j.m_auxDiff.check_pow(h)) { + // TODO + } + if (j.m_sidechainDiff.check_pow(h)) { LOGINFO(0, log::Green() << "SHARE FOUND: mainchain height " << j.m_height << ", sidechain height " << j.m_sidechainHeight << ", diff " << j.m_sidechainDiff << ", worker thread " << data->m_index << '/' << data->m_count); ++m_sharesFound; diff --git a/src/miner.h b/src/miner.h index 57a0b6f..4153d98 100644 --- a/src/miner.h +++ b/src/miner.h @@ -69,6 +69,7 @@ private: uint32_t m_blobSize = 0; uint32_t m_templateId = 0; difficulty_type m_diff = {}; + difficulty_type m_auxDiff = {}; difficulty_type m_sidechainDiff = {}; uint64_t m_height = 0; uint64_t m_sidechainHeight = 0; diff --git a/src/stratum_server.cpp b/src/stratum_server.cpp index e6828ec..4f98c57 100644 --- a/src/stratum_server.cpp +++ b/src/stratum_server.cpp @@ -128,6 +128,7 @@ void StratumServer::on_block(const BlockTemplate& block) blobs_data->m_extraNonceStart = extra_nonce_start; difficulty_type difficulty; + difficulty_type aux_diff; difficulty_type sidechain_difficulty; size_t nonce_offset; @@ -135,7 +136,7 @@ void StratumServer::on_block(const BlockTemplate& block) // Even if they do, they'll be added to the beginning of the list and will get their block template in on_login() // We'll iterate through the list backwards so when we get to the beginning and run out of extra_nonce values, it'll be only new clients left blobs_data->m_numClientsExpected = num_connections; - blobs_data->m_blobSize = block.get_hashing_blobs(extra_nonce_start, num_connections, blobs_data->m_blobs, blobs_data->m_height, difficulty, sidechain_difficulty, blobs_data->m_seedHash, nonce_offset, blobs_data->m_templateId); + blobs_data->m_blobSize = block.get_hashing_blobs(extra_nonce_start, num_connections, blobs_data->m_blobs, blobs_data->m_height, difficulty, aux_diff, sidechain_difficulty, blobs_data->m_seedHash, nonce_offset, blobs_data->m_templateId); // Integrity checks if (blobs_data->m_blobSize < 76) { @@ -168,6 +169,7 @@ void StratumServer::on_block(const BlockTemplate& block) } blobs_data->m_target = std::max(difficulty.target(), sidechain_difficulty.target()); + blobs_data->m_target = std::max(blobs_data->m_target, aux_diff.target()); { MutexLock lock(m_blobsQueueLock); @@ -256,14 +258,16 @@ bool StratumServer::on_login(StratumClient* client, uint32_t id, const char* log uint8_t hashing_blob[128]; uint64_t height, sidechain_height; difficulty_type difficulty; + difficulty_type aux_diff; difficulty_type sidechain_difficulty; hash seed_hash; size_t nonce_offset; uint32_t template_id; - const size_t blob_size = m_pool->block_template().get_hashing_blob(extra_nonce, hashing_blob, height, sidechain_height, difficulty, sidechain_difficulty, seed_hash, nonce_offset, template_id); + const size_t blob_size = m_pool->block_template().get_hashing_blob(extra_nonce, hashing_blob, height, sidechain_height, difficulty, aux_diff, sidechain_difficulty, seed_hash, nonce_offset, template_id); uint64_t target = std::max(difficulty.target(), sidechain_difficulty.target()); + target = std::max(target, aux_diff.target()); if (get_custom_diff(login, client->m_customDiff)) { LOGINFO(5, "client " << log::Gray() << static_cast(client->m_addrString) << " set custom difficulty " << client->m_customDiff); @@ -377,9 +381,9 @@ bool StratumServer::on_submit(StratumClient* client, uint32_t id, const char* jo if (found) { BlockTemplate& block = m_pool->block_template(); uint64_t height, sidechain_height; - difficulty_type mainchain_diff, sidechain_diff; + difficulty_type mainchain_diff, aux_diff, sidechain_diff; - if (!block.get_difficulties(template_id, height, sidechain_height, mainchain_diff, sidechain_diff)) { + if (!block.get_difficulties(template_id, height, sidechain_height, mainchain_diff, aux_diff, sidechain_diff)) { LOGWARN(4, "client " << static_cast(client->m_addrString) << " got a stale share"); return send(client, [id](uint8_t* buf, size_t buf_size) @@ -396,6 +400,10 @@ bool StratumServer::on_submit(StratumClient* client, uint32_t id, const char* jo m_pool->submit_block_async(template_id, nonce, extra_nonce); } + if (aux_diff.check_pow(resultHash)) { + // TODO + } + SubmittedShare* share; if (!m_submittedSharesPool.empty()) { @@ -881,11 +889,12 @@ void StratumServer::on_share_found(uv_work_t* req) uint8_t blob[128]; uint64_t height; difficulty_type difficulty; + difficulty_type aux_diff; difficulty_type sidechain_difficulty; hash seed_hash; size_t nonce_offset; - const uint32_t blob_size = pool->block_template().get_hashing_blob(share->m_templateId, share->m_extraNonce, blob, height, difficulty, sidechain_difficulty, seed_hash, nonce_offset); + const uint32_t blob_size = pool->block_template().get_hashing_blob(share->m_templateId, share->m_extraNonce, blob, height, difficulty, aux_diff, sidechain_difficulty, seed_hash, nonce_offset); if (!blob_size) { LOGWARN(4, "client " << static_cast(share->m_clientAddrString) << " got a stale share"); share->m_result = SubmittedShare::Result::STALE; diff --git a/tests/src/block_template_tests.cpp b/tests/src/block_template_tests.cpp index ea5af5c..6a76f55 100644 --- a/tests/src/block_template_tests.cpp +++ b/tests/src/block_template_tests.cpp @@ -64,11 +64,11 @@ TEST(block_template, DISABLED_update) std::vector blobs; uint64_t height; - difficulty_type diff, sidechain_diff; + difficulty_type diff, aux_diff, sidechain_diff; hash seed_hash; size_t nonce_offset; uint32_t template_id; - tpl.get_hashing_blobs(0, 10000, blobs, height, diff, sidechain_diff, seed_hash, nonce_offset, template_id); + tpl.get_hashing_blobs(0, 10000, blobs, height, diff, aux_diff, sidechain_diff, seed_hash, nonce_offset, template_id); ASSERT_EQ(height, 2762973); ASSERT_EQ(diff, 300346053753ULL); @@ -99,7 +99,7 @@ TEST(block_template, DISABLED_update) ASSERT_GE(*reinterpret_cast(b->m_transactions[i].h), 256); } - tpl.get_hashing_blobs(0, 10000, blobs, height, diff, sidechain_diff, seed_hash, nonce_offset, template_id); + tpl.get_hashing_blobs(0, 10000, blobs, height, diff, aux_diff, sidechain_diff, seed_hash, nonce_offset, template_id); ASSERT_EQ(height, 2762973); ASSERT_EQ(diff, 300346053753ULL);