diff --git a/src/p2p_server.cpp b/src/p2p_server.cpp index 0b3dbe8..356e89f 100644 --- a/src/p2p_server.cpp +++ b/src/p2p_server.cpp @@ -806,26 +806,9 @@ void P2PServer::Peer::normalize() } } -void P2PServer::broadcast(const PoolBlock& block, const PoolBlock* parent) +P2PServer::Broadcast::Broadcast(const PoolBlock& block, const PoolBlock* parent) { - // Don't broadcast blocks when shutting down - if (m_finished.load()) { - return; - } - - MinerData miner_data = m_pool->miner_data(); - - if (block.m_txinGenHeight + 2 < miner_data.height) { - LOGWARN(3, "Trying to broadcast a stale block " << block.m_sidechainId << " (mainchain height " << block.m_txinGenHeight << ", current height is " << miner_data.height << ')'); - return; - } - - if (block.m_txinGenHeight > miner_data.height + 2) { - LOGWARN(3, "Trying to broadcast a block " << block.m_sidechainId << " ahead on mainchain (mainchain height " << block.m_txinGenHeight << ", current height is " << miner_data.height << ')'); - return; - } - - Broadcast* data = new Broadcast{}; + Broadcast* data = this; data->id = block.m_sidechainId; data->received_timestamp = block.m_receivedTimestamp; @@ -895,6 +878,28 @@ void P2PServer::broadcast(const PoolBlock& block, const PoolBlock* parent) data->ancestor_hashes.reserve(block.m_uncles.size() + 1); data->ancestor_hashes = block.m_uncles; data->ancestor_hashes.push_back(block.m_parent); +} + +void P2PServer::broadcast(const PoolBlock& block, const PoolBlock* parent) +{ + // Don't broadcast blocks when shutting down + if (m_finished.load()) { + return; + } + + MinerData miner_data = m_pool->miner_data(); + + if (block.m_txinGenHeight + 2 < miner_data.height) { + LOGWARN(3, "Trying to broadcast a stale block " << block.m_sidechainId << " (mainchain height " << block.m_txinGenHeight << ", current height is " << miner_data.height << ')'); + return; + } + + if (block.m_txinGenHeight > miner_data.height + 2) { + LOGWARN(3, "Trying to broadcast a block " << block.m_sidechainId << " ahead on mainchain (mainchain height " << block.m_txinGenHeight << ", current height is " << miner_data.height << ')'); + return; + } + + Broadcast* data = new Broadcast(block, parent); LOGINFO(5, "Broadcasting block " << block.m_sidechainId << " (height " << block.m_sidechainHeight << "): " << data->compact_blob.size() << '/' << data->pruned_blob.size() << '/' << data->blob.size() << " bytes (compact/pruned/full)"); diff --git a/src/p2p_server.h b/src/p2p_server.h index d9fddbd..191d8e8 100644 --- a/src/p2p_server.h +++ b/src/p2p_server.h @@ -168,6 +168,19 @@ public: }; }; + struct Broadcast + { + Broadcast(const PoolBlock& block, const PoolBlock* parent); + + hash id; + uint64_t received_timestamp; + + std::vector blob; + std::vector pruned_blob; + std::vector compact_blob; + std::vector ancestor_hashes; + }; + void broadcast(const PoolBlock& block, const PoolBlock* parent); [[nodiscard]] uint64_t get_random64(); [[nodiscard]] uint64_t get_peerId() const { return m_peerId; } @@ -262,17 +275,6 @@ private: std::vector m_peerListMonero; std::atomic m_peerListLastSaved; - struct Broadcast - { - hash id; - uint64_t received_timestamp; - - std::vector blob; - std::vector pruned_blob; - std::vector compact_blob; - std::vector ancestor_hashes; - }; - uv_mutex_t m_broadcastLock; uv_async_t m_broadcastAsync; std::vector m_broadcastQueue; diff --git a/tests/src/pool_block_tests.cpp b/tests/src/pool_block_tests.cpp index 5323e1e..d5a7728 100644 --- a/tests/src/pool_block_tests.cpp +++ b/tests/src/pool_block_tests.cpp @@ -20,6 +20,7 @@ #include "pool_block.h" #include "pow_hash.h" #include "side_chain.h" +#include "p2p_server.h" #include "gtest/gtest.h" #include @@ -221,6 +222,39 @@ TEST(pool_block, verify) ASSERT_EQ(block.m_sidechainHeight, t.m_sidechainHeight + 1); ASSERT_EQ(shares.size(), t.m_expectedSharesNextBlock); + + const PoolBlock* parent = sidechain.find_block(tip->m_parent); + ASSERT_TRUE(parent != nullptr); + + // Check pruned and compact broadcast blobs + + auto tip_full_blob = tip->serialize_mainchain_data(); + auto v2 = tip->serialize_sidechain_data(); + tip_full_blob.insert(tip_full_blob.end(), v2.begin(), v2.end()); + + P2PServer::Broadcast broadcast(*tip, parent); + + { + PoolBlock block2; + ASSERT_EQ(block2.deserialize(broadcast.pruned_blob.data(), broadcast.pruned_blob.size(), sidechain, nullptr, false), 0); + + auto v1 = block2.serialize_mainchain_data(); + v2 = block2.serialize_sidechain_data(); + v1.insert(v1.end(), v2.begin(), v2.end()); + + ASSERT_EQ(v1, tip_full_blob); + } + + if (!broadcast.compact_blob.empty()) { + PoolBlock block3; + ASSERT_EQ(block3.deserialize(broadcast.compact_blob.data(), broadcast.compact_blob.size(), sidechain, nullptr, true), 0); + + auto v1 = block3.serialize_mainchain_data(); + v2 = block3.serialize_sidechain_data(); + v1.insert(v1.end(), v2.begin(), v2.end()); + + ASSERT_EQ(v1, tip_full_blob); + } } destroy_crypto_cache();