From 4bb198280674e4448eeee9160236127f678a6f1f Mon Sep 17 00:00:00 2001 From: SChernykh Date: Thu, 24 Nov 2022 21:38:15 +0100 Subject: [PATCH] Added BlockTemplate tests --- src/block_template.cpp | 39 ++++++----- src/block_template.h | 9 ++- src/p2pool.cpp | 2 +- src/util.cpp | 3 + tests/CMakeLists.txt | 1 + tests/src/block_template_tests.cpp | 101 +++++++++++++++++++++++++++++ 6 files changed, 133 insertions(+), 22 deletions(-) create mode 100644 tests/src/block_template_tests.cpp diff --git a/src/block_template.cpp b/src/block_template.cpp index fd6506e..b67501b 100644 --- a/src/block_template.cpp +++ b/src/block_template.cpp @@ -39,8 +39,9 @@ static constexpr size_t MAX_BLOCK_TEMPLATE_SIZE = 128 * 1024 - (1 + sizeof(uint3 namespace p2pool { -BlockTemplate::BlockTemplate(p2pool* pool) - : m_pool(pool) +BlockTemplate::BlockTemplate(SideChain* sidechain, RandomX_Hasher_Base* hasher) + : m_sidechain(sidechain) + , m_hasher(hasher) , m_templateId(0) , m_lastUpdated(seconds_since_epoch()) , m_blockHeaderSize(0) @@ -75,7 +76,7 @@ BlockTemplate::BlockTemplate(p2pool* pool) m_mempoolTxs.reserve(1024); m_mempoolTxsOrder.reserve(1024); m_mempoolTxsOrder2.reserve(1024); - m_shares.reserve(m_pool->side_chain().chain_window_size() * 2); + m_shares.reserve(m_sidechain->chain_window_size() * 2); for (size_t i = 0; i < array_size(&BlockTemplate::m_oldTemplates); ++i) { m_oldTemplates[i] = new BlockTemplate(*this); @@ -113,7 +114,8 @@ BlockTemplate& BlockTemplate::operator=(const BlockTemplate& b) WriteLock lock(m_lock); - m_pool = b.m_pool; + m_sidechain = b.m_sidechain; + m_hasher = b.m_hasher; m_templateId = b.m_templateId; m_lastUpdated = b.m_lastUpdated.load(); m_blockTemplateBlob = b.m_blockTemplateBlob; @@ -256,7 +258,7 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet m_blockHeaderSize = m_blockHeader.size(); - m_pool->side_chain().fill_sidechain_data(*m_poolBlockTemplate, miner_wallet, m_txkeySec, m_shares); + m_sidechain->fill_sidechain_data(*m_poolBlockTemplate, miner_wallet, m_txkeySec, m_shares); // Only choose transactions that were received 10 or more seconds ago size_t total_mempool_transactions; @@ -596,7 +598,7 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet buf.insert(buf.end(), sidechain_data.begin(), sidechain_data.end()); PoolBlock check; - const int result = check.deserialize(buf.data(), buf.size(), m_pool->side_chain(), nullptr, false); + const int result = check.deserialize(buf.data(), buf.size(), *m_sidechain, nullptr, false); if (result != 0) { LOGERR(1, "pool block blob generation and/or parsing is broken, error " << result); } @@ -626,6 +628,7 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet m_rewards.clear(); m_mempoolTxs.clear(); m_mempoolTxsOrder.clear(); + m_mempoolTxsOrder2.clear(); } #if TEST_MEMPOOL_PICKING_ALGORITHM @@ -832,7 +835,7 @@ hash BlockTemplate::calc_sidechain_hash() const const int sidechain_hash_offset = static_cast(m_extraNonceOffsetInTemplate + m_poolBlockTemplate->m_extraNonceSize) + 2; const int blob_size = static_cast(m_blockTemplateBlob.size()); - const std::vector& consensus_id = m_pool->side_chain().consensus_id(); + const std::vector& consensus_id = m_sidechain->consensus_id(); const std::vector sidechain_data = m_poolBlockTemplate->serialize_sidechain_data(); keccak_custom([this, sidechain_hash_offset, blob_size, consensus_id, &sidechain_data](int offset) -> uint8_t { @@ -1120,8 +1123,6 @@ void BlockTemplate::submit_sidechain_block(uint32_t template_id, uint32_t nonce, m_poolBlockTemplate->m_nonce = nonce; m_poolBlockTemplate->m_extraNonce = extra_nonce; - SideChain& side_chain = m_pool->side_chain(); - #if POOL_BLOCK_DEBUG { std::vector buf = m_poolBlockTemplate->serialize_mainchain_data(); @@ -1133,25 +1134,27 @@ void BlockTemplate::submit_sidechain_block(uint32_t template_id, uint32_t nonce, buf.insert(buf.end(), sidechain_data.begin(), sidechain_data.end()); PoolBlock check; - const int result = check.deserialize(buf.data(), buf.size(), side_chain, nullptr, false); + const int result = check.deserialize(buf.data(), buf.size(), *m_sidechain, nullptr, false); if (result != 0) { LOGERR(1, "pool block blob generation and/or parsing is broken, error " << result); } - hash pow_hash; - if (!check.get_pow_hash(m_pool->hasher(), check.m_txinGenHeight, m_seedHash, pow_hash)) { - LOGERR(1, "PoW check failed for the sidechain block. Fix it! "); - } - else if (!check.m_difficulty.check_pow(pow_hash)) { - LOGERR(1, "Sidechain block has wrong PoW. Fix it! "); + if (m_hasher) { + hash pow_hash; + if (!check.get_pow_hash(m_hasher, check.m_txinGenHeight, m_seedHash, pow_hash)) { + LOGERR(1, "PoW check failed for the sidechain block. Fix it! "); + } + else if (!check.m_difficulty.check_pow(pow_hash)) { + LOGERR(1, "Sidechain block has wrong PoW. Fix it! "); + } } } #endif m_poolBlockTemplate->m_verified = true; - if (!side_chain.block_seen(*m_poolBlockTemplate)) { + if (!m_sidechain->block_seen(*m_poolBlockTemplate)) { m_poolBlockTemplate->m_wantBroadcast = true; - side_chain.add_block(*m_poolBlockTemplate); + m_sidechain->add_block(*m_poolBlockTemplate); } return; } diff --git a/src/block_template.h b/src/block_template.h index 630a757..4879e5b 100644 --- a/src/block_template.h +++ b/src/block_template.h @@ -23,7 +23,8 @@ namespace p2pool { -class p2pool; +class SideChain; +class RandomX_Hasher_Base; class Mempool; class Wallet; struct PoolBlock; @@ -32,7 +33,7 @@ struct MinerShare; class BlockTemplate { public: - explicit BlockTemplate(p2pool* pool); + explicit BlockTemplate(SideChain* sidechain, RandomX_Hasher_Base* hasher); ~BlockTemplate(); BlockTemplate(const BlockTemplate& b); @@ -55,9 +56,11 @@ public: void submit_sidechain_block(uint32_t template_id, uint32_t nonce, uint32_t extra_nonce); FORCEINLINE const std::vector& shares() const { return m_shares; } + FORCEINLINE const PoolBlock* pool_block_template() const { return m_poolBlockTemplate; } private: - p2pool* m_pool; + SideChain* m_sidechain; + RandomX_Hasher_Base* m_hasher; private: int create_miner_tx(const MinerData& data, const std::vector& shares, uint64_t max_reward_amounts_weight, bool dry_run); diff --git a/src/p2pool.cpp b/src/p2pool.cpp index c911165..53bb60b 100644 --- a/src/p2pool.cpp +++ b/src/p2pool.cpp @@ -162,7 +162,7 @@ p2pool::p2pool(int argc, char* argv[]) m_hasher = new RandomX_Hasher_RPC(this); #endif - m_blockTemplate = new BlockTemplate(this); + m_blockTemplate = new BlockTemplate(m_sideChain, m_hasher); m_mempool = new Mempool(); try { diff --git a/src/util.cpp b/src/util.cpp index 1f12b68..5e55831 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -238,6 +238,9 @@ std::istream& operator>>(std::istream& s, hash& h) found_number = true; h.h[index >> 1] = (h.h[index >> 1] << 4) | digit; ++index; + if (index >= HASH_SIZE * 2) { + return s; + } } else if (found_number) { return s; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4be4f73..ceb2da0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -22,6 +22,7 @@ set(HEADERS ) set(SOURCES + src/block_template_tests.cpp src/crypto_tests.cpp src/difficulty_type_tests.cpp src/hash_tests.cpp diff --git a/tests/src/block_template_tests.cpp b/tests/src/block_template_tests.cpp new file mode 100644 index 0000000..2111e99 --- /dev/null +++ b/tests/src/block_template_tests.cpp @@ -0,0 +1,101 @@ +/* + * This file is part of the Monero P2Pool + * Copyright (c) 2021 SChernykh + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "common.h" +#include "crypto.h" +#include "block_template.h" +#include "mempool.h" +#include "side_chain.h" +#include "wallet.h" +#include "keccak.h" +#include "gtest/gtest.h" + +namespace p2pool { + +TEST(block_template, update) +{ + init_crypto_cache(); + + SideChain sidechain(nullptr, NetworkType::Mainnet); + BlockTemplate tpl(&sidechain, nullptr); + + auto H = [](const char* s) + { + std::stringstream ss; + ss << s; + hash result; + ss >> result; + return result; + }; + + MinerData data; + data.major_version = 16; + data.height = 2762973; + data.prev_id = H("81a0260b29d5224e88d04b11faff321fbdc11c4570779386b2a1817a86dc622c"); + data.seed_hash = H("33d0fb381466f04d6a1919ced3b698f54a28add3da5a6479b096c67df7a4974c"); + data.difficulty = { 300346053753ULL, 0 }; + data.median_weight = 300000; + data.already_generated_coins = 18204981557254756780ULL; + data.median_timestamp = (1ULL << 35) - 2; + + Mempool mempool; + Wallet wallet("44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg"); + + // Test 1: empty template + tpl.update(data, mempool, &wallet); + + const PoolBlock* b = tpl.pool_block_template(); + ASSERT_EQ(b->m_sidechainId, H("b708e3e456d97c43a7fcbd7b4e7aa29bdf45cd909bba07f915cb5f1d805433e6")); + + std::vector blobs; + uint64_t height; + difficulty_type 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); + + ASSERT_EQ(height, 2762973); + ASSERT_EQ(diff, 300346053753ULL); + ASSERT_EQ(sidechain_diff, sidechain.difficulty()); + ASSERT_EQ(seed_hash, data.seed_hash); + ASSERT_EQ(nonce_offset, 39); + ASSERT_EQ(template_id, 1); + + hash blobs_hash; + keccak(blobs.data(), static_cast(blobs.size()), blobs_hash.h, HASH_SIZE); + ASSERT_EQ(blobs_hash, H("e9154971a27c412175562d23ab458b0d3cf780a8bcecf62ff3f667fed9d3bc1d")); + + // Test 2: mempool with high fee and low fee transactions, it must choose high fee transactions + for (uint64_t i = 0; i < 512; ++i) { + TxMempoolData tx; + *reinterpret_cast(tx.id.h) = i; + tx.fee = (i < 256) ? 30000000 : 60000000; + tx.weight = 1500; + mempool.add(tx); + } + + tpl.update(data, mempool, &wallet); + + for (size_t i = 1; i < b->m_transactions.size(); ++i) { + ASSERT_GE(*reinterpret_cast(b->m_transactions[i].h), 256); + } + + destroy_crypto_cache(); +} + +}