mirror of
https://github.com/SChernykh/p2pool.git
synced 2025-02-02 03:06:27 +00:00
Use monerod peers to find p2pool nodes
This commit is contained in:
parent
cc6ce4a366
commit
d4a1b14820
3 changed files with 138 additions and 5 deletions
|
@ -55,13 +55,25 @@ JSONRPCRequest::JSONRPCRequest(const char* address, int port, const char* req, C
|
|||
m_connect.data = this;
|
||||
m_write.data = this;
|
||||
|
||||
const size_t len = strlen(req);
|
||||
const char* uri = "/json_rpc";
|
||||
|
||||
size_t len = req ? strlen(req) : 0;
|
||||
if (!len) {
|
||||
LOGERR(1, "Empty JSONRPCRequest, fix the code!");
|
||||
m_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (req[0] == '/') {
|
||||
uri = req;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
m_request.reserve(std::max<size_t>(len + 128, log::Stream::BUF_SIZE + 1));
|
||||
m_request.resize(log::Stream::BUF_SIZE + 1);
|
||||
|
||||
log::Stream s(m_request.data());
|
||||
s << "POST /json_rpc HTTP/1.1\nContent-Type: application/json\nContent-Length: " << len << "\n\n";
|
||||
s << "POST " << uri << " HTTP/1.1\nContent-Type: application/json\nContent-Length: " << len << "\n\n";
|
||||
|
||||
m_request.resize(s.m_pos);
|
||||
m_request.insert(m_request.end(), req, req + len);
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#include "side_chain.h"
|
||||
#include "pool_block.h"
|
||||
#include "block_cache.h"
|
||||
#include "json_rpc_request.h"
|
||||
#include "json_parsers.h"
|
||||
#include <rapidjson/document.h>
|
||||
#include <fstream>
|
||||
#include <numeric>
|
||||
|
||||
|
@ -173,6 +176,8 @@ void P2PServer::update_peer_connections()
|
|||
const time_t cur_time = time(nullptr);
|
||||
const time_t last_updated = m_pool->side_chain().last_updated();
|
||||
|
||||
bool has_good_peers = false;
|
||||
|
||||
std::vector<raw_ip> connected_clients;
|
||||
{
|
||||
MutexLock lock(m_clientsListLock);
|
||||
|
@ -205,6 +210,9 @@ void P2PServer::update_peer_connections()
|
|||
|
||||
if (!disconnected) {
|
||||
connected_clients.emplace_back(client->m_addr);
|
||||
if (client->m_handshakeComplete && !client->m_handshakeInvalid && (client->m_listenPort >= 0)) {
|
||||
has_good_peers = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -228,8 +236,20 @@ void P2PServer::update_peer_connections()
|
|||
peer_list = m_peerList;
|
||||
}
|
||||
|
||||
uint32_t N = m_maxOutgoingPeers;
|
||||
|
||||
// Special case: when we can't find p2pool peers, scan through monerod peers (try 25 peers at a time)
|
||||
if (!has_good_peers && !m_peerListMonero.empty()) {
|
||||
LOGINFO(3, "Scanning monerod peers, " << m_peerListMonero.size() << " left");
|
||||
for (uint32_t i = 0; (i < 25) && !m_peerListMonero.empty(); ++i) {
|
||||
peer_list.push_back(m_peerListMonero.back());
|
||||
m_peerListMonero.pop_back();
|
||||
}
|
||||
N = static_cast<uint32_t>(peer_list.size());
|
||||
}
|
||||
|
||||
// Try to have at least N outgoing connections (N defaults to 10, can be set via --out-peers command line parameter)
|
||||
for (uint32_t i = m_numConnections - m_numIncomingConnections; (i < m_maxOutgoingPeers) && !peer_list.empty();) {
|
||||
for (uint32_t i = m_numConnections - m_numIncomingConnections; (i < N) && !peer_list.empty();) {
|
||||
const uint64_t k = get_random64() % peer_list.size();
|
||||
const Peer& peer = peer_list[k];
|
||||
|
||||
|
@ -251,8 +271,11 @@ void P2PServer::update_peer_connections()
|
|||
peer_list.pop_back();
|
||||
}
|
||||
|
||||
if ((m_numConnections == 0) && ((m_timerCounter % 30) == 0)) {
|
||||
if (!has_good_peers && ((m_timerCounter % 30) == 0)) {
|
||||
LOGERR(1, "no connections to other p2pool nodes, check your monerod/p2pool/network/firewall setup!!!");
|
||||
if (m_peerListMonero.empty()) {
|
||||
load_monerod_peer_list();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -369,6 +392,7 @@ void P2PServer::save_peer_list()
|
|||
void P2PServer::load_peer_list()
|
||||
{
|
||||
std::string saved_list;
|
||||
const size_t old_size = m_peerList.size();
|
||||
|
||||
// Load peers from seed nodes if we're on the default or mini sidechain
|
||||
auto load_from_seed_nodes = [&saved_list](const char** nodes, int p2p_port) {
|
||||
|
@ -493,7 +517,102 @@ void P2PServer::load_peer_list()
|
|||
}
|
||||
});
|
||||
|
||||
LOGINFO(4, "peer list loaded (" << m_peerList.size() << " peers)");
|
||||
LOGINFO(4, "peer list loaded (" << (m_peerList.size() - old_size) << " peers)");
|
||||
}
|
||||
|
||||
void P2PServer::load_monerod_peer_list()
|
||||
{
|
||||
const Params& params = m_pool->params();
|
||||
|
||||
JSONRPCRequest::call(params.m_host.c_str(), params.m_rpcPort, "/get_peer_list",
|
||||
[this](const char* data, size_t size)
|
||||
{
|
||||
constexpr char err_str[] = "/get_peer_list RPC request returned invalid JSON ";
|
||||
|
||||
using namespace rapidjson;
|
||||
|
||||
Document doc;
|
||||
if (doc.Parse(data, size).HasParseError()) {
|
||||
LOGWARN(4, err_str << "(parse error)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!doc.IsObject()) {
|
||||
LOGWARN(4, err_str << "(not an object)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!doc.HasMember("white_list")) {
|
||||
LOGWARN(4, err_str << "('white_list' not found)");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& white_list = doc["white_list"];
|
||||
|
||||
if (!white_list.IsArray()) {
|
||||
LOGWARN(4, err_str << "('white_list' is not an array)");
|
||||
return;
|
||||
}
|
||||
|
||||
const int port = m_pool->side_chain().is_mini() ? DEFAULT_P2P_PORT_MINI : DEFAULT_P2P_PORT;
|
||||
|
||||
const SizeType n = white_list.Size();
|
||||
|
||||
m_peerListMonero.clear();
|
||||
m_peerListMonero.reserve(n);
|
||||
|
||||
for (SizeType i = 0; i < n; ++i) {
|
||||
auto& v = white_list[i];
|
||||
const char* ip;
|
||||
uint64_t last_seen;
|
||||
if (!parseValue(v, "host", ip) || !parseValue(v, "last_seen", last_seen)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Peer p;
|
||||
p.m_lastSeen = last_seen;
|
||||
|
||||
if (strchr(ip, ':')) {
|
||||
sockaddr_in6 addr6;
|
||||
const int err = uv_ip6_addr(ip, port, &addr6);
|
||||
if (err) {
|
||||
continue;
|
||||
}
|
||||
p.m_isV6 = true;
|
||||
memcpy(p.m_addr.data, &addr6.sin6_addr, sizeof(in6_addr));
|
||||
}
|
||||
else {
|
||||
sockaddr_in addr4;
|
||||
const int err = uv_ip4_addr(ip, port, &addr4);
|
||||
if (err) {
|
||||
continue;
|
||||
}
|
||||
p.m_isV6 = false;
|
||||
p.m_addr = {};
|
||||
p.m_addr.data[10] = 0xFF;
|
||||
p.m_addr.data[11] = 0xFF;
|
||||
memcpy(p.m_addr.data + 12, &addr4.sin_addr, sizeof(in_addr));
|
||||
}
|
||||
|
||||
p.m_port = port;
|
||||
p.m_numFailedConnections = 0;
|
||||
|
||||
if (!is_banned(p.m_addr)) {
|
||||
m_peerListMonero.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
// Put recently active peers first in the list
|
||||
std::sort(m_peerListMonero.begin(), m_peerListMonero.end(), [](const Peer& a, const Peer& b) { return a.m_lastSeen > b.m_lastSeen; });
|
||||
|
||||
LOGINFO(4, "monerod peer list loaded (" << m_peerListMonero.size() << " peers)");
|
||||
},
|
||||
[](const char* data, size_t size)
|
||||
{
|
||||
if (size > 0) {
|
||||
LOGWARN(4, "/get_peer_list RPC request failed: error " << log::const_buf(data, size));
|
||||
}
|
||||
}, &m_loop);
|
||||
}
|
||||
|
||||
void P2PServer::update_peer_in_list(bool is_v6, const raw_ip& ip, int port)
|
||||
|
|
|
@ -160,6 +160,7 @@ private:
|
|||
void save_peer_list_async();
|
||||
void save_peer_list();
|
||||
void load_peer_list();
|
||||
void load_monerod_peer_list();
|
||||
void update_peer_in_list(bool is_v6, const raw_ip& ip, int port);
|
||||
void remove_peer_from_list(P2PClient* client);
|
||||
void remove_peer_from_list(const raw_ip& ip);
|
||||
|
@ -188,6 +189,7 @@ private:
|
|||
};
|
||||
|
||||
std::vector<Peer> m_peerList;
|
||||
std::vector<Peer> m_peerListMonero;
|
||||
time_t m_peerListLastSaved;
|
||||
|
||||
struct Broadcast
|
||||
|
|
Loading…
Reference in a new issue