mirror of
https://github.com/SChernykh/p2pool.git
synced 2025-01-03 09:19:24 +00:00
Added BlockTemplate tests
This commit is contained in:
parent
9283677a2b
commit
4bb1982806
6 changed files with 133 additions and 22 deletions
|
@ -39,8 +39,9 @@ static constexpr size_t MAX_BLOCK_TEMPLATE_SIZE = 128 * 1024 - (1 + sizeof(uint3
|
||||||
|
|
||||||
namespace p2pool {
|
namespace p2pool {
|
||||||
|
|
||||||
BlockTemplate::BlockTemplate(p2pool* pool)
|
BlockTemplate::BlockTemplate(SideChain* sidechain, RandomX_Hasher_Base* hasher)
|
||||||
: m_pool(pool)
|
: m_sidechain(sidechain)
|
||||||
|
, m_hasher(hasher)
|
||||||
, m_templateId(0)
|
, m_templateId(0)
|
||||||
, m_lastUpdated(seconds_since_epoch())
|
, m_lastUpdated(seconds_since_epoch())
|
||||||
, m_blockHeaderSize(0)
|
, m_blockHeaderSize(0)
|
||||||
|
@ -75,7 +76,7 @@ BlockTemplate::BlockTemplate(p2pool* pool)
|
||||||
m_mempoolTxs.reserve(1024);
|
m_mempoolTxs.reserve(1024);
|
||||||
m_mempoolTxsOrder.reserve(1024);
|
m_mempoolTxsOrder.reserve(1024);
|
||||||
m_mempoolTxsOrder2.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) {
|
for (size_t i = 0; i < array_size(&BlockTemplate::m_oldTemplates); ++i) {
|
||||||
m_oldTemplates[i] = new BlockTemplate(*this);
|
m_oldTemplates[i] = new BlockTemplate(*this);
|
||||||
|
@ -113,7 +114,8 @@ BlockTemplate& BlockTemplate::operator=(const BlockTemplate& b)
|
||||||
|
|
||||||
WriteLock lock(m_lock);
|
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_templateId = b.m_templateId;
|
||||||
m_lastUpdated = b.m_lastUpdated.load();
|
m_lastUpdated = b.m_lastUpdated.load();
|
||||||
m_blockTemplateBlob = b.m_blockTemplateBlob;
|
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_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
|
// Only choose transactions that were received 10 or more seconds ago
|
||||||
size_t total_mempool_transactions;
|
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());
|
buf.insert(buf.end(), sidechain_data.begin(), sidechain_data.end());
|
||||||
|
|
||||||
PoolBlock check;
|
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) {
|
if (result != 0) {
|
||||||
LOGERR(1, "pool block blob generation and/or parsing is broken, error " << result);
|
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_rewards.clear();
|
||||||
m_mempoolTxs.clear();
|
m_mempoolTxs.clear();
|
||||||
m_mempoolTxsOrder.clear();
|
m_mempoolTxsOrder.clear();
|
||||||
|
m_mempoolTxsOrder2.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TEST_MEMPOOL_PICKING_ALGORITHM
|
#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 sidechain_hash_offset = static_cast<int>(m_extraNonceOffsetInTemplate + m_poolBlockTemplate->m_extraNonceSize) + 2;
|
||||||
const int blob_size = static_cast<int>(m_blockTemplateBlob.size());
|
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();
|
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 {
|
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_nonce = nonce;
|
||||||
m_poolBlockTemplate->m_extraNonce = extra_nonce;
|
m_poolBlockTemplate->m_extraNonce = extra_nonce;
|
||||||
|
|
||||||
SideChain& side_chain = m_pool->side_chain();
|
|
||||||
|
|
||||||
#if POOL_BLOCK_DEBUG
|
#if POOL_BLOCK_DEBUG
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> buf = m_poolBlockTemplate->serialize_mainchain_data();
|
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());
|
buf.insert(buf.end(), sidechain_data.begin(), sidechain_data.end());
|
||||||
|
|
||||||
PoolBlock check;
|
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) {
|
if (result != 0) {
|
||||||
LOGERR(1, "pool block blob generation and/or parsing is broken, error " << result);
|
LOGERR(1, "pool block blob generation and/or parsing is broken, error " << result);
|
||||||
}
|
}
|
||||||
|
|
||||||
hash pow_hash;
|
if (m_hasher) {
|
||||||
if (!check.get_pow_hash(m_pool->hasher(), check.m_txinGenHeight, m_seedHash, pow_hash)) {
|
hash pow_hash;
|
||||||
LOGERR(1, "PoW check failed for the sidechain block. Fix it! ");
|
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! ");
|
else if (!check.m_difficulty.check_pow(pow_hash)) {
|
||||||
|
LOGERR(1, "Sidechain block has wrong PoW. Fix it! ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_poolBlockTemplate->m_verified = true;
|
m_poolBlockTemplate->m_verified = true;
|
||||||
if (!side_chain.block_seen(*m_poolBlockTemplate)) {
|
if (!m_sidechain->block_seen(*m_poolBlockTemplate)) {
|
||||||
m_poolBlockTemplate->m_wantBroadcast = true;
|
m_poolBlockTemplate->m_wantBroadcast = true;
|
||||||
side_chain.add_block(*m_poolBlockTemplate);
|
m_sidechain->add_block(*m_poolBlockTemplate);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,8 @@
|
||||||
|
|
||||||
namespace p2pool {
|
namespace p2pool {
|
||||||
|
|
||||||
class p2pool;
|
class SideChain;
|
||||||
|
class RandomX_Hasher_Base;
|
||||||
class Mempool;
|
class Mempool;
|
||||||
class Wallet;
|
class Wallet;
|
||||||
struct PoolBlock;
|
struct PoolBlock;
|
||||||
|
@ -32,7 +33,7 @@ struct MinerShare;
|
||||||
class BlockTemplate
|
class BlockTemplate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit BlockTemplate(p2pool* pool);
|
explicit BlockTemplate(SideChain* sidechain, RandomX_Hasher_Base* hasher);
|
||||||
~BlockTemplate();
|
~BlockTemplate();
|
||||||
|
|
||||||
BlockTemplate(const BlockTemplate& b);
|
BlockTemplate(const BlockTemplate& b);
|
||||||
|
@ -55,9 +56,11 @@ public:
|
||||||
void submit_sidechain_block(uint32_t template_id, uint32_t nonce, uint32_t extra_nonce);
|
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 std::vector<MinerShare>& shares() const { return m_shares; }
|
||||||
|
FORCEINLINE const PoolBlock* pool_block_template() const { return m_poolBlockTemplate; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
p2pool* m_pool;
|
SideChain* m_sidechain;
|
||||||
|
RandomX_Hasher_Base* m_hasher;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int create_miner_tx(const MinerData& data, const std::vector<MinerShare>& shares, uint64_t max_reward_amounts_weight, bool dry_run);
|
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);
|
m_hasher = new RandomX_Hasher_RPC(this);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_blockTemplate = new BlockTemplate(this);
|
m_blockTemplate = new BlockTemplate(m_sideChain, m_hasher);
|
||||||
m_mempool = new Mempool();
|
m_mempool = new Mempool();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -238,6 +238,9 @@ std::istream& operator>>(std::istream& s, hash& h)
|
||||||
found_number = true;
|
found_number = true;
|
||||||
h.h[index >> 1] = (h.h[index >> 1] << 4) | digit;
|
h.h[index >> 1] = (h.h[index >> 1] << 4) | digit;
|
||||||
++index;
|
++index;
|
||||||
|
if (index >= HASH_SIZE * 2) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (found_number) {
|
else if (found_number) {
|
||||||
return s;
|
return s;
|
||||||
|
|
|
@ -22,6 +22,7 @@ set(HEADERS
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
|
src/block_template_tests.cpp
|
||||||
src/crypto_tests.cpp
|
src/crypto_tests.cpp
|
||||||
src/difficulty_type_tests.cpp
|
src/difficulty_type_tests.cpp
|
||||||
src/hash_tests.cpp
|
src/hash_tests.cpp
|
||||||
|
|
101
tests/src/block_template_tests.cpp
Normal file
101
tests/src/block_template_tests.cpp
Normal file
|
@ -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…
Reference in a new issue