P2PServer: ban peers that don't broadcast blocks

This commit is contained in:
SChernykh 2021-09-13 14:26:52 +02:00
parent 0d439e7712
commit da0f376bef
4 changed files with 33 additions and 0 deletions

View file

@ -167,6 +167,7 @@ void P2PServer::update_peer_connections()
} }
const time_t cur_time = time(nullptr); const time_t cur_time = time(nullptr);
const time_t last_updated = m_pool->side_chain().last_updated();
std::vector<raw_ip> connected_clients; std::vector<raw_ip> connected_clients;
{ {
@ -181,6 +182,20 @@ void P2PServer::update_peer_connections()
LOGWARN(5, "peer " << static_cast<char*>(client->m_addrString) << " has been idle for " << idle_time << " seconds, disconnecting"); LOGWARN(5, "peer " << static_cast<char*>(client->m_addrString) << " has been idle for " << idle_time << " seconds, disconnecting");
client->close(); client->close();
} }
if (client->m_handshakeComplete && client->m_lastBroadcastTimestamp) {
// - Side chain is at least 5 minutes newer (last_updated >= client->m_lastBroadcastTimestamp + 300)
// - It's been at least 10 seconds since side chain updated (cur_time >= last_updated + 10)
// - It's been at least 10 seconds since the last block request (peer is not syncing)
// - Peer should have sent a broadcast by now
if (last_updated && (cur_time >= std::max(last_updated, client->m_lastBlockrequestTimestamp) + 10) && (last_updated >= client->m_lastBroadcastTimestamp + 300)) {
const time_t dt = last_updated - client->m_lastBroadcastTimestamp;
LOGWARN(5, "peer " << static_cast<char*>(client->m_addrString) << " is not broadcasting blocks (last update " << dt << " seconds ago)");
client->ban(DEFAULT_BAN_TIME);
remove_peer_from_list(client);
client->close();
}
}
} }
} }
@ -754,6 +769,8 @@ P2PServer::P2PClient::P2PClient()
, m_listenPort(-1) , m_listenPort(-1)
, m_nextPeerListRequest(0) , m_nextPeerListRequest(0)
, m_lastAlive(0) , m_lastAlive(0)
, m_lastBroadcastTimestamp(0)
, m_lastBlockrequestTimestamp(0)
{ {
uv_rwlock_init_checked(&m_broadcastedHashesLock); uv_rwlock_init_checked(&m_broadcastedHashesLock);
} }
@ -776,6 +793,8 @@ void P2PServer::P2PClient::reset()
m_listenPort = -1; m_listenPort = -1;
m_nextPeerListRequest = 0; m_nextPeerListRequest = 0;
m_lastAlive = 0; m_lastAlive = 0;
m_lastBroadcastTimestamp = 0;
m_lastBlockrequestTimestamp = 0;
WriteLock lock(m_broadcastedHashesLock); WriteLock lock(m_broadcastedHashesLock);
m_broadcastedHashes.clear(); m_broadcastedHashes.clear();
@ -1291,6 +1310,8 @@ void P2PServer::P2PClient::on_after_handshake(uint8_t* &p)
hash empty; hash empty;
memcpy(p, empty.h, HASH_SIZE); memcpy(p, empty.h, HASH_SIZE);
p += HASH_SIZE; p += HASH_SIZE;
m_lastBroadcastTimestamp = time(nullptr);
} }
bool P2PServer::P2PClient::on_listen_port(const uint8_t* buf) bool P2PServer::P2PClient::on_listen_port(const uint8_t* buf)
@ -1311,6 +1332,8 @@ bool P2PServer::P2PClient::on_listen_port(const uint8_t* buf)
bool P2PServer::P2PClient::on_block_request(const uint8_t* buf) bool P2PServer::P2PClient::on_block_request(const uint8_t* buf)
{ {
m_lastBlockrequestTimestamp = time(nullptr);
hash id; hash id;
memcpy(id.h, buf, HASH_SIZE); memcpy(id.h, buf, HASH_SIZE);
@ -1418,6 +1441,8 @@ bool P2PServer::P2PClient::on_block_broadcast(const uint8_t* buf, uint32_t size)
server->m_block->m_wantBroadcast = true; server->m_block->m_wantBroadcast = true;
m_lastBroadcastTimestamp = time(nullptr);
return handle_incoming_block_async(server->m_block); return handle_incoming_block_async(server->m_block);
} }

View file

@ -109,6 +109,8 @@ public:
int m_listenPort; int m_listenPort;
time_t m_nextPeerListRequest; time_t m_nextPeerListRequest;
time_t m_lastAlive; time_t m_lastAlive;
time_t m_lastBroadcastTimestamp;
time_t m_lastBlockrequestTimestamp;
uv_rwlock_t m_broadcastedHashesLock; uv_rwlock_t m_broadcastedHashesLock;
std::set<hash> m_broadcastedHashes; std::set<hash> m_broadcastedHashes;

View file

@ -737,6 +737,11 @@ uint64_t SideChain::miner_count()
return m_seenWallets.size(); return m_seenWallets.size();
} }
time_t SideChain::last_updated() const
{
return m_chainTip ? m_chainTip->m_localTimestamp : 0;
}
bool SideChain::is_default() const bool SideChain::is_default() const
{ {
constexpr uint8_t default_consensus_id[HASH_SIZE] = { constexpr uint8_t default_consensus_id[HASH_SIZE] = {

View file

@ -69,6 +69,7 @@ public:
difficulty_type total_hashes() const; difficulty_type total_hashes() const;
uint64_t block_time() const { return m_targetBlockTime; } uint64_t block_time() const { return m_targetBlockTime; }
uint64_t miner_count(); uint64_t miner_count();
time_t last_updated() const;
bool is_default() const; bool is_default() const;
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);