P2PServer: don't deserialize the same block twice

This commit is contained in:
SChernykh
2022-07-10 10:24:03 +02:00
parent ae161fac49
commit c5bd184bbc
7 changed files with 111 additions and 112 deletions
+67 -47
View File
@@ -52,11 +52,15 @@ P2PServer::P2PServer(p2pool* pool)
, m_cachedBlocks(nullptr)
, m_rng(RandomDeviceSeed::instance)
, m_block(new PoolBlock())
, m_blockDeserializeResult(0)
, m_timer{}
, m_timerCounter(0)
, m_timerInterval(2)
, m_peerListLastSaved(0)
, m_lookForMissingBlocks(true)
{
m_blockDeserializeBuf.reserve(131072);
// Diffuse the initial state in case it has low quality
m_rng.discard(10000);
@@ -211,16 +215,15 @@ void P2PServer::update_peer_connections()
unordered_set<raw_ip> connected_clients;
{
MutexLock lock(m_clientsListLock);
connected_clients.reserve(m_numConnections);
for (P2PClient* client = static_cast<P2PClient*>(m_connectedClientsList->m_next); client != m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
bool disconnected = false;
const int timeout = client->m_handshakeComplete ? 300 : 10;
if (cur_time >= client->m_lastAlive + timeout) {
const uint64_t idle_time = static_cast<uint64_t>(cur_time - client->m_lastAlive);
LOGWARN(5, "peer " << static_cast<char*>(client->m_addrString) << " has been idle for " << idle_time << " seconds, disconnecting");
client->close();
disconnected = true;
continue;
}
if (client->m_handshakeComplete && client->m_lastBroadcastTimestamp) {
@@ -234,15 +237,13 @@ void P2PServer::update_peer_connections()
client->ban(DEFAULT_BAN_TIME);
remove_peer_from_list(client);
client->close();
disconnected = true;
continue;
}
}
if (!disconnected) {
connected_clients.insert(client->m_addr);
if (client->m_handshakeComplete && !client->m_handshakeInvalid && (client->m_listenPort >= 0)) {
has_good_peers = true;
}
connected_clients.insert(client->m_addr);
if (client->is_good()) {
has_good_peers = true;
}
}
}
@@ -305,35 +306,30 @@ void P2PServer::update_peer_connections()
void P2PServer::update_peer_list()
{
const uint64_t cur_time = seconds_since_epoch();
{
MutexLock lock(m_clientsListLock);
for (P2PClient* client = static_cast<P2PClient*>(m_connectedClientsList->m_next); client != m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
if (!client->m_handshakeComplete || !client->m_handshakeSolutionSent) {
continue;
}
MutexLock lock(m_clientsListLock);
if (cur_time >= client->m_nextOutgoingPeerListRequest) {
// Send peer list requests at random intervals (60-120 seconds)
client->m_nextOutgoingPeerListRequest = cur_time + (60 + (get_random64() % 61));
for (P2PClient* client = static_cast<P2PClient*>(m_connectedClientsList->m_next); client != m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
if (client->is_good() && (cur_time >= client->m_nextOutgoingPeerListRequest)) {
// Send peer list requests at random intervals (60-120 seconds)
client->m_nextOutgoingPeerListRequest = cur_time + (60 + (get_random64() % 61));
const bool result = send(client,
[](void* buf, size_t buf_size)
{
LOGINFO(5, "sending PEER_LIST_REQUEST");
const bool result = send(client,
[](void* buf, size_t buf_size)
{
LOGINFO(5, "sending PEER_LIST_REQUEST");
if (buf_size < SEND_BUF_MIN_SIZE) {
return 0;
}
if (buf_size < SEND_BUF_MIN_SIZE) {
return 0;
}
*reinterpret_cast<uint8_t*>(buf) = static_cast<uint8_t>(MessageId::PEER_LIST_REQUEST);
return 1;
});
*reinterpret_cast<uint8_t*>(buf) = static_cast<uint8_t>(MessageId::PEER_LIST_REQUEST);
return 1;
});
if (result) {
client->m_lastPeerListRequestTime = std::chrono::high_resolution_clock::now();
++client->m_peerListPendingRequests;
}
if (result) {
client->m_lastPeerListRequestTime = std::chrono::high_resolution_clock::now();
++client->m_peerListPendingRequests;
}
}
}
@@ -895,6 +891,24 @@ void P2PServer::show_peers()
LOGINFO(0, "Total: " << n << " peers");
}
int P2PServer::deserialize_block(const uint8_t* buf, uint32_t size)
{
int result;
if ((m_blockDeserializeBuf.size() == size) && (memcmp(m_blockDeserializeBuf.data(), buf, size) == 0)) {
m_block->reset_offchain_data();
result = m_blockDeserializeResult;
}
else {
result = m_block->deserialize(buf, size, m_pool->side_chain());
m_blockDeserializeBuf.assign(buf, buf + size);
m_blockDeserializeResult = result;
m_lookForMissingBlocks = true;
}
return result;
}
void P2PServer::on_timer()
{
++m_timerCounter;
@@ -948,10 +962,16 @@ void P2PServer::flush_cache()
void P2PServer::download_missing_blocks()
{
if (!m_lookForMissingBlocks) {
return;
}
std::vector<hash> missing_blocks;
m_pool->side_chain().get_missing_blocks(missing_blocks);
if (missing_blocks.empty()) {
m_lookForMissingBlocks = false;
MutexLock lock(m_missingBlockRequestsLock);
m_missingBlockRequests.clear();
return;
@@ -967,11 +987,9 @@ void P2PServer::download_missing_blocks()
clients.reserve(m_numConnections);
for (P2PClient* client = static_cast<P2PClient*>(m_connectedClientsList->m_next); client != m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
if (!client->m_handshakeComplete || !client->m_handshakeSolutionSent) {
continue;
if (client->is_good()) {
clients.emplace_back(client);
}
clients.emplace_back(client);
}
if (clients.empty()) {
@@ -1032,7 +1050,7 @@ void P2PServer::download_missing_blocks()
void P2PServer::check_zmq()
{
if ((m_timerCounter % 30) != 0) {
if ((m_timerCounter % 30) != 3) {
return;
}
@@ -1764,7 +1782,7 @@ bool P2PServer::P2PClient::on_block_response(const uint8_t* buf, uint32_t size)
MutexLock lock(server->m_blockLock);
const int result = server->m_block->deserialize(buf, size, server->m_pool->side_chain());
const int result = server->deserialize_block(buf, size);
if (result != 0) {
LOGWARN(3, "peer " << static_cast<char*>(m_addrString) << " sent an invalid block, error " << result);
return false;
@@ -1773,7 +1791,7 @@ bool P2PServer::P2PClient::on_block_response(const uint8_t* buf, uint32_t size)
if (m_chainTipBlockRequest) {
m_chainTipBlockRequest = false;
const uint64_t peer_height = server->m_block->m_txinGenHeight;
const uint64_t peer_height = server->get_block()->m_txinGenHeight;
const uint64_t our_height = server->m_pool->miner_data().height;
if (peer_height + 2 < our_height) {
@@ -1782,7 +1800,7 @@ bool P2PServer::P2PClient::on_block_response(const uint8_t* buf, uint32_t size)
}
}
return handle_incoming_block_async(server->m_block);
return handle_incoming_block_async(server->get_block());
}
bool P2PServer::P2PClient::on_block_broadcast(const uint8_t* buf, uint32_t size)
@@ -1796,19 +1814,21 @@ bool P2PServer::P2PClient::on_block_broadcast(const uint8_t* buf, uint32_t size)
MutexLock lock(server->m_blockLock);
const int result = server->m_block->deserialize(buf, size, server->m_pool->side_chain());
const int result = server->deserialize_block(buf, size);
if (result != 0) {
LOGWARN(3, "peer " << static_cast<char*>(m_addrString) << " sent an invalid block, error " << result);
return false;
}
m_broadcastedHashes[m_broadcastedHashesIndex.fetch_add(1) % array_size(&P2PClient::m_broadcastedHashes)] = server->m_block->m_sidechainId;
const PoolBlock* block = server->get_block();
m_broadcastedHashes[m_broadcastedHashesIndex.fetch_add(1) % array_size(&P2PClient::m_broadcastedHashes)] = block->m_sidechainId;
MinerData miner_data = server->m_pool->miner_data();
if (server->m_block->m_prevId != miner_data.prev_id) {
if (block->m_prevId != miner_data.prev_id) {
// This peer is mining on top of a different Monero block, investigate it
const uint64_t peer_height = server->m_block->m_txinGenHeight;
const uint64_t peer_height = block->m_txinGenHeight;
const uint64_t our_height = miner_data.height;
if (peer_height < our_height) {
@@ -1838,11 +1858,11 @@ bool P2PServer::P2PClient::on_block_broadcast(const uint8_t* buf, uint32_t size)
}
}
server->m_block->m_wantBroadcast = true;
block->m_wantBroadcast = true;
m_lastBroadcastTimestamp = seconds_since_epoch();
return handle_incoming_block_async(server->m_block);
return handle_incoming_block_async(block);
}
bool P2PServer::P2PClient::on_peer_list_request(const uint8_t*)
@@ -1967,7 +1987,7 @@ bool P2PServer::P2PClient::on_peer_list_response(const uint8_t* buf) const
return true;
}
bool P2PServer::P2PClient::handle_incoming_block_async(PoolBlock* block)
bool P2PServer::P2PClient::handle_incoming_block_async(const PoolBlock* block)
{
P2PServer* server = static_cast<P2PServer*>(m_owner);