mirror of
https://github.com/SChernykh/p2pool.git
synced 2025-03-24 16:18:50 +00:00
SideChain: fix for out of order blocks
This commit is contained in:
parent
6ffe1d81c2
commit
32dc235aa5
4 changed files with 63 additions and 7 deletions
|
@ -1762,7 +1762,7 @@ void SideChain::update_chain_tip(const PoolBlock* block)
|
||||||
" is not a longer chain than " << tip->m_sidechainId <<
|
" is not a longer chain than " << tip->m_sidechainId <<
|
||||||
", height " << tip->m_sidechainHeight);
|
", height " << tip->m_sidechainHeight);
|
||||||
}
|
}
|
||||||
else if (block->m_sidechainHeight + UNCLE_BLOCK_DEPTH > tip->m_sidechainHeight) {
|
else if (m_pool && (block->m_sidechainHeight + UNCLE_BLOCK_DEPTH > tip->m_sidechainHeight)) {
|
||||||
LOGINFO(4, "possible uncle block: id = " << log::Gray() << block->m_sidechainId << log::NoColor() <<
|
LOGINFO(4, "possible uncle block: id = " << log::Gray() << block->m_sidechainId << log::NoColor() <<
|
||||||
", height = " << log::Gray() << block->m_sidechainHeight);
|
", height = " << log::Gray() << block->m_sidechainHeight);
|
||||||
m_pool->update_block_template_async();
|
m_pool->update_block_template_async();
|
||||||
|
@ -1970,6 +1970,36 @@ void SideChain::update_depths(PoolBlock* block)
|
||||||
verify_loop(block);
|
verify_loop(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 1; i <= UNCLE_BLOCK_DEPTH; ++i) {
|
||||||
|
auto it = m_blocksByHeight.find(block->m_sidechainHeight + i);
|
||||||
|
if (it == m_blocksByHeight.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (PoolBlock* child : it->second) {
|
||||||
|
const uint64_t old_depth = child->m_depth;
|
||||||
|
|
||||||
|
if (child->m_parent == block->m_sidechainId) {
|
||||||
|
if (i != 1) {
|
||||||
|
LOGWARN(3, "Block " << block->m_sidechainId << ": m_sidechainHeight is inconsistent with child's m_sidechainHeight.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (block->m_depth > 0) {
|
||||||
|
update_depth(child, block->m_depth - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::find(child->m_uncles.begin(), child->m_uncles.end(), block->m_sidechainId) != child->m_uncles.end()) {
|
||||||
|
if (block->m_depth > i) {
|
||||||
|
update_depth(child, block->m_depth - i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child->m_depth > old_depth) {
|
||||||
|
blocks_to_update.push_back(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto it = m_blocksById.find(block->m_parent);
|
auto it = m_blocksById.find(block->m_parent);
|
||||||
if (it != m_blocksById.end()) {
|
if (it != m_blocksById.end()) {
|
||||||
if (it->second->m_sidechainHeight + 1 != block->m_sidechainHeight) {
|
if (it->second->m_sidechainHeight + 1 != block->m_sidechainHeight) {
|
||||||
|
|
|
@ -84,6 +84,7 @@ public:
|
||||||
|
|
||||||
#ifdef P2POOL_UNIT_TESTS
|
#ifdef P2POOL_UNIT_TESTS
|
||||||
difficulty_type m_testMainChainDiff;
|
difficulty_type m_testMainChainDiff;
|
||||||
|
const unordered_map<hash, PoolBlock*>& blocksById() const { return m_blocksById; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool split_reward(uint64_t reward, const std::vector<MinerShare>& shares, std::vector<uint64_t>& rewards);
|
static bool split_reward(uint64_t reward, const std::vector<MinerShare>& shares, std::vector<uint64_t>& rewards);
|
||||||
|
|
|
@ -18,9 +18,11 @@
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
void p2pool_usage() {}
|
void p2pool_usage() {}
|
||||||
|
namespace p2pool { void set_main_thread(); }
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
p2pool::set_main_thread();
|
||||||
testing::InitGoogleTest(&argc, argv);
|
testing::InitGoogleTest(&argc, argv);
|
||||||
return RUN_ALL_TESTS();
|
return RUN_ALL_TESTS();
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,14 +130,14 @@ TEST(pool_block, verify)
|
||||||
const char* m_fileName;
|
const char* m_fileName;
|
||||||
uint64_t m_txinGenHeight;
|
uint64_t m_txinGenHeight;
|
||||||
uint64_t m_sidechainHeight;
|
uint64_t m_sidechainHeight;
|
||||||
|
bool m_shuffle;
|
||||||
} tests[2] = {
|
} tests[2] = {
|
||||||
{ "default", "sidechain_dump.dat", 2870010, 4957203 },
|
{ "default", "sidechain_dump.dat", 2870010, 4957203, true },
|
||||||
{ "mini", "sidechain_dump_mini.dat", 2870010, 4414446 },
|
{ "mini", "sidechain_dump_mini.dat", 2870010, 4414446, false },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const STest& t : tests)
|
for (const STest& t : tests)
|
||||||
{
|
{
|
||||||
PoolBlock b;
|
|
||||||
SideChain sidechain(nullptr, NetworkType::Mainnet, t.m_poolName);
|
SideChain sidechain(nullptr, NetworkType::Mainnet, t.m_poolName);
|
||||||
|
|
||||||
// Difficulty of block 2869248
|
// Difficulty of block 2869248
|
||||||
|
@ -151,17 +151,40 @@ TEST(pool_block, verify)
|
||||||
f.read(reinterpret_cast<char*>(buf.data()), buf.size());
|
f.read(reinterpret_cast<char*>(buf.data()), buf.size());
|
||||||
ASSERT_EQ(f.good(), true);
|
ASSERT_EQ(f.good(), true);
|
||||||
|
|
||||||
|
std::vector<PoolBlock*> blocks;
|
||||||
for (const uint8_t *p = buf.data(), *e = buf.data() + buf.size(); p < e;) {
|
for (const uint8_t *p = buf.data(), *e = buf.data() + buf.size(); p < e;) {
|
||||||
ASSERT_TRUE(p + sizeof(uint32_t) <= e);
|
ASSERT_TRUE(p + sizeof(uint32_t) <= e);
|
||||||
const uint32_t n = *reinterpret_cast<const uint32_t*>(p);
|
const uint32_t n = *reinterpret_cast<const uint32_t*>(p);
|
||||||
p += sizeof(uint32_t);
|
p += sizeof(uint32_t);
|
||||||
|
|
||||||
ASSERT_TRUE(p + n <= e);
|
ASSERT_TRUE(p + n <= e);
|
||||||
ASSERT_EQ(b.deserialize(p, n, sidechain, nullptr, false), 0);
|
|
||||||
|
PoolBlock* b = new PoolBlock();
|
||||||
|
ASSERT_EQ(b->deserialize(p, n, sidechain, nullptr, false), 0);
|
||||||
p += n;
|
p += n;
|
||||||
|
|
||||||
ASSERT_TRUE(sidechain.add_block(b));
|
blocks.push_back(b);
|
||||||
ASSERT_TRUE(sidechain.find_block(b.m_sidechainId) != nullptr);
|
}
|
||||||
|
|
||||||
|
if (t.m_shuffle) {
|
||||||
|
std::mt19937_64 rng;
|
||||||
|
|
||||||
|
for (uint64_t i = 0, k, n = blocks.size(); i < n - 1; ++i) {
|
||||||
|
umul128(rng(), n - i, &k);
|
||||||
|
std::swap(blocks[i], blocks[i + k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint64_t i = 0, n = blocks.size(); i < n; ++i) {
|
||||||
|
ASSERT_TRUE(sidechain.add_block(*blocks[i]));
|
||||||
|
ASSERT_TRUE(sidechain.find_block(blocks[i]->m_sidechainId) != nullptr);
|
||||||
|
delete blocks[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = sidechain.blocksById().begin(); it != sidechain.blocksById().end(); ++it) {
|
||||||
|
const PoolBlock* b = it->second;
|
||||||
|
ASSERT_TRUE(b->m_verified);
|
||||||
|
ASSERT_FALSE(b->m_invalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
const PoolBlock* tip = sidechain.chainTip();
|
const PoolBlock* tip = sidechain.chainTip();
|
||||||
|
|
Loading…
Reference in a new issue