Compare commits

...
16 Commits
Author SHA1 Message Date
SChernykh 2071a24a9f Update version 2021-10-27 17:27:48 +02:00
SChernykh 1c0da4513f Added --no-color command line option
`--no-color` disables colors in console output
2021-10-27 16:48:17 +02:00
SChernykh 6a002cda46 Create msvc-analysis.yml 2021-10-27 16:06:36 +02:00
SChernykh c21c9615a3 Fixed optimization flags for gcc/clang 2021-10-26 20:13:51 +02:00
SChernykh c0c210664a Show uptime in status 2021-10-26 17:55:47 +02:00
SChernykh 6859d11445 Disable console quick-edit mode on Windows
Prevent user from accidentally selecting text in console and freezing all output
2021-10-26 17:42:00 +02:00
SChernykh 111324b6e0 Added console command to show connected peers 2021-10-24 16:04:30 +02:00
SChernykh 148b9dd294 Switch to faster unordered_map/set 2021-10-22 18:34:20 +02:00
SChernykh 04d18cdf1d P2PServer: fixed m_timer leak 2021-10-21 19:19:22 +02:00
SChernykh 352ad81a0a StratumServer: faster processing of regular shares 2021-10-21 19:09:36 +02:00
SChernykh d26902468d P2PServer: peer list tweaks
- Increase outgoing connections to 10
- Stricter handling of peer list responses
2021-10-21 15:55:00 +02:00
SChernykh 0382027d70 Fixed wrong error message 2021-10-21 10:12:57 +02:00
SChernykh 966b499e5c ZMQReader: keep trying to connect on startup 2021-10-21 00:22:53 +02:00
SChernykh 9885f82e9e Limit user name length to 64 characters
Also avoid creating temporary strings (`" user " + client->m_customUser`) when logging user name
2021-10-19 21:09:08 +02:00
SChernykhandGitHub 32a58d1534 Merge pull request #58 from WeebDataHoarder/master
Display stratum user on SHARE FOUND and "client found mainchain block" log entries
2021-10-19 20:10:53 +02:00
WeebDataHoarder bc341918f6 Decode custom user from stratum client, display stratum client+user on SHARE FOUND and client mainchain found message 2021-10-19 19:33:15 +02:00
32 changed files with 303 additions and 75 deletions
+61
View File
@@ -0,0 +1,61 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
#
# Find more information at:
# https://github.com/microsoft/msvc-code-analysis-action
name: Microsoft C++ Code Analysis
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
schedule:
- cron: '40 10 * * 0'
env:
# Path to the CMake build directory.
build: '${{ github.workspace }}/build'
jobs:
analyze:
name: Analyze
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
submodules: true
- name: Configure CMake
run: cmake -B ${{ env.build }}
# Build is not required unless generated source files are used
# - name: Build CMake
# run: cmake --build ${{ env.build }}
- name: Initialize MSVC Code Analysis
uses: microsoft/msvc-code-analysis-action@04825f6d9e00f87422d6bf04e1a38b1f3ed60d99
# Provide a unique ID to access the sarif output path
id: run-analysis
with:
cmakeBuildDirectory: ${{ env.build }}
# Ruleset file that will determine what checks will be run
ruleset: NativeRecommendedRules.ruleset
# Upload SARIF file to GitHub Code Scanning Alerts
- name: Upload SARIF to GitHub
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: ${{ steps.run-analysis.outputs.sarif }}
# Upload SARIF file as an Artifact to download and view
- name: Upload SARIF as an Artifact
uses: actions/upload-artifact@v2
with:
name: sarif-file
path: ${{ steps.run-analysis.outputs.sarif }}
+3
View File
@@ -19,3 +19,6 @@
[submodule "external/src/libzmq"] [submodule "external/src/libzmq"]
path = external/src/libzmq path = external/src/libzmq
url = https://github.com/SChernykh/libzmq url = https://github.com/SChernykh/libzmq
[submodule "external/src/robin-hood-hashing"]
path = external/src/robin-hood-hashing
url = https://github.com/SChernykh/robin-hood-hashing
+1
View File
@@ -82,6 +82,7 @@ include_directories(external/src/libzmq/include)
include_directories(external/src/llhttp) include_directories(external/src/llhttp)
include_directories(external/src/RandomX/src) include_directories(external/src/RandomX/src)
include_directories(external/src/rapidjson/include) include_directories(external/src/rapidjson/include)
include_directories(external/src/robin-hood-hashing/src/include)
if (WIN32) if (WIN32)
set(LIBS ${LIBS} ws2_32 iphlpapi userenv psapi) set(LIBS ${LIBS} ws2_32 iphlpapi userenv psapi)
+4 -4
View File
@@ -9,10 +9,10 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(WARNING_FLAGS "-Wall -Wextra -Werror") set(WARNING_FLAGS "-Wall -Wextra -Werror")
set(OPTIMIZATION_FLAGS "-Ofast -s") set(OPTIMIZATION_FLAGS "-Ofast -s")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
if (WIN32) if (WIN32)
@@ -42,9 +42,9 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
set(WARNING_FLAGS "-Wall -Wextra -Wno-undefined-internal -Werror") set(WARNING_FLAGS "-Wall -Wextra -Wno-undefined-internal -Werror")
set(OPTIMIZATION_FLAGS "-Ofast -funroll-loops -fmerge-all-constants") set(OPTIMIZATION_FLAGS "-Ofast -funroll-loops -fmerge-all-constants")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
endif() endif()
+1
View File
@@ -7,3 +7,4 @@
../external/src/llhttp/ ../external/src/llhttp/
../external/src/RandomX/src/ ../external/src/RandomX/src/
../external/src/rapidjson/include ../external/src/rapidjson/include
../external/src/robin-hood-hashing/src/include
+1 -1
View File
@@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
cppcheck ../src -DZMQ_STATIC --platform=unix64 --std=c++14 --enable=all --inconclusive --inline-suppr --template="{file}:{line}:{id}{inconclusive: INCONCLUSIVE} {message}" -I ../src/ -I ../external/src/ -I ../external/src/cryptonote/ -I ../external/src/libuv/ -I ../external/src/cppzmq/ -I ../external/src/libzmq/ -I ../external/src/llhttp/ -I ../external/src/RandomX/src/ -I ../external/src/rapidjson/include --suppressions-list=suppressions.txt --output-file=errors_full.txt cppcheck ../src -DZMQ_STATIC --platform=unix64 --std=c++14 --enable=all --inconclusive --inline-suppr --template="{file}:{line}:{id}{inconclusive: INCONCLUSIVE} {message}" -I ../src/ -I ../external/src/ -I ../external/src/cryptonote/ -I ../external/src/libuv/ -I ../external/src/cppzmq/ -I ../external/src/libzmq/ -I ../external/src/llhttp/ -I ../external/src/RandomX/src/ -I ../external/src/rapidjson/include -I ../external/src/robin-hood-hashing/src/include --suppressions-list=suppressions.txt --output-file=errors_full.txt
grep -v 'external' errors_full.txt | grep -v 'unmatchedSuppression' > errors_filtered.txt grep -v 'external' errors_full.txt | grep -v 'unmatchedSuppression' > errors_filtered.txt
if [ -s errors_filtered.txt ]; then if [ -s errors_filtered.txt ]; then
cat errors_filtered.txt cat errors_filtered.txt
+5
View File
@@ -279,6 +279,11 @@ enum class NetworkType {
Stagenet, Stagenet,
}; };
void* malloc_hook(size_t n) noexcept;
void* realloc_hook(void* ptr, size_t size) noexcept;
void* calloc_hook(size_t count, size_t size) noexcept;
void free_hook(void* p) noexcept;
} // namespace p2pool } // namespace p2pool
#include "util.h" #include "util.h"
+10 -1
View File
@@ -69,7 +69,7 @@ typedef struct cmd {
cmdfunc *func; cmdfunc *func;
} cmd; } cmd;
static cmdfunc do_help, do_status, do_loglevel, do_addpeers, do_droppeers, do_exit; static cmdfunc do_help, do_status, do_loglevel, do_addpeers, do_droppeers, do_showpeers, do_exit;
static cmd cmds[] = { static cmd cmds[] = {
{ STRCONST("help"), "", "display list of commands", do_help }, { STRCONST("help"), "", "display list of commands", do_help },
@@ -77,6 +77,7 @@ static cmd cmds[] = {
{ STRCONST("loglevel"), "<level>", "set log level", do_loglevel }, { STRCONST("loglevel"), "<level>", "set log level", do_loglevel },
{ STRCONST("addpeers"), "<peeraddr>", "add peer", do_addpeers }, { STRCONST("addpeers"), "<peeraddr>", "add peer", do_addpeers },
{ STRCONST("droppeers"), "", "disconnect all peers", do_droppeers }, { STRCONST("droppeers"), "", "disconnect all peers", do_droppeers },
{ STRCONST("peers"), "", "show all peers", do_showpeers },
{ STRCONST("exit"), "", "terminate p2pool", do_exit }, { STRCONST("exit"), "", "terminate p2pool", do_exit },
{ STRCNULL, NULL, NULL, NULL } { STRCNULL, NULL, NULL, NULL }
}; };
@@ -129,6 +130,14 @@ static int do_droppeers(p2pool *m_pool, const char * /* args */)
return 0; return 0;
} }
static int do_showpeers(p2pool* m_pool, const char* /* args */)
{
if (m_pool->p2p_server()) {
m_pool->p2p_server()->show_peers();
}
return 0;
}
static int do_exit(p2pool *m_pool, const char * /* args */) static int do_exit(p2pool *m_pool, const char * /* args */)
{ {
bkg_jobs_tracker.wait(); bkg_jobs_tracker.wait();
+2 -3
View File
@@ -20,7 +20,6 @@
#include "keccak.h" #include "keccak.h"
#include "uv_util.h" #include "uv_util.h"
#include <random> #include <random>
#include <unordered_map>
extern "C" { extern "C" {
#include "crypto-ops.h" #include "crypto-ops.h"
@@ -237,8 +236,8 @@ public:
private: private:
uv_mutex_t m; uv_mutex_t m;
std::unordered_map<std::array<uint8_t, HASH_SIZE * 2>, hash> derivations; unordered_map<std::array<uint8_t, HASH_SIZE * 2>, hash> derivations;
std::unordered_map<std::array<uint8_t, HASH_SIZE * 2 + sizeof(size_t)>, hash> public_keys; unordered_map<std::array<uint8_t, HASH_SIZE * 2 + sizeof(size_t)>, hash> public_keys;
}; };
static Cache* cache = nullptr; static Cache* cache = nullptr;
+12 -1
View File
@@ -28,6 +28,7 @@ namespace p2pool {
namespace log { namespace log {
int GLOBAL_LOG_LEVEL = 3; int GLOBAL_LOG_LEVEL = 3;
bool CONSOLE_COLORS = true;
#ifndef P2POOL_LOG_DISABLE #ifndef P2POOL_LOG_DISABLE
@@ -35,6 +36,7 @@ static volatile bool stopped = false;
static volatile bool worker_started = false; static volatile bool worker_started = false;
#ifdef _WIN32 #ifdef _WIN32
static const HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
static const HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); static const HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
static const HANDLE hStdErr = GetStdHandle(STD_ERROR_HANDLE); static const HANDLE hStdErr = GetStdHandle(STD_ERROR_HANDLE);
#endif #endif
@@ -69,6 +71,9 @@ public:
#ifdef _WIN32 #ifdef _WIN32
DWORD dwConsoleMode; DWORD dwConsoleMode;
if (GetConsoleMode(hStdIn, &dwConsoleMode)) {
SetConsoleMode(hStdIn, dwConsoleMode & ~ENABLE_QUICK_EDIT_MODE);
}
if (GetConsoleMode(hStdOut, &dwConsoleMode)) { if (GetConsoleMode(hStdOut, &dwConsoleMode)) {
SetConsoleMode(hStdOut, dwConsoleMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); SetConsoleMode(hStdOut, dwConsoleMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
} }
@@ -155,6 +160,10 @@ private:
p += 3; p += 3;
size -= 3; size -= 3;
if (!CONSOLE_COLORS) {
strip_colors(p, size);
}
#ifdef _WIN32 #ifdef _WIN32
DWORD k; DWORD k;
WriteConsole((severity == 1) ? hStdOut : hStdErr, p, size, &k, nullptr); WriteConsole((severity == 1) ? hStdOut : hStdErr, p, size, &k, nullptr);
@@ -172,7 +181,9 @@ private:
} }
if (m_logFile.is_open()) { if (m_logFile.is_open()) {
strip_colors(p, size); if (CONSOLE_COLORS) {
strip_colors(p, size);
}
if (severity == 1) { if (severity == 1) {
m_logFile.write("NOTICE ", 8); m_logFile.write("NOTICE ", 8);
+1
View File
@@ -22,6 +22,7 @@ namespace p2pool {
namespace log { namespace log {
extern int GLOBAL_LOG_LEVEL; extern int GLOBAL_LOG_LEVEL;
extern bool CONSOLE_COLORS;
constexpr int MAX_GLOBAL_LOG_LEVEL = 6; constexpr int MAX_GLOBAL_LOG_LEVEL = 6;
enum class Severity { enum class Severity {
+1
View File
@@ -38,6 +38,7 @@ static void usage()
"--data-api Path to the p2pool JSON data (use it in tandem with an external web-server)\n" "--data-api Path to the p2pool JSON data (use it in tandem with an external web-server)\n"
"--stratum-api Enable /local/ path in api path for Stratum Server statistics\n" "--stratum-api Enable /local/ path in api path for Stratum Server statistics\n"
"--no-cache Disable p2pool.cache\n" "--no-cache Disable p2pool.cache\n"
"--no-color Disable colors in console output\n"
"--help Show this help message\n\n" "--help Show this help message\n\n"
"Example command line:\n\n" "Example command line:\n\n"
"%s --host 127.0.0.1 --rpc-port 18081 --zmq-port 18083 --wallet YOUR_WALLET_ADDRESS --stratum 0.0.0.0:%d --p2p 0.0.0.0:%d\n\n", "%s --host 127.0.0.1 --rpc-port 18081 --zmq-port 18083 --wallet YOUR_WALLET_ADDRESS --stratum 0.0.0.0:%d --p2p 0.0.0.0:%d\n\n",
+40 -10
View File
@@ -120,9 +120,9 @@ FORCEINLINE static void remove_allocation(void* p)
__debugbreak(); __debugbreak();
} }
FORCEINLINE static void* allocate_noexcept(size_t n) noexcept void* malloc_hook(size_t n) noexcept
{ {
void* p = malloc(n + sizeof(TrackedAllocation)); void* p = malloc(n);
if (p) { if (p) {
add_alocation(p, n); add_alocation(p, n);
} }
@@ -131,25 +131,46 @@ FORCEINLINE static void* allocate_noexcept(size_t n) noexcept
FORCEINLINE static void* allocate(size_t n) FORCEINLINE static void* allocate(size_t n)
{ {
void* p = allocate_noexcept(n); void* p = malloc_hook(n);
if (!p) { if (!p) {
throw std::bad_alloc(); throw std::bad_alloc();
} }
return p; return p;
} }
FORCEINLINE static void deallocate(void* p) void free_hook(void* p) noexcept
{ {
remove_allocation(p); remove_allocation(p);
free(p); free(p);
} }
void* realloc_hook(void* ptr, size_t size) noexcept
{
remove_allocation(ptr);
void* p = realloc(ptr, size);
if (p) {
add_alocation(p, size);
}
return p;
}
void* calloc_hook(size_t count, size_t size) noexcept
{
void* p = calloc(count, size);
if (p) {
add_alocation(p, size);
}
return p;
}
} // p2pool } // p2pool
void memory_tracking_start() void memory_tracking_start()
{ {
using namespace p2pool; using namespace p2pool;
uv_replace_allocator(malloc_hook, realloc_hook, calloc_hook, free_hook);
uv_mutex_init_checked(&allocation_lock); uv_mutex_init_checked(&allocation_lock);
track_memory = true; track_memory = true;
} }
@@ -207,14 +228,23 @@ void memory_tracking_stop()
NOINLINE void* operator new(size_t n) { return p2pool::allocate(n); } NOINLINE void* operator new(size_t n) { return p2pool::allocate(n); }
NOINLINE void* operator new[](size_t n) { return p2pool::allocate(n); } NOINLINE void* operator new[](size_t n) { return p2pool::allocate(n); }
NOINLINE void* operator new(size_t n, const std::nothrow_t&) noexcept { return p2pool::allocate_noexcept(n); } NOINLINE void* operator new(size_t n, const std::nothrow_t&) noexcept { return p2pool::malloc_hook(n); }
NOINLINE void* operator new[](size_t n, const std::nothrow_t&) noexcept { return p2pool::allocate_noexcept(n); } NOINLINE void* operator new[](size_t n, const std::nothrow_t&) noexcept { return p2pool::malloc_hook(n); }
NOINLINE void operator delete(void* p) noexcept { p2pool::deallocate(p); } NOINLINE void operator delete(void* p) noexcept { p2pool::free_hook(p); }
NOINLINE void operator delete[](void* p) noexcept { p2pool::deallocate(p); } NOINLINE void operator delete[](void* p) noexcept { p2pool::free_hook(p); }
NOINLINE void operator delete(void* p, size_t) noexcept { p2pool::deallocate(p); } NOINLINE void operator delete(void* p, size_t) noexcept { p2pool::free_hook(p); }
NOINLINE void operator delete[](void* p, size_t) noexcept { p2pool::deallocate(p); } NOINLINE void operator delete[](void* p, size_t) noexcept { p2pool::free_hook(p); }
#else #else
void memory_tracking_start() {} void memory_tracking_start() {}
void memory_tracking_stop() {} void memory_tracking_stop() {}
namespace p2pool {
void* malloc_hook(size_t n) noexcept { return malloc(n); }
void* realloc_hook(void* ptr, size_t size) noexcept { return realloc(ptr, size); }
void* calloc_hook(size_t count, size_t size) noexcept { return calloc(count, size); }
void free_hook(void* p) noexcept { free(p); }
}
#endif #endif
+1 -2
View File
@@ -18,7 +18,6 @@
#pragma once #pragma once
#include "uv_util.h" #include "uv_util.h"
#include <unordered_map>
namespace p2pool { namespace p2pool {
@@ -35,7 +34,7 @@ public:
public: public:
mutable uv_rwlock_t m_lock; mutable uv_rwlock_t m_lock;
std::unordered_map<hash, TxMempoolData> m_transactions; unordered_map<hash, TxMempoolData> m_transactions;
}; };
} // namespace p2pool } // namespace p2pool
+50 -7
View File
@@ -94,6 +94,7 @@ P2PServer::P2PServer(p2pool* pool)
P2PServer::~P2PServer() P2PServer::~P2PServer()
{ {
uv_timer_stop(&m_timer); uv_timer_stop(&m_timer);
uv_close(reinterpret_cast<uv_handle_t*>(&m_timer), nullptr);
uv_close(reinterpret_cast<uv_handle_t*>(&m_broadcastAsync), nullptr); uv_close(reinterpret_cast<uv_handle_t*>(&m_broadcastAsync), nullptr);
shutdown_tcp(); shutdown_tcp();
@@ -225,8 +226,8 @@ void P2PServer::update_peer_connections()
peer_list = m_peerList; peer_list = m_peerList;
} }
// Try to have at least 8 outgoing connections // Try to have at least 10 outgoing connections
for (uint32_t i = m_numConnections - m_numIncomingConnections; (i < 8) && !peer_list.empty();) { for (uint32_t i = m_numConnections - m_numIncomingConnections; (i < 10) && !peer_list.empty();) {
const uint64_t k = get_random64() % peer_list.size(); const uint64_t k = get_random64() % peer_list.size();
const Peer& peer = peer_list[k]; const Peer& peer = peer_list[k];
@@ -277,6 +278,7 @@ void P2PServer::update_peer_list()
}); });
if (result) { if (result) {
client->m_lastPeerListRequestTime = std::chrono::system_clock::now();
++client->m_peerListPendingRequests; ++client->m_peerListPendingRequests;
} }
} }
@@ -314,7 +316,7 @@ void P2PServer::save_peer_list_async()
}); });
if (err) { if (err) {
LOGERR(1, "update_peer_list: uv_queue_work failed, error " << uv_err_name(err)); LOGERR(1, "save_peer_list_async: uv_queue_work failed, error " << uv_err_name(err));
delete work; delete work;
} }
} }
@@ -686,12 +688,39 @@ uint64_t P2PServer::get_random64()
void P2PServer::print_status() void P2PServer::print_status()
{ {
const int64_t uptime = time(nullptr) - m_pool->start_time();
const int64_t s = uptime % 60;
const int64_t m = (uptime / 60) % 60;
const int64_t h = (uptime / 3600) % 24;
const int64_t d = uptime / 86400;
char buf[log::Stream::BUF_SIZE + 1];
log::Stream s1(buf);
if (d > 0) {
s1 << d << "d ";
}
s1 << h << "h " << m << "m " << s << 's';
LOGINFO(0, "status" << LOGINFO(0, "status" <<
"\nConnections = " << m_numConnections << " (" << m_numIncomingConnections << " incoming)" << "\nConnections = " << m_numConnections << " (" << m_numIncomingConnections << " incoming)" <<
"\nPeer list size = " << m_peerList.size() "\nPeer list size = " << m_peerList.size() <<
"\nUptime = " << log::const_buf(buf, s1.m_pos)
); );
} }
void P2PServer::show_peers()
{
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_listenPort >= 0) {
LOGINFO(0, (client->m_isIncoming ? "I " : "O ") << client->m_pingTime << " ms\t" << static_cast<char*>(client->m_addrString));
}
}
}
void P2PServer::on_timer() void P2PServer::on_timer()
{ {
++m_timerCounter; ++m_timerCounter;
@@ -831,7 +860,9 @@ P2PServer::P2PClient::P2PClient()
, m_handshakeInvalid(false) , m_handshakeInvalid(false)
, m_listenPort(-1) , m_listenPort(-1)
, m_nextPeerListRequest(0) , m_nextPeerListRequest(0)
, m_lastPeerListRequestTime{}
, m_peerListPendingRequests(0) , m_peerListPendingRequests(0)
, m_pingTime(0)
, m_lastAlive(0) , m_lastAlive(0)
, m_lastBroadcastTimestamp(0) , m_lastBroadcastTimestamp(0)
, m_lastBlockrequestTimestamp(0) , m_lastBlockrequestTimestamp(0)
@@ -855,7 +886,9 @@ void P2PServer::P2PClient::reset()
m_handshakeInvalid = false; m_handshakeInvalid = false;
m_listenPort = -1; m_listenPort = -1;
m_nextPeerListRequest = 0; m_nextPeerListRequest = 0;
m_lastPeerListRequestTime = {};
m_peerListPendingRequests = 0; m_peerListPendingRequests = 0;
m_pingTime = 0;
m_lastAlive = 0; m_lastAlive = 0;
m_lastBroadcastTimestamp = 0; m_lastBroadcastTimestamp = 0;
m_lastBlockrequestTimestamp = 0; m_lastBlockrequestTimestamp = 0;
@@ -1041,7 +1074,7 @@ bool P2PServer::P2PClient::on_read(char* data, uint32_t size)
LOGINFO(5, "peer " << log::Gray() << static_cast<char*>(m_addrString) << log::NoColor() << " sent PEER_LIST_RESPONSE"); LOGINFO(5, "peer " << log::Gray() << static_cast<char*>(m_addrString) << log::NoColor() << " sent PEER_LIST_RESPONSE");
if (bytes_left >= 2) { if (bytes_left >= 2) {
const uint8_t num_peers = buf[1]; const uint32_t num_peers = buf[1];
if (num_peers > PEER_LIST_RESPONSE_MAX_PEERS) { if (num_peers > PEER_LIST_RESPONSE_MAX_PEERS) {
LOGWARN(5, "peer " << log::Gray() << static_cast<char*>(m_addrString) << log::NoColor() << " sent too long peer list (" << num_peers << ')'); LOGWARN(5, "peer " << log::Gray() << static_cast<char*>(m_addrString) << log::NoColor() << " sent too long peer list (" << num_peers << ')');
ban(DEFAULT_BAN_TIME); ban(DEFAULT_BAN_TIME);
@@ -1049,8 +1082,11 @@ bool P2PServer::P2PClient::on_read(char* data, uint32_t size)
return false; return false;
} }
if (bytes_left >= 2u + num_peers * 19) { if (bytes_left >= 2u + num_peers * 19u) {
bytes_read = 2u + num_peers * 19; bytes_read = 2u + num_peers * 19u;
using namespace std::chrono;
m_pingTime = duration_cast<milliseconds>(system_clock::now() - m_lastPeerListRequestTime).count();
--m_peerListPendingRequests; --m_peerListPendingRequests;
if (!on_peer_list_response(buf + 1)) { if (!on_peer_list_response(buf + 1)) {
@@ -1609,6 +1645,13 @@ bool P2PServer::P2PClient::on_peer_list_response(const uint8_t* buf) const
memcpy(ip.data, buf, sizeof(ip.data)); memcpy(ip.data, buf, sizeof(ip.data));
buf += sizeof(ip.data); buf += sizeof(ip.data);
// Fill in default bytes for IPv4 addresses
if (!is_v6) {
memset(ip.data, 0, 10);
ip.data[10] = 0xFF;
ip.data[11] = 0xFF;
}
int port = 0; int port = 0;
memcpy(&port, buf, 2); memcpy(&port, buf, 2);
buf += 2; buf += 2;
+6 -2
View File
@@ -19,7 +19,6 @@
#include "tcp_server.h" #include "tcp_server.h"
#include <random> #include <random>
#include <unordered_map>
namespace p2pool { namespace p2pool {
@@ -109,8 +108,12 @@ public:
bool m_handshakeComplete; bool m_handshakeComplete;
bool m_handshakeInvalid; bool m_handshakeInvalid;
int m_listenPort; int m_listenPort;
time_t m_nextPeerListRequest; time_t m_nextPeerListRequest;
std::chrono::system_clock::time_point m_lastPeerListRequestTime;
int m_peerListPendingRequests; int m_peerListPendingRequests;
int64_t m_pingTime;
time_t m_lastAlive; time_t m_lastAlive;
time_t m_lastBroadcastTimestamp; time_t m_lastBroadcastTimestamp;
time_t m_lastBlockrequestTimestamp; time_t m_lastBlockrequestTimestamp;
@@ -124,6 +127,7 @@ public:
uint64_t get_peerId() const { return m_peerId; } uint64_t get_peerId() const { return m_peerId; }
void print_status() override; void print_status() override;
void show_peers();
private: private:
p2pool* m_pool; p2pool* m_pool;
@@ -132,7 +136,7 @@ private:
std::string m_initialPeerList; std::string m_initialPeerList;
uv_rwlock_t m_cachedBlocksLock; uv_rwlock_t m_cachedBlocksLock;
std::unordered_map<hash, PoolBlock*> m_cachedBlocks; unordered_map<hash, PoolBlock*> m_cachedBlocks;
private: private:
static void on_timer(uv_timer_t* timer) { reinterpret_cast<P2PServer*>(timer->data)->on_timer(); } static void on_timer(uv_timer_t* timer) { reinterpret_cast<P2PServer*>(timer->data)->on_timer(); }
+2
View File
@@ -49,6 +49,8 @@ p2pool::p2pool(int argc, char* argv[])
, m_params(new Params(argc, argv)) , m_params(new Params(argc, argv))
, m_updateSeed(true) , m_updateSeed(true)
, m_submitBlockData{} , m_submitBlockData{}
, m_zmqLastActive(0)
, m_startTime(time(nullptr))
{ {
LOGINFO(1, log::LightCyan() << VERSION); LOGINFO(1, log::LightCyan() << VERSION);
+7 -6
View File
@@ -19,7 +19,6 @@
#include "uv_util.h" #include "uv_util.h"
#include <map> #include <map>
#include <unordered_map>
namespace p2pool { namespace p2pool {
@@ -79,6 +78,7 @@ public:
bool get_difficulty_at_height(uint64_t height, difficulty_type& diff); bool get_difficulty_at_height(uint64_t height, difficulty_type& diff);
time_t zmq_last_active() const { return m_zmqLastActive; } time_t zmq_last_active() const { return m_zmqLastActive; }
time_t start_time() const { return m_startTime; }
private: private:
p2pool(const p2pool&) = delete; p2pool(const p2pool&) = delete;
@@ -104,7 +104,7 @@ private:
mutable uv_rwlock_t m_mainchainLock; mutable uv_rwlock_t m_mainchainLock;
std::map<uint64_t, ChainMain> m_mainchainByHeight; std::map<uint64_t, ChainMain> m_mainchainByHeight;
std::unordered_map<hash, ChainMain> m_mainchainByHash; unordered_map<hash, ChainMain> m_mainchainByHash;
enum { TIMESTAMP_WINDOW = 60 }; enum { TIMESTAMP_WINDOW = 60 };
bool get_timestamps(uint64_t (&timestamps)[TIMESTAMP_WINDOW]) const; bool get_timestamps(uint64_t (&timestamps)[TIMESTAMP_WINDOW]) const;
@@ -157,9 +157,9 @@ private:
struct SubmitBlockData struct SubmitBlockData
{ {
uint32_t template_id; uint32_t template_id = 0;
uint32_t nonce; uint32_t nonce = 0;
uint32_t extra_nonce; uint32_t extra_nonce = 0;
std::vector<uint8_t> blob; std::vector<uint8_t> blob;
}; };
@@ -170,7 +170,8 @@ private:
uv_async_t m_blockTemplateAsync; uv_async_t m_blockTemplateAsync;
uv_async_t m_stopAsync; uv_async_t m_stopAsync;
time_t m_zmqLastActive = 0; time_t m_zmqLastActive;
time_t m_startTime;
}; };
} // namespace p2pool } // namespace p2pool
+1 -1
View File
@@ -127,7 +127,7 @@ void p2pool_api::dump_to_file_async_internal(const Category& category, const cha
void p2pool_api::dump_to_file() void p2pool_api::dump_to_file()
{ {
std::unordered_map<std::string, std::vector<char>> data; unordered_map<std::string, std::vector<char>> data;
{ {
MutexLock lock(m_dumpDataLock); MutexLock lock(m_dumpDataLock);
data = std::move(m_dumpData); data = std::move(m_dumpData);
+1 -2
View File
@@ -18,7 +18,6 @@
#pragma once #pragma once
#include "uv_util.h" #include "uv_util.h"
#include <unordered_map>
namespace p2pool { namespace p2pool {
@@ -84,7 +83,7 @@ private:
std::string m_localPath; std::string m_localPath;
uv_mutex_t m_dumpDataLock; uv_mutex_t m_dumpDataLock;
std::unordered_map<std::string, std::vector<char>> m_dumpData; unordered_map<std::string, std::vector<char>> m_dumpData;
uv_async_t m_dumpToFileAsync; uv_async_t m_dumpToFileAsync;
}; };
+4
View File
@@ -77,6 +77,10 @@ Params::Params(int argc, char* argv[])
if (strcmp(argv[i], "--no-cache") == 0) { if (strcmp(argv[i], "--no-cache") == 0) {
m_blockCache = false; m_blockCache = false;
} }
if (strcmp(argv[i], "--no-color") == 0) {
log::CONSOLE_COLORS = false;
}
} }
if (m_stratumAddresses.empty()) { if (m_stratumAddresses.empty()) {
+3 -3
View File
@@ -44,8 +44,8 @@ private:
struct ThreadSafeVM struct ThreadSafeVM
{ {
uv_mutex_t mutex; uv_mutex_t mutex{};
randomx_vm* vm; randomx_vm* vm = nullptr;
}; };
p2pool* m_pool; p2pool* m_pool;
@@ -62,7 +62,7 @@ private:
// 1: light VM for the previous seed // 1: light VM for the previous seed
// 2: full dataset VM for the current seed // 2: full dataset VM for the current seed
enum { FULL_DATASET_VM = 2 }; enum { FULL_DATASET_VM = 2 };
ThreadSafeVM m_vm[3]; ThreadSafeVM m_vm[3]{};
hash m_seed[2]; hash m_seed[2];
uint32_t m_index; uint32_t m_index;
+3 -5
View File
@@ -19,8 +19,6 @@
#include "uv_util.h" #include "uv_util.h"
#include <map> #include <map>
#include <unordered_map>
#include <unordered_set>
namespace p2pool { namespace p2pool {
@@ -98,9 +96,9 @@ private:
mutable uv_mutex_t m_sidechainLock; mutable uv_mutex_t m_sidechainLock;
PoolBlock* m_chainTip; PoolBlock* m_chainTip;
std::map<uint64_t, std::vector<PoolBlock*>> m_blocksByHeight; std::map<uint64_t, std::vector<PoolBlock*>> m_blocksByHeight;
std::unordered_map<hash, PoolBlock*> m_blocksById; unordered_map<hash, PoolBlock*> m_blocksById;
std::unordered_set<hash> m_seenBlocks; unordered_set<hash> m_seenBlocks;
std::unordered_map<hash, time_t> m_seenWallets; unordered_map<hash, time_t> m_seenWallets;
std::vector<DifficultyData> m_difficultyData; std::vector<DifficultyData> m_difficultyData;
+43 -5
View File
@@ -176,6 +176,28 @@ void StratumServer::on_block(const BlockTemplate& block)
} }
} }
bool StratumServer::get_custom_user(const char* s, std::string& user)
{
user.clear();
// Find first of '+' or '.', drop non-printable characters
while (s && (user.length() < 64)) {
const char c = *s;
if (!c) {
break;
}
if ((c == '+') || (c == '.')) {
break;
}
// Limit to printable ASCII characters
if (c >= ' ' && c <= '~') {
user += c;
}
++s;
}
return !user.empty();
}
bool StratumServer::get_custom_diff(const char* s, difficulty_type& diff) bool StratumServer::get_custom_diff(const char* s, difficulty_type& diff)
{ {
const char* diff_str = nullptr; const char* diff_str = nullptr;
@@ -225,6 +247,10 @@ bool StratumServer::on_login(StratumClient* client, uint32_t id, const char* log
target = std::max(target, client->m_customDiff.target()); target = std::max(target, client->m_customDiff.target());
} }
if (get_custom_user(login, client->m_customUser)) {
LOGINFO(5, "client " << log::Gray() << static_cast<char*>(client->m_addrString) << " set custom user " << client->m_customUser);
}
uint32_t job_id; uint32_t job_id;
{ {
MutexLock lock(client->m_jobsLock); MutexLock lock(client->m_jobsLock);
@@ -334,7 +360,8 @@ bool StratumServer::on_submit(StratumClient* client, uint32_t id, const char* jo
} }
if (mainchain_diff.check_pow(resultHash)) { if (mainchain_diff.check_pow(resultHash)) {
LOGINFO(0, log::Green() << "client " << static_cast<char*>(client->m_addrString) << " found a mainchain block, submitting it"); const std::string& s = client->m_customUser;
LOGINFO(0, log::Green() << "client " << static_cast<char*>(client->m_addrString) << (!s.empty() ? " user " : "") << s << " found a mainchain block, submitting it");
m_pool->submit_block_async(template_id, nonce, extra_nonce); m_pool->submit_block_async(template_id, nonce, extra_nonce);
block.update_tx_keys(); block.update_tx_keys();
} }
@@ -367,12 +394,21 @@ bool StratumServer::on_submit(StratumClient* client, uint32_t id, const char* jo
share->m_resultHash = resultHash; share->m_resultHash = resultHash;
share->m_sidechainDifficulty = sidechain_diff; share->m_sidechainDifficulty = sidechain_diff;
// If this share is below sidechain difficulty, process it in this thread because it'll be quick
if (!share->m_sidechainDifficulty.check_pow(share->m_resultHash)) {
on_share_found(&share->m_req);
on_after_share_found(&share->m_req, 0);
return true;
}
// Else switch to a worker thread to check PoW which can take a long time
const int err = uv_queue_work(&m_loop, &share->m_req, on_share_found, on_after_share_found); const int err = uv_queue_work(&m_loop, &share->m_req, on_share_found, on_after_share_found);
if (err) { if (err) {
LOGERR(1, "uv_queue_work failed, error " << uv_err_name(err)); LOGERR(1, "uv_queue_work failed, error " << uv_err_name(err));
MutexLock lock(m_submittedSharesPoolLock);
m_submittedSharesPool.push_back(share); // If uv_queue_work failed, process this share here anyway
return false; on_share_found(&share->m_req);
on_after_share_found(&share->m_req, 0);
} }
return true; return true;
@@ -645,7 +681,8 @@ void StratumServer::on_share_found(uv_work_t* req)
server->m_cumulativeFoundSharesDiff += diff; server->m_cumulativeFoundSharesDiff += diff;
++server->m_totalFoundShares; ++server->m_totalFoundShares;
LOGINFO(0, log::Green() << "SHARE FOUND: mainchain height " << height << ", diff " << sidechain_difficulty << ", effort " << effort << '%'); const std::string& s = client->m_customUser;
LOGINFO(0, log::Green() << "SHARE FOUND: mainchain height " << height << ", diff " << sidechain_difficulty << ", client " << static_cast<char*>(client->m_addrString) << (!s.empty() ? " user " : "") << s << ", effort " << effort << '%');
pool->submit_sidechain_block(share->m_templateId, share->m_nonce, share->m_extraNonce); pool->submit_sidechain_block(share->m_templateId, share->m_nonce, share->m_extraNonce);
} }
@@ -742,6 +779,7 @@ void StratumServer::StratumClient::reset()
memset(m_jobs, 0, sizeof(m_jobs)); memset(m_jobs, 0, sizeof(m_jobs));
m_perConnectionJobId = 0; m_perConnectionJobId = 0;
m_customDiff = {}; m_customDiff = {};
m_customUser.clear();
} }
bool StratumServer::StratumClient::on_read(char* data, uint32_t size) bool StratumServer::StratumClient::on_read(char* data, uint32_t size)
+2
View File
@@ -65,6 +65,7 @@ public:
uint32_t m_perConnectionJobId; uint32_t m_perConnectionJobId;
difficulty_type m_customDiff; difficulty_type m_customDiff;
std::string m_customUser;
}; };
bool on_login(StratumClient* client, uint32_t id, const char* login); bool on_login(StratumClient* client, uint32_t id, const char* login);
@@ -77,6 +78,7 @@ private:
void print_stratum_status() const; void print_stratum_status() const;
static bool get_custom_diff(const char* s, difficulty_type& diff); static bool get_custom_diff(const char* s, difficulty_type& diff);
static bool get_custom_user(const char* s, std::string& user);
static void on_share_found(uv_work_t* req); static void on_share_found(uv_work_t* req);
static void on_after_share_found(uv_work_t* req, int status); static void on_after_share_found(uv_work_t* req, int status);
-1
View File
@@ -308,7 +308,6 @@ bool TCPServer<READ_BUF_SIZE, WRITE_BUF_SIZE>::connect_to_peer(bool is_v6, const
return connect_to_peer_nolock(client, is_v6, reinterpret_cast<sockaddr*>(&addr)); return connect_to_peer_nolock(client, is_v6, reinterpret_cast<sockaddr*>(&addr));
} }
template<size_t READ_BUF_SIZE, size_t WRITE_BUF_SIZE> template<size_t READ_BUF_SIZE, size_t WRITE_BUF_SIZE>
void TCPServer<READ_BUF_SIZE, WRITE_BUF_SIZE>::on_connect_failed(bool, const raw_ip&, int) void TCPServer<READ_BUF_SIZE, WRITE_BUF_SIZE>::on_connect_failed(bool, const raw_ip&, int)
{ {
+1 -1
View File
@@ -32,7 +32,7 @@ namespace p2pool {
#define STR2(X) STR(X) #define STR2(X) STR(X)
#define STR(X) #X #define STR(X) #X
const char* VERSION = "v1.2 (built" const char* VERSION = "v1.3 (built"
#if defined(__clang__) #if defined(__clang__)
" with clang/" __clang_version__ " with clang/" __clang_version__
#elif defined(__GNUC__) #elif defined(__GNUC__)
+25 -12
View File
@@ -17,6 +17,21 @@
#pragma once #pragma once
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 5027)
#endif
#define ROBIN_HOOD_MALLOC(size) p2pool::malloc_hook(size)
#define ROBIN_HOOD_CALLOC(count, size) p2pool::calloc_hook((count), (size))
#define ROBIN_HOOD_FREE(ptr) p2pool::free_hook(ptr)
#include "robin_hood.h"
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace p2pool { namespace p2pool {
extern const char* VERSION; extern const char* VERSION;
@@ -122,20 +137,22 @@ extern thread_local bool is_main_thread;
bool resolve_host(std::string& host, bool& is_v6); bool resolve_host(std::string& host, bool& is_v6);
template <typename Key, typename T>
using unordered_map = robin_hood::detail::Table<false, 80, Key, T, robin_hood::hash<Key>, std::equal_to<Key>>;
template <typename Key>
using unordered_set = robin_hood::detail::Table<false, 80, Key, void, robin_hood::hash<Key>, std::equal_to<Key>>;
} // namespace p2pool } // namespace p2pool
namespace std { namespace robin_hood {
template<> template<>
struct hash<p2pool::hash> struct hash<p2pool::hash>
{ {
FORCEINLINE size_t operator()(const p2pool::hash& value) const noexcept FORCEINLINE size_t operator()(const p2pool::hash& value) const noexcept
{ {
uint64_t result = 0xcbf29ce484222325ull; return hash_bytes(value.h, p2pool::HASH_SIZE);
for (size_t i = 0; i < p2pool::HASH_SIZE; ++i) {
result = (result ^ value.h[i]) * 0x100000001b3ull;
}
return static_cast<size_t>(result);
} }
}; };
@@ -144,12 +161,8 @@ struct hash<std::array<uint8_t, N>>
{ {
FORCEINLINE size_t operator()(const std::array<uint8_t, N>& value) const noexcept FORCEINLINE size_t operator()(const std::array<uint8_t, N>& value) const noexcept
{ {
uint64_t result = 0xcbf29ce484222325ull; return hash_bytes(value.data(), N);
for (size_t i = 0; i < N; ++i) {
result = (result ^ value[i]) * 0x100000001b3ull;
}
return static_cast<size_t>(result);
} }
}; };
} // namespace std } // namespace robin_hood
+8 -7
View File
@@ -76,20 +76,22 @@ ZMQReader::~ZMQReader()
} }
} }
void ZMQReader::run_wrapper(void* arg)
{
reinterpret_cast<ZMQReader*>(arg)->run();
LOGINFO(1, "worker thread stopped");
}
void ZMQReader::run() void ZMQReader::run()
{ {
try { try {
char addr[32]; char addr[32];
snprintf(addr, sizeof(addr), "tcp://%s:%u", m_address, m_zmqPort); snprintf(addr, sizeof(addr), "tcp://%s:%u", m_address, m_zmqPort);
if (!connect(addr, m_zmqPort)) { while (!connect(addr, m_zmqPort)) { if (m_finished.load()) return; }
throw zmq::error_t();
}
snprintf(addr, sizeof(addr), "tcp://127.0.0.1:%u", m_publisherPort); snprintf(addr, sizeof(addr), "tcp://127.0.0.1:%u", m_publisherPort);
if (!connect(addr, m_publisherPort)) { while (!connect(addr, m_publisherPort)) { if (m_finished.load()) return; }
throw zmq::error_t();
}
m_subscriber.set(zmq::sockopt::subscribe, "json-full-chain_main"); m_subscriber.set(zmq::sockopt::subscribe, "json-full-chain_main");
m_subscriber.set(zmq::sockopt::subscribe, "json-full-miner_data"); m_subscriber.set(zmq::sockopt::subscribe, "json-full-miner_data");
@@ -122,7 +124,6 @@ void ZMQReader::run()
LOGERR(1, "exception " << e.what() << ", aborting"); LOGERR(1, "exception " << e.what() << ", aborting");
panic(); panic();
} }
LOGINFO(1, "worker thread stopped");
} }
bool ZMQReader::connect(const char* address, uint32_t id) bool ZMQReader::connect(const char* address, uint32_t id)
+1 -1
View File
@@ -28,7 +28,7 @@ public:
~ZMQReader(); ~ZMQReader();
private: private:
static void run_wrapper(void* arg) { reinterpret_cast<ZMQReader*>(arg)->run(); } static void run_wrapper(void* arg);
void run(); void run();
bool connect(const char* address, uint32_t id); bool connect(const char* address, uint32_t id);
+2
View File
@@ -84,6 +84,7 @@ set(SOURCES
../src/json_rpc_request.cpp ../src/json_rpc_request.cpp
../src/keccak.cpp ../src/keccak.cpp
../src/log.cpp ../src/log.cpp
../src/memory_leak_debug.cpp
../src/mempool.cpp ../src/mempool.cpp
../src/p2p_server.cpp ../src/p2p_server.cpp
../src/p2pool.cpp ../src/p2pool.cpp
@@ -107,6 +108,7 @@ include_directories(../external/src/libzmq/include)
include_directories(../external/src/llhttp) include_directories(../external/src/llhttp)
include_directories(../external/src/RandomX/src) include_directories(../external/src/RandomX/src)
include_directories(../external/src/rapidjson/include) include_directories(../external/src/rapidjson/include)
include_directories(../external/src/robin-hood-hashing/src/include)
include_directories(src) include_directories(src)
include_directories(googletest/googletest/include) include_directories(googletest/googletest/include)