diff --git a/src/p2p_server.cpp b/src/p2p_server.cpp index ad62308..8220cf4 100644 --- a/src/p2p_server.cpp +++ b/src/p2p_server.cpp @@ -726,7 +726,7 @@ void P2PServer::remove_peer_from_list(const raw_ip& ip) } } -void P2PServer::broadcast(const PoolBlock& block) +void P2PServer::broadcast(const PoolBlock& block, const PoolBlock* parent) { MinerData miner_data = m_pool->miner_data(); @@ -766,13 +766,48 @@ void P2PServer::broadcast(const PoolBlock& block) writeVarint(outputs_blob_size, data->pruned_blob); data->pruned_blob.insert(data->pruned_blob.end(), mainchain_data.begin() + outputs_offset + outputs_blob_size, mainchain_data.end()); + + const size_t N = block.m_transactions.size(); + if ((N > 1) && parent) { + unordered_map parent_transactions; + parent_transactions.reserve(parent->m_transactions.size()); + + for (size_t i = 1; i < parent->m_transactions.size(); ++i) { + parent_transactions.emplace(parent->m_transactions[i], i); + } + + // Reserve 1 additional byte per transaction to be ready for the worst case (all transactions are different in the parent block) + data->compact_blob.reserve(data->pruned_blob.capacity() + (N - 1)); + + // Copy pruned_blob without the transaction list + data->compact_blob.assign(data->pruned_blob.begin(), data->pruned_blob.end() - (N - 1) * HASH_SIZE); + + // Process transaction hashes one by one + size_t num_found = 0; + for (size_t i = 1; i < N; ++i) { + const hash& tx = block.m_transactions[i]; + auto it = parent_transactions.find(tx); + if (it != parent_transactions.end()) { + writeVarint(it->second, data->compact_blob); + ++num_found; + } + else { + data->compact_blob.push_back(0); + data->compact_blob.insert(data->compact_blob.end(), tx.h, tx.h + HASH_SIZE); + } + } + LOGINFO(6, "compact blob: " << num_found << '/' << (N - 1) << " transactions were found in the parent block"); + + data->compact_blob.insert(data->compact_blob.end(), sidechain_data.begin(), sidechain_data.end()); + } + data->pruned_blob.insert(data->pruned_blob.end(), sidechain_data.begin(), sidechain_data.end()); data->ancestor_hashes.reserve(block.m_uncles.size() + 1); data->ancestor_hashes = block.m_uncles; data->ancestor_hashes.push_back(block.m_parent); - LOGINFO(5, "Broadcasting block " << block.m_sidechainId << " (height " << block.m_sidechainHeight << "): " << data->pruned_blob.size() << '/' << data->blob.size() << " bytes (pruned/full)"); + 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)"); { MutexLock lock(m_broadcastLock); diff --git a/src/p2p_server.h b/src/p2p_server.h index da278c0..930a951 100644 --- a/src/p2p_server.h +++ b/src/p2p_server.h @@ -130,7 +130,7 @@ public: std::atomic m_broadcastedHashesIndex{ 0 }; }; - void broadcast(const PoolBlock& block); + void broadcast(const PoolBlock& block, const PoolBlock* parent); uint64_t get_random64(); uint64_t get_peerId() const { return m_peerId; } @@ -212,6 +212,7 @@ private: { std::vector blob; std::vector pruned_blob; + std::vector compact_blob; std::vector ancestor_hashes; }; diff --git a/src/side_chain.cpp b/src/side_chain.cpp index 038b39b..c8898a0 100644 --- a/src/side_chain.cpp +++ b/src/side_chain.cpp @@ -1275,7 +1275,7 @@ void SideChain::verify_loop(PoolBlock* block) if (block->m_wantBroadcast && !block->m_broadcasted) { block->m_broadcasted = true; if (server && (block->m_depth < UNCLE_BLOCK_DEPTH)) { - server->broadcast(*block); + server->broadcast(*block, get_parent(block)); } } @@ -1674,7 +1674,7 @@ void SideChain::update_chain_tip(const PoolBlock* block) if (p2pServer() && block->m_wantBroadcast && !block->m_broadcasted) { block->m_broadcasted = true; - p2pServer()->broadcast(*block); + p2pServer()->broadcast(*block, get_parent(block)); } }