Added BlockTemplate tests

pull/226/head
SChernykh 1 year ago
parent 9283677a2b
commit 4bb1982806

@ -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<int>(m_extraNonceOffsetInTemplate + m_poolBlockTemplate->m_extraNonceSize) + 2;
const int blob_size = static_cast<int>(m_blockTemplateBlob.size());
const std::vector<uint8_t>& consensus_id = m_pool->side_chain().consensus_id();
const std::vector<uint8_t>& consensus_id = m_sidechain->consensus_id();
const std::vector<uint8_t> 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<uint8_t> 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;
}

@ -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<MinerShare>& 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<MinerShare>& shares, uint64_t max_reward_amounts_weight, bool dry_run);

@ -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 {

@ -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;

@ -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

@ -0,0 +1,101 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/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 <http://www.gnu.org/licenses/>.
*/
#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<uint8_t> 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<int>(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<uint64_t*>(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<const uint64_t*>(b->m_transactions[i].h), 256);
}
destroy_crypto_cache();
}
}
Loading…
Cancel
Save