Compare commits

...

21 Commits

Author SHA1 Message Date
SChernykh 5b9b73abcc p2pool v1.9 2022-03-30 20:15:47 +02:00
SChernykh a2afa29052 Updated copyright 2022-03-30 14:42:26 +02:00
SChernykh a2d3dbad5e Use old bock template when update fails 2022-03-30 10:11:35 +02:00
SChernykh e50cf060cb Miner: fixed share counter initialization 2022-03-30 08:34:22 +02:00
SChernykh 915988d694 Added logging for the extra_nonce fix 2022-03-30 07:59:59 +02:00
SChernykh 345c231a9a Update config.json 2022-03-28 19:12:21 +02:00
SChernykh a7aed2f221 Fixed miner tx creation 2022-03-28 11:28:56 +02:00
SChernykh 292e2580e5 Make sure dataset init doesn't block start 2022-03-24 20:55:35 +01:00
SChernykh 028a5d0c88 Fixed memory leak after loading block cache 2022-03-24 18:30:23 +01:00
SChernykh 8b27faad6d BlockCache: fixed collisions of same height blocks 2022-03-24 16:03:12 +01:00
SChernykh cdc3206ee8 Optimized keccak 2022-03-24 12:52:57 +01:00
SChernykh 0c2b7d6010 More time handling fixes 2022-03-23 15:49:24 +01:00
SChernykh ef15c3b54f Show sidechain ID in status 2022-03-23 14:17:40 +01:00
SChernykh f4bcdc7fe9 Use steady_clock to time peer list requests 2022-03-23 11:37:05 +01:00
SChernykh aada1bb5cc Use chrono::steady_clock for internal timestamps 2022-03-23 11:30:38 +01:00
SChernykh 796850d8c5 Update CMakeLists.txt 2022-03-18 14:53:30 +01:00
SChernykh ab0bc0488e Removed libsodium as it's not used in compilation 2022-03-18 14:43:23 +01:00
SChernykh f3af02111d Update README.md 2022-03-18 10:31:06 +01:00
SChernykh c21d052d7a Refactored RNG usage across the code 2022-03-17 16:14:29 +01:00
SChernykh 62b1690780 Added an option to disable RandomX for the build 2022-03-15 17:11:45 +01:00
SChernykh 52050bbcfb Update difficulty_type_tests.cpp 2022-03-10 19:11:49 +01:00
56 changed files with 422 additions and 231 deletions
+5 -4
View File
@@ -106,8 +106,9 @@ jobs:
strategy:
matrix:
config:
- {vs: Visual Studio 16 2019, os: 2019, msbuild: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\MSBuild\\Current\\Bin\\amd64\\"}
- {vs: Visual Studio 17 2022, os: 2022, msbuild: "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\"}
- {vs: Visual Studio 16 2019, os: 2019, msbuild: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\MSBuild\\Current\\Bin\\amd64\\", rx: "ON"}
- {vs: Visual Studio 17 2022, os: 2022, msbuild: "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\", rx: "ON"}
- {vs: Visual Studio 17 2022, os: 2022, msbuild: "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\", rx: "OFF"}
steps:
- name: Checkout repository
@@ -122,7 +123,7 @@ jobs:
run: |
mkdir build
cd build
cmake .. -G "${{ matrix.config.vs }}"
cmake .. -G "${{ matrix.config.vs }}" -DWITH_RANDOMX=${{ matrix.config.rx }}
& "${{ matrix.config.msbuild }}msbuild" /m /p:Configuration=Release p2pool.vcxproj
- name: Build tests
@@ -141,7 +142,7 @@ jobs:
- name: Archive binary
uses: actions/upload-artifact@v2
with:
name: p2pool-msbuild-${{ matrix.config.os }}.exe
name: p2pool-msbuild-${{ matrix.config.os }}-randomx-${{ matrix.config.rx }}.exe
path: build/Release/p2pool.exe
build-macos:
-3
View File
@@ -10,9 +10,6 @@
[submodule "external/src/cppzmq"]
path = external/src/cppzmq
url = https://github.com/SChernykh/cppzmq
[submodule "external/src/libsodium"]
path = external/src/libsodium
url = https://github.com/SChernykh/libsodium
[submodule "external/src/libuv"]
path = external/src/libuv
url = https://github.com/SChernykh/libuv
+18 -6
View File
@@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 2.8.12)
project(p2pool)
option(STATIC_BINARY "Build static binary" OFF)
option(WITH_RANDOMX "Include the RandomX library in the build. If this is turned off, p2pool will rely on monerod for verifying RandomX hashes" ON)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
@@ -9,8 +10,11 @@ if (${CMAKE_VERSION} VERSION_GREATER "3.5.2")
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT p2pool)
endif()
add_subdirectory(external/src/RandomX)
set(LIBS randomx)
if (WITH_RANDOMX)
add_definitions(-DWITH_RANDOMX)
add_subdirectory(external/src/RandomX)
set(LIBS randomx)
endif()
include(cmake/flags.cmake)
@@ -27,7 +31,6 @@ set(HEADERS
src/keccak.h
src/log.h
src/mempool.h
src/miner.h
src/p2p_server.h
src/p2pool.h
src/p2pool_api.h
@@ -61,7 +64,6 @@ set(SOURCES
src/main.cpp
src/memory_leak_debug.cpp
src/mempool.cpp
src/miner.cpp
src/p2p_server.cpp
src/p2pool.cpp
src/p2pool_api.cpp
@@ -75,6 +77,11 @@ set(SOURCES
src/zmq_reader.cpp
)
if (WITH_RANDOMX)
set(HEADERS ${HEADERS} src/miner.h)
set(SOURCES ${SOURCES} src/miner.cpp)
endif()
include_directories(src)
include_directories(external/src)
include_directories(external/src/cryptonote)
@@ -82,7 +89,9 @@ include_directories(external/src/libuv/include)
include_directories(external/src/cppzmq)
include_directories(external/src/libzmq/include)
include_directories(external/src/llhttp)
include_directories(external/src/RandomX/src)
if (WITH_RANDOMX)
include_directories(external/src/RandomX/src)
endif()
include_directories(external/src/rapidjson/include)
include_directories(external/src/robin-hood-hashing/src/include)
@@ -127,7 +136,10 @@ add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES})
if (STATIC_BINARY)
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} ${CMAKE_PROJECT_NAME})
set(STATIC_LIBS randomx)
if (WITH_RANDOMX)
set(STATIC_LIBS randomx)
endif()
if (NOT APPLE)
set(STATIC_LIBS ${STATIC_LIBS} pthread dl)
endif()
+1 -1
View File
@@ -2,7 +2,7 @@
Decentralized pool for Monero mining.
Pool status and monitoring pages can be found at https://p2pool.io/ and https://p2pool.observer/
Pool status and monitoring pages can be found at https://p2pool.io/, https://p2pool.io/mini/ and https://p2pool.observer/
### Build Status
+1 -1
View File
@@ -5,7 +5,7 @@
// Fixed difficulty for miners that connect to your node must be set in their config.json
//
{
"name": "mainnet test 2",
"name": "default",
"password": "",
"block_time": 10,
"min_diff": 100000,
+3 -2
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -154,6 +154,7 @@ struct BlockCache::Impl : public nocopy_nomove
BlockCache::BlockCache()
: m_impl(new Impl())
, m_flushRunning(0)
, m_storeIndex(0)
{
}
@@ -171,7 +172,7 @@ void BlockCache::store(const PoolBlock& block)
return;
}
uint8_t* data = m_impl->m_data + (static_cast<size_t>(block.m_sidechainHeight % NUM_BLOCKS) * BLOCK_SIZE);
uint8_t* data = m_impl->m_data + (static_cast<size_t>((m_storeIndex++) % NUM_BLOCKS) * BLOCK_SIZE);
*reinterpret_cast<uint32_t*>(data) = static_cast<uint32_t>(n1 + n2);
memcpy(data + sizeof(uint32_t), block.m_mainChainData.data(), n1);
+2 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,6 +37,7 @@ private:
struct Impl;
Impl* m_impl;
std::atomic<uint32_t> m_flushRunning;
std::atomic<uint32_t> m_storeIndex;
};
} // namespace p2pool
+81 -18
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
* Portions Copyright (c) 2012-2013 The Cryptonote developers
* Portions Copyright (c) 2014-2021 The Monero Project
* Portions Copyright (c) 2021 XMRig <https://github.com/xmrig>
@@ -190,12 +190,17 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet
++m_templateId;
// When block template generation fails for any reason
auto use_old_template = [this]() {
const uint32_t id = m_templateId - 1;
LOGWARN(4, "using old block template with ID = " << id);
*this = *m_oldTemplates[id % array_size(&BlockTemplate::m_oldTemplates)];
};
m_height = data.height;
m_difficulty = data.difficulty;
m_seedHash = data.seed_hash;
const time_t cur_time = time(nullptr);
// Only choose transactions that were received 10 or more seconds ago
size_t total_mempool_transactions;
{
@@ -205,6 +210,8 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet
total_mempool_transactions = mempool.m_transactions.size();
const uint64_t cur_time = seconds_since_epoch();
for (auto& it : mempool.m_transactions) {
if (cur_time >= it.second.time_received + 10) {
m_mempoolTxs.emplace_back(it.second);
@@ -252,7 +259,7 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet
m_poolBlockTemplate->m_minorVersion = HARDFORK_SUPPORTED_VERSION;
// Timestamp
m_timestamp = cur_time;
m_timestamp = time(nullptr);
if (m_timestamp <= data.median_timestamp) {
LOGWARN(2, "timestamp adjusted from " << m_timestamp << " to " << data.median_timestamp + 1 << ". Fix your system time!");
m_timestamp = data.median_timestamp + 1;
@@ -275,21 +282,26 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet
m_pool->side_chain().fill_sidechain_data(*m_poolBlockTemplate, miner_wallet, m_txkeySec, m_shares);
if (!SideChain::split_reward(max_reward, m_shares, m_rewards)) {
use_old_template();
return;
}
const uint64_t max_reward_amounts_weight = std::accumulate(m_rewards.begin(), m_rewards.end(), 0ULL,
[](uint64_t a, uint64_t b)
{
writeVarint(b, [&a](uint8_t) { ++a; });
return a;
});
auto get_reward_amounts_weight = [this]() {
return std::accumulate(m_rewards.begin(), m_rewards.end(), 0ULL,
[](uint64_t a, uint64_t b)
{
writeVarint(b, [&a](uint8_t) { ++a; });
return a;
});
};
uint64_t max_reward_amounts_weight = get_reward_amounts_weight();
if (!create_miner_tx(data, m_shares, max_reward_amounts_weight, true)) {
if (create_miner_tx(data, m_shares, max_reward_amounts_weight, true) < 0) {
use_old_template();
return;
}
const uint64_t miner_tx_weight = m_minerTx.size();
uint64_t miner_tx_weight = m_minerTx.size();
// Select transactions from the mempool
uint64_t final_reward, final_fees, final_weight;
@@ -427,17 +439,64 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet
}
if (!SideChain::split_reward(final_reward, m_shares, m_rewards)) {
use_old_template();
return;
}
m_finalReward = final_reward;
if (!create_miner_tx(data, m_shares, max_reward_amounts_weight, false)) {
return;
const int create_miner_tx_result = create_miner_tx(data, m_shares, max_reward_amounts_weight, false);
if (create_miner_tx_result < 0) {
if (create_miner_tx_result == -3) {
// Too many extra bytes were added, refine max_reward_amounts_weight and miner_tx_weight
LOGINFO(4, "Readjusting miner_tx to reduce extra nonce size");
// The difference between max possible reward and the actual reward can't reduce the size of output amount varints by more than 1 byte each
// So block weight will be >= current weight - number of outputs
const uint64_t w = (final_weight > m_rewards.size()) ? (final_weight - m_rewards.size()) : 0;
// Block reward will be <= r due to how block size penalty works
const uint64_t r = get_block_reward(base_reward, data.median_weight, final_fees, w);
if (!SideChain::split_reward(r, m_shares, m_rewards)) {
use_old_template();
return;
}
max_reward_amounts_weight = get_reward_amounts_weight();
if (create_miner_tx(data, m_shares, max_reward_amounts_weight, true) < 0) {
use_old_template();
return;
}
final_weight -= miner_tx_weight;
final_weight += m_minerTx.size();
miner_tx_weight = m_minerTx.size();
final_reward = get_block_reward(base_reward, data.median_weight, final_fees, final_weight);
if (!SideChain::split_reward(final_reward, m_shares, m_rewards)) {
use_old_template();
return;
}
if (create_miner_tx(data, m_shares, max_reward_amounts_weight, false) < 0) {
use_old_template();
return;
}
LOGINFO(4, "New extra nonce size = " << m_poolBlockTemplate->m_extraNonceSize);
}
else {
use_old_template();
return;
}
}
if (m_minerTx.size() != miner_tx_weight) {
LOGERR(1, "miner tx size changed after adjusting reward");
use_old_template();
return;
}
@@ -600,7 +659,7 @@ void BlockTemplate::fill_optimal_knapsack(const MinerData& data, uint64_t base_r
}
#endif
bool BlockTemplate::create_miner_tx(const MinerData& data, const std::vector<MinerShare>& shares, uint64_t max_reward_amounts_weight, bool dry_run)
int BlockTemplate::create_miner_tx(const MinerData& data, const std::vector<MinerShare>& shares, uint64_t max_reward_amounts_weight, bool dry_run)
{
// Miner transaction (coinbase)
m_minerTx.clear();
@@ -655,12 +714,12 @@ bool BlockTemplate::create_miner_tx(const MinerData& data, const std::vector<Min
if (dry_run) {
if (reward_amounts_weight != max_reward_amounts_weight) {
LOGERR(1, "create_miner_tx: incorrect miner rewards during the dry run (" << reward_amounts_weight << " != " << max_reward_amounts_weight << ")");
return false;
return -1;
}
}
else if (reward_amounts_weight > max_reward_amounts_weight) {
LOGERR(1, "create_miner_tx: incorrect miner rewards during the real run (" << reward_amounts_weight << " > " << max_reward_amounts_weight << ")");
return false;
return -2;
}
m_poolBlockTemplate->m_txkeyPub = m_txkeyPub;
@@ -676,6 +735,10 @@ bool BlockTemplate::create_miner_tx(const MinerData& data, const std::vector<Min
const uint64_t corrected_extra_nonce_size = EXTRA_NONCE_SIZE + max_reward_amounts_weight - reward_amounts_weight;
if (corrected_extra_nonce_size > EXTRA_NONCE_SIZE) {
if (corrected_extra_nonce_size > EXTRA_NONCE_MAX_SIZE) {
LOGWARN(4, "create_miner_tx: corrected_extra_nonce_size (" << corrected_extra_nonce_size << ") is too large");
return -3;
}
LOGINFO(4, "increased EXTRA_NONCE from " << EXTRA_NONCE_SIZE << " to " << corrected_extra_nonce_size << " bytes to maintain miner tx weight");
}
writeVarint(corrected_extra_nonce_size, m_minerTxExtra);
@@ -701,7 +764,7 @@ bool BlockTemplate::create_miner_tx(const MinerData& data, const std::vector<Min
// Not a part of transaction hash data
m_minerTx.push_back(0);
return true;
return 1;
}
hash BlockTemplate::calc_sidechain_hash() const
+3 -3
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -50,7 +50,7 @@ public:
void update_tx_keys();
FORCEINLINE uint64_t height() const { return m_height; }
FORCEINLINE time_t timestamp() const { return m_timestamp; }
FORCEINLINE uint64_t timestamp() const { return m_timestamp; }
FORCEINLINE difficulty_type difficulty() const { return m_difficulty; }
void submit_sidechain_block(uint32_t template_id, uint32_t nonce, uint32_t extra_nonce);
@@ -61,7 +61,7 @@ private:
p2pool* m_pool;
private:
bool create_miner_tx(const MinerData& data, const std::vector<MinerShare>& shares, uint64_t max_reward_amounts_weight, bool dry_run);
int create_miner_tx(const MinerData& data, const std::vector<MinerShare>& shares, uint64_t max_reward_amounts_weight, bool dry_run);
hash calc_sidechain_hash() const;
hash calc_miner_tx_hash(uint32_t extra_nonce) const;
void calc_merkle_tree_main_branch();
+5 -3
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -54,6 +54,7 @@
#include <atomic>
#include <chrono>
#include <iostream>
#include <random>
#include <signal.h>
@@ -84,6 +85,7 @@ constexpr uint8_t HARDFORK_SUPPORTED_VERSION = 14;
constexpr uint8_t MINER_REWARD_UNLOCK_TIME = 60;
constexpr uint8_t NONCE_SIZE = 4;
constexpr uint8_t EXTRA_NONCE_SIZE = 4;
constexpr uint8_t EXTRA_NONCE_MAX_SIZE = EXTRA_NONCE_SIZE + 10;
constexpr uint8_t TX_VERSION = 2;
constexpr uint8_t TXIN_GEN = 0xFF;
constexpr uint8_t TXOUT_TO_KEY = 2;
@@ -234,7 +236,7 @@ struct TxMempoolData
uint64_t blob_size;
uint64_t weight;
uint64_t fee;
time_t time_received;
uint64_t time_received;
};
struct MinerData
@@ -260,7 +262,7 @@ struct MinerData
uint64_t median_timestamp;
std::vector<TxMempoolData> tx_backlog;
std::chrono::system_clock::time_point time_received;
std::chrono::high_resolution_clock::time_point time_received;
};
struct ChainMain
+14 -2
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021 hyc <https://github.com/hyc>
*
* This program is free software: you can redistribute it and/or modify
@@ -21,7 +21,9 @@
#include "p2pool.h"
#include "stratum_server.h"
#include "p2p_server.h"
#ifdef WITH_RANDOMX
#include "miner.h"
#endif
#include "side_chain.h"
#include <iostream>
@@ -70,7 +72,11 @@ typedef struct cmd {
cmdfunc *func;
} cmd;
static cmdfunc do_help, do_status, do_loglevel, do_addpeers, do_droppeers, do_showpeers, do_showbans, do_outpeers, do_inpeers, do_start_mining, do_stop_mining, do_exit;
static cmdfunc do_help, do_status, do_loglevel, do_addpeers, do_droppeers, do_showpeers, do_showbans, do_outpeers, do_inpeers, do_exit;
#ifdef WITH_RANDOMX
static cmdfunc do_start_mining, do_stop_mining;
#endif
static cmd cmds[] = {
{ STRCONST("help"), "", "display list of commands", do_help },
@@ -82,8 +88,10 @@ static cmd cmds[] = {
{ STRCONST("bans"), "", "show all banned IPs", do_showbans },
{ STRCONST("outpeers"), "", "set maximum number of outgoing connections", do_outpeers },
{ STRCONST("inpeers"), "", "set maximum number of incoming connections", do_inpeers },
#ifdef WITH_RANDOMX
{ STRCONST("start_mining"), "<threads>", "start mining", do_start_mining },
{ STRCONST("stop_mining"), "", "stop mining", do_stop_mining },
#endif
{ STRCONST("exit"), "", "terminate p2pool", do_exit },
{ STRCNULL, NULL, NULL, NULL }
};
@@ -106,9 +114,11 @@ static int do_status(p2pool *m_pool, const char * /* args */)
if (m_pool->p2p_server()) {
m_pool->p2p_server()->print_status();
}
#ifdef WITH_RANDOMX
if (m_pool->miner()) {
m_pool->miner()->print_status();
}
#endif
bkg_jobs_tracker.print_status();
return 0;
}
@@ -175,6 +185,7 @@ static int do_inpeers(p2pool* m_pool, const char* args)
return 0;
}
#ifdef WITH_RANDOMX
static int do_start_mining(p2pool* m_pool, const char* args)
{
uint32_t threads = strtoul(args, nullptr, 10);
@@ -188,6 +199,7 @@ static int do_stop_mining(p2pool* m_pool, const char* /*args*/)
m_pool->stop_mining();
return 0;
}
#endif
static int do_exit(p2pool *m_pool, const char * /* args */)
{
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+2 -19
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,7 +19,6 @@
#include "crypto.h"
#include "keccak.h"
#include "uv_util.h"
#include <random>
extern "C" {
#include "crypto-ops.h"
@@ -32,7 +31,7 @@ namespace {
class RandomBytes
{
public:
RandomBytes() : rng(s), dist(0, 255)
RandomBytes() : rng(RandomDeviceSeed::instance), dist(0, 255)
{
uv_mutex_init_checked(&m);
@@ -57,22 +56,6 @@ public:
private:
uv_mutex_t m;
// Fills the whole initial MT19937-64 state with non-deterministic random numbers
struct SeedSequence
{
using result_type = std::random_device::result_type;
template<typename T>
static void generate(T begin, T end)
{
std::random_device rd;
for (T i = begin; i != end; ++i) {
*i = rd();
}
}
};
SeedSequence s;
std::mt19937_64 rng;
std::uniform_int_distribution<> dist;
};
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+13 -9
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -48,17 +48,21 @@ NOINLINE void keccakf(uint64_t* st)
bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
for (int i = 0; i < 5; ++i) {
uint64_t t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
st[i + 0 ] ^= t;
st[i + 5] ^= t;
st[i + 10] ^= t;
st[i + 15] ^= t;
st[i + 20] ^= t;
#define X(i) { \
const uint64_t t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); \
st[i + 0 ] ^= t; \
st[i + 5] ^= t; \
st[i + 10] ^= t; \
st[i + 15] ^= t; \
st[i + 20] ^= t; \
}
X(0); X(1); X(2); X(3); X(4);
#undef X
// Rho Pi
uint64_t t = st[1];
const uint64_t t = st[1];
st[ 1] = ROTL64(st[ 6], 44);
st[ 6] = ROTL64(st[ 9], 20);
st[ 9] = ROTL64(st[22], 61);
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+2 -2
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@ void Mempool::add(const TxMempoolData& tx)
void Mempool::swap(std::vector<TxMempoolData>& transactions)
{
const time_t cur_time = time(nullptr);
const uint64_t cur_time = seconds_since_epoch();
WriteLock lock(m_lock);
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+2 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -41,6 +41,7 @@ Miner::Miner(p2pool* pool, uint32_t threads)
, m_nonceTimestamp(m_startTimestamp)
, m_extraNonce(0xF19E3779U)
, m_totalHashes(0)
, m_sharesFound(0)
, m_job{}
, m_jobIndex(0)
{
+3 -3
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -51,10 +51,10 @@ private:
std::vector<WorkerData*> m_minerThreads;
volatile bool m_stopped;
std::chrono::time_point<std::chrono::high_resolution_clock> m_startTimestamp;
std::chrono::high_resolution_clock::time_point m_startTimestamp;
std::atomic<uint32_t> m_nonce;
std::chrono::time_point<std::chrono::high_resolution_clock> m_nonceTimestamp;
std::chrono::high_resolution_clock::time_point m_nonceTimestamp;
const uint32_t m_extraNonce;
uint64_t m_totalHashes;
+71 -39
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -47,15 +47,19 @@ P2PServer::P2PServer(p2pool* pool)
, m_cache(pool->params().m_blockCache ? new BlockCache() : nullptr)
, m_cacheLoaded(false)
, m_initialPeerList(pool->params().m_p2pPeerList)
, m_rd{}
, m_rng(m_rd())
, m_cachedBlocks(nullptr)
, m_rng(RandomDeviceSeed::instance)
, m_block(new PoolBlock())
, m_timer{}
, m_timerCounter(0)
, m_timerInterval(2)
, m_peerId(m_rng())
, m_peerListLastSaved(0)
{
// Diffuse the initial state in case it has low quality
m_rng.discard(10000);
m_peerId = m_rng();
set_max_outgoing_peers(pool->params().m_maxOutgoingPeers);
set_max_incoming_peers(pool->params().m_maxIncomingPeers);
@@ -125,18 +129,34 @@ void P2PServer::add_cached_block(const PoolBlock& block)
return;
}
PoolBlock* new_block = new PoolBlock(block);
m_cachedBlocks.insert({ new_block->m_sidechainId, new_block });
if (!m_cachedBlocks) {
m_cachedBlocks = new unordered_map<hash, PoolBlock*>();
}
if (m_cachedBlocks->find(block.m_sidechainId) == m_cachedBlocks->end()) {
PoolBlock* new_block = new PoolBlock(block);
m_cachedBlocks->insert({ new_block->m_sidechainId, new_block });
}
}
void P2PServer::clear_cached_blocks()
{
if (!m_cachedBlocks) {
return;
}
WriteLock lock(m_cachedBlocksLock);
for (auto it : m_cachedBlocks) {
if (!m_cachedBlocks) {
return;
}
for (auto it : *m_cachedBlocks) {
delete it.second;
}
m_cachedBlocks.clear();
delete m_cachedBlocks;
m_cachedBlocks = nullptr;
}
void P2PServer::store_in_cache(const PoolBlock& block)
@@ -174,8 +194,8 @@ void P2PServer::on_connect_failed(bool is_v6, const raw_ip& ip, int port)
void P2PServer::update_peer_connections()
{
const time_t cur_time = time(nullptr);
const time_t last_updated = m_pool->side_chain().last_updated();
const uint64_t cur_time = seconds_since_epoch();
const uint64_t last_updated = m_pool->side_chain().last_updated();
bool has_good_peers = false;
@@ -200,7 +220,7 @@ void P2PServer::update_peer_connections()
// - 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;
const uint64_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);
@@ -282,6 +302,7 @@ void P2PServer::update_peer_connections()
void P2PServer::update_peer_list()
{
const uint64_t cur_time = seconds_since_epoch();
{
MutexLock lock(m_clientsListLock);
@@ -290,9 +311,9 @@ void P2PServer::update_peer_list()
continue;
}
if (m_timerCounter >= client->m_nextOutgoingPeerListRequest) {
if (cur_time >= client->m_nextOutgoingPeerListRequest) {
// Send peer list requests at random intervals (60-120 seconds)
client->m_nextOutgoingPeerListRequest = m_timerCounter + (60 + (get_random64() % 61)) / m_timerInterval;
client->m_nextOutgoingPeerListRequest = cur_time + (60 + (get_random64() % 61));
const bool result = send(client,
[](void* buf)
@@ -313,7 +334,7 @@ void P2PServer::update_peer_list()
void P2PServer::save_peer_list_async()
{
const time_t cur_time = time(nullptr);
const uint64_t cur_time = seconds_since_epoch();
if (cur_time < m_peerListLastSaved + 300) {
return;
}
@@ -386,7 +407,7 @@ void P2PServer::save_peer_list()
f.close();
LOGINFO(5, "peer list saved (" << peer_list.size() << " peers)");
m_peerListLastSaved = time(nullptr);
m_peerListLastSaved = seconds_since_epoch();
}
void P2PServer::load_peer_list()
@@ -510,7 +531,7 @@ void P2PServer::load_peer_list()
p.m_port = port;
p.m_numFailedConnections = 0;
p.m_lastSeen = time(nullptr);
p.m_lastSeen = seconds_since_epoch();
if (!already_added && !is_banned(p.m_addr)) {
m_peerList.push_back(p);
@@ -617,7 +638,7 @@ void P2PServer::load_monerod_peer_list()
void P2PServer::update_peer_in_list(bool is_v6, const raw_ip& ip, int port)
{
const time_t cur_time = time(nullptr);
const uint64_t cur_time = seconds_since_epoch();
MutexLock lock(m_peerListLock);
@@ -814,7 +835,7 @@ uint64_t P2PServer::get_random64()
void P2PServer::print_status()
{
const int64_t uptime = time(nullptr) - m_pool->start_time();
const int64_t uptime = seconds_since_epoch() - m_pool->start_time();
const int64_t s = uptime % 60;
const int64_t m = (uptime / 60) % 60;
@@ -930,12 +951,14 @@ void P2PServer::download_missing_blocks()
return;
}
ReadLock lock2(m_cachedBlocksLock);
// Try to download each block from a random client
for (const hash& id : missing_blocks) {
P2PClient* client = clients[get_random64() % clients.size()];
{
MutexLock lock2(m_missingBlockRequestsLock);
MutexLock lock3(m_missingBlockRequestsLock);
const uint64_t truncated_block_id = *reinterpret_cast<const uint64_t*>(id.h);
if (!m_missingBlockRequests.insert({ client->m_peerId, truncated_block_id }).second) {
@@ -945,6 +968,15 @@ void P2PServer::download_missing_blocks()
}
}
if (m_cachedBlocks) {
auto it = m_cachedBlocks->find(id);
if (it != m_cachedBlocks->end()) {
LOGINFO(5, "using cached block for id = " << id);
client->handle_incoming_block_async(it->second);
continue;
}
}
const bool result = send(client,
[&id](void* buf)
{
@@ -972,8 +1004,8 @@ void P2PServer::check_zmq()
return;
}
const time_t cur_time = time(nullptr);
const time_t last_active = m_pool->zmq_last_active();
const uint64_t cur_time = seconds_since_epoch();
const uint64_t last_active = m_pool->zmq_last_active();
if (cur_time >= last_active + 300) {
const uint64_t dt = static_cast<uint64_t>(cur_time - last_active);
@@ -990,7 +1022,7 @@ P2PServer::P2PClient::P2PClient()
, m_handshakeInvalid(false)
, m_listenPort(-1)
, m_fastPeerListRequestCount(0)
, m_prevIncomingPeerListRequest{}
, m_prevIncomingPeerListRequest(0)
, m_nextOutgoingPeerListRequest(0)
, m_lastPeerListRequestTime{}
, m_peerListPendingRequests(0)
@@ -1019,7 +1051,7 @@ void P2PServer::P2PClient::reset()
m_handshakeInvalid = false;
m_listenPort = -1;
m_fastPeerListRequestCount = 0;
m_prevIncomingPeerListRequest = {};
m_prevIncomingPeerListRequest = 0;
m_nextOutgoingPeerListRequest = 0;
m_lastPeerListRequestTime = {};
m_peerListPendingRequests = 0;
@@ -1057,7 +1089,7 @@ bool P2PServer::P2PClient::on_connect()
}
}
m_lastAlive = time(nullptr);
m_lastAlive = seconds_since_epoch();
return send_handshake_challenge();
}
@@ -1273,7 +1305,7 @@ bool P2PServer::P2PClient::on_read(char* data, uint32_t size)
if (bytes_read) {
buf += bytes_read;
bytes_left -= bytes_read;
m_lastAlive = time(nullptr);
m_lastAlive = seconds_since_epoch();
}
} while (bytes_read && bytes_left);
@@ -1608,7 +1640,7 @@ void P2PServer::P2PClient::on_after_handshake(uint8_t* &p)
p += HASH_SIZE;
++m_blockPendingRequests;
m_lastBroadcastTimestamp = time(nullptr);
m_lastBroadcastTimestamp = seconds_since_epoch();
}
bool P2PServer::P2PClient::on_listen_port(const uint8_t* buf)
@@ -1629,7 +1661,7 @@ bool P2PServer::P2PClient::on_listen_port(const uint8_t* buf)
bool P2PServer::P2PClient::on_block_request(const uint8_t* buf)
{
m_lastBlockrequestTimestamp = time(nullptr);
m_lastBlockrequestTimestamp = seconds_since_epoch();
hash id;
memcpy(id.h, buf, HASH_SIZE);
@@ -1709,7 +1741,7 @@ bool P2PServer::P2PClient::on_block_broadcast(const uint8_t* buf, uint32_t size)
if (peer_height < our_height) {
if (our_height - peer_height < 5) {
using namespace std::chrono;
const int64_t elapsed_ms = duration_cast<milliseconds>(system_clock::now() - miner_data.time_received).count();
const int64_t elapsed_ms = duration_cast<milliseconds>(high_resolution_clock::now() - miner_data.time_received).count();
if (our_height - peer_height > 1) {
LOGWARN(5, "peer " << static_cast<char*>(m_addrString) << " broadcasted a stale block (" << elapsed_ms << " ms late, mainchain height " << peer_height << ", expected >= " << our_height << "), ignoring it");
return true;
@@ -1735,20 +1767,18 @@ bool P2PServer::P2PClient::on_block_broadcast(const uint8_t* buf, uint32_t size)
server->m_block->m_wantBroadcast = true;
m_lastBroadcastTimestamp = time(nullptr);
m_lastBroadcastTimestamp = seconds_since_epoch();
return handle_incoming_block_async(server->m_block);
}
bool P2PServer::P2PClient::on_peer_list_request(const uint8_t*)
{
using namespace std::chrono;
P2PServer* server = static_cast<P2PServer*>(m_owner);
const auto cur_time = steady_clock::now();
const uint64_t cur_time = seconds_since_epoch();
// Allow peer list requests no more than once every 30 seconds
if (duration_cast<seconds>(cur_time - m_prevIncomingPeerListRequest).count() < 30) {
if (cur_time - m_prevIncomingPeerListRequest < 30) {
++m_fastPeerListRequestCount;
if (m_fastPeerListRequestCount >= 3) {
LOGWARN(4, "peer " << log::Gray() << static_cast<char*>(m_addrString) << log::NoColor() << " is sending PEER_LIST_REQUEST too often");
@@ -1819,7 +1849,7 @@ bool P2PServer::P2PClient::on_peer_list_request(const uint8_t*)
bool P2PServer::P2PClient::on_peer_list_response(const uint8_t* buf) const
{
P2PServer* server = static_cast<P2PServer*>(m_owner);
const time_t cur_time = time(nullptr);
const uint64_t cur_time = seconds_since_epoch();
MutexLock lock(server->m_peerListLock);
@@ -1942,11 +1972,13 @@ void P2PServer::P2PClient::post_handle_incoming_block(const uint32_t reset_count
ReadLock lock(server->m_cachedBlocksLock);
for (const hash& id : missing_blocks) {
auto it = server->m_cachedBlocks.find(id);
if (it != server->m_cachedBlocks.end()) {
LOGINFO(5, "using cached block for id = " << id);
handle_incoming_block_async(it->second);
continue;
if (server->m_cachedBlocks) {
auto it = server->m_cachedBlocks->find(id);
if (it != server->m_cachedBlocks->end()) {
LOGINFO(5, "using cached block for id = " << id);
handle_incoming_block_async(it->second);
continue;
}
}
const bool result = m_owner->send(this,
+8 -10
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,7 +18,6 @@
#pragma once
#include "tcp_server.h"
#include <random>
namespace p2pool {
@@ -111,7 +110,7 @@ public:
int m_listenPort;
uint32_t m_fastPeerListRequestCount;
std::chrono::steady_clock::time_point m_prevIncomingPeerListRequest;
uint64_t m_prevIncomingPeerListRequest;
uint64_t m_nextOutgoingPeerListRequest;
std::chrono::high_resolution_clock::time_point m_lastPeerListRequestTime;
int m_peerListPendingRequests;
@@ -119,9 +118,9 @@ public:
int m_blockPendingRequests;
time_t m_lastAlive;
time_t m_lastBroadcastTimestamp;
time_t m_lastBlockrequestTimestamp;
uint64_t m_lastAlive;
uint64_t m_lastBroadcastTimestamp;
uint64_t m_lastBlockrequestTimestamp;
hash m_broadcastedHashes[8];
std::atomic<uint32_t> m_broadcastedHashesIndex{ 0 };
@@ -150,7 +149,7 @@ private:
uint32_t m_maxIncomingPeers;
uv_rwlock_t m_cachedBlocksLock;
unordered_map<hash, PoolBlock*> m_cachedBlocks;
unordered_map<hash, PoolBlock*>* m_cachedBlocks;
private:
static void on_timer(uv_timer_t* timer) { reinterpret_cast<P2PServer*>(timer->data)->on_timer(); }
@@ -170,7 +169,6 @@ private:
void remove_peer_from_list(const raw_ip& ip);
uv_mutex_t m_rngLock;
std::random_device m_rd;
std::mt19937_64 m_rng;
uv_mutex_t m_blockLock;
@@ -190,12 +188,12 @@ private:
raw_ip m_addr;
int m_port;
uint32_t m_numFailedConnections;
time_t m_lastSeen;
uint64_t m_lastSeen;
};
std::vector<Peer> m_peerList;
std::vector<Peer> m_peerListMonero;
time_t m_peerListLastSaved;
uint64_t m_peerListLastSaved;
struct Broadcast
{
+20 -6
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,7 +27,9 @@
#include "side_chain.h"
#include "stratum_server.h"
#include "p2p_server.h"
#ifdef WITH_RANDOMX
#include "miner.h"
#endif
#include "params.h"
#include "console_commands.h"
#include "crypto.h"
@@ -52,7 +54,7 @@ p2pool::p2pool(int argc, char* argv[])
, m_updateSeed(true)
, m_submitBlockData{}
, m_zmqLastActive(0)
, m_startTime(time(nullptr))
, m_startTime(seconds_since_epoch())
{
LOGINFO(1, log::LightCyan() << VERSION);
@@ -128,12 +130,16 @@ p2pool::p2pool(int argc, char* argv[])
m_params->m_p2pAddresses = buf;
}
#ifdef WITH_RANDOMX
if (m_params->m_disableRandomX) {
m_hasher = new RandomX_Hasher_RPC(this);
}
else {
m_hasher = new RandomX_Hasher(this);
}
#else
m_hasher = new RandomX_Hasher_RPC(this);
#endif
m_blockTemplate = new BlockTemplate(this);
m_mempool = new Mempool();
@@ -200,7 +206,7 @@ void p2pool::handle_tx(TxMempoolData& tx)
m_blockTemplate->update(m_minerData, *m_mempool, &m_params->m_wallet);
#endif
m_zmqLastActive = time(nullptr);
m_zmqLastActive = seconds_since_epoch();
}
void p2pool::handle_miner_data(MinerData& data)
@@ -232,7 +238,7 @@ void p2pool::handle_miner_data(MinerData& data)
}
data.tx_backlog.clear();
data.time_received = std::chrono::system_clock::now();
data.time_received = std::chrono::high_resolution_clock::now();
m_minerData = data;
m_updateSeed = true;
update_median_timestamp();
@@ -257,7 +263,7 @@ void p2pool::handle_miner_data(MinerData& data)
update_block_template();
}
m_zmqLastActive = time(nullptr);
m_zmqLastActive = seconds_since_epoch();
if (m_serversStarted.load()) {
std::vector<uint64_t> missing_heights;
@@ -361,7 +367,7 @@ void p2pool::handle_chain_main(ChainMain& data, const char* extra)
api_update_network_stats();
m_zmqLastActive = time(nullptr);
m_zmqLastActive = seconds_since_epoch();
}
void p2pool::submit_block_async(uint32_t template_id, uint32_t nonce, uint32_t extra_nonce)
@@ -602,9 +608,11 @@ void p2pool::download_block_headers(uint64_t current_height)
m_ZMQReader = new ZMQReader(m_params->m_host.c_str(), m_params->m_zmqPort, this);
m_stratumServer = new StratumServer(this);
m_p2pServer = new P2PServer(this);
#ifdef WITH_RANDOMX
if (m_params->m_minerThreads) {
start_mining(m_params->m_minerThreads);
}
#endif
api_update_network_stats();
}
}
@@ -671,9 +679,11 @@ void p2pool::update_median_timestamp()
void p2pool::stratum_on_block()
{
#ifdef WITH_RANDOMX
if (m_miner) {
m_miner->on_block(*m_blockTemplate);
}
#endif
if (m_stratumServer) {
m_stratumServer->on_block(*m_blockTemplate);
}
@@ -1219,6 +1229,7 @@ bool p2pool::get_difficulty_at_height(uint64_t height, difficulty_type& diff)
return true;
}
#ifdef WITH_RANDOMX
void p2pool::start_mining(uint32_t threads)
{
stop_mining();
@@ -1233,6 +1244,7 @@ void p2pool::stop_mining()
delete miner;
}
}
#endif
static void on_signal(uv_signal_t* handle, int signum)
{
@@ -1342,7 +1354,9 @@ int p2pool::run()
bkg_jobs_tracker.wait();
#ifdef WITH_RANDOMX
delete m_miner;
#endif
delete m_stratumServer;
delete m_p2pServer;
+11 -5
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -59,7 +59,9 @@ public:
StratumServer* stratum_server() const { return m_stratumServer; }
P2PServer* p2p_server() const { return m_p2pServer; }
#ifdef WITH_RANDOMX
Miner* miner() const { return m_miner; }
#endif
virtual void handle_tx(TxMempoolData& tx) override;
virtual void handle_miner_data(MinerData& data) override;
@@ -80,11 +82,13 @@ public:
bool get_difficulty_at_height(uint64_t height, difficulty_type& diff);
#ifdef WITH_RANDOMX
void start_mining(uint32_t threads);
void stop_mining();
#endif
time_t zmq_last_active() const { return m_zmqLastActive; }
time_t start_time() const { return m_startTime; }
uint64_t zmq_last_active() const { return m_zmqLastActive; }
uint64_t start_time() const { return m_startTime; }
private:
p2pool(const p2pool&) = delete;
@@ -160,7 +164,9 @@ private:
std::atomic<uint32_t> m_serversStarted{ 0 };
StratumServer* m_stratumServer = nullptr;
P2PServer* m_p2pServer = nullptr;
#ifdef WITH_RANDOMX
Miner* m_miner = nullptr;
#endif
ConsoleCommands* m_consoleCommands;
@@ -179,8 +185,8 @@ private:
uv_async_t m_blockTemplateAsync;
uv_async_t m_stopAsync;
time_t m_zmqLastActive;
time_t m_startTime;
uint64_t m_zmqLastActive;
uint64_t m_startTime;
ZMQReader* m_ZMQReader = nullptr;
};
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+5 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -39,7 +39,11 @@ struct Params
std::string m_apiPath;
bool m_localStats = false;
bool m_blockCache = true;
#ifdef WITH_RANDOMX
bool m_disableRandomX = false;
#else
bool m_disableRandomX = true;
#endif
uint32_t m_maxOutgoingPeers = 10;
uint32_t m_maxIncomingPeers = 1000;
uint32_t m_minerThreads = 0;
+3 -3
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -53,7 +53,7 @@ PoolBlock::PoolBlock()
, m_invalid(false)
, m_broadcasted(false)
, m_wantBroadcast(false)
, m_localTimestamp(time(nullptr))
, m_localTimestamp(seconds_since_epoch())
{
uv_mutex_init_checked(&m_lock);
@@ -115,7 +115,7 @@ PoolBlock& PoolBlock::operator=(const PoolBlock& b)
m_broadcasted = b.m_broadcasted;
m_wantBroadcast = b.m_wantBroadcast;
m_localTimestamp = time(nullptr);
m_localTimestamp = seconds_since_epoch();
if (lock_result == 0) {
uv_mutex_unlock(&b.m_lock);
+2 -2
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -130,7 +130,7 @@ struct PoolBlock
bool m_broadcasted;
bool m_wantBroadcast;
time_t m_localTimestamp;
uint64_t m_localTimestamp;
void serialize_mainchain_data(uint32_t nonce, uint32_t extra_nonce, const hash& sidechain_hash);
void serialize_sidechain_data();
+3 -3
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -187,7 +187,7 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, SideChain& sidechai
READ_VARINT(m_extraNonceSize);
// Sanity check
if ((m_extraNonceSize < EXTRA_NONCE_SIZE) || (m_extraNonceSize > EXTRA_NONCE_SIZE + 10)) return __LINE__;
if ((m_extraNonceSize < EXTRA_NONCE_SIZE) || (m_extraNonceSize > EXTRA_NONCE_MAX_SIZE)) return __LINE__;
const int extra_nonce_offset = static_cast<int>((data - data_begin) + outputs_blob_size_diff);
READ_BUF(&m_extraNonce, EXTRA_NONCE_SIZE);
@@ -350,7 +350,7 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, SideChain& sidechai
m_broadcasted = false;
m_wantBroadcast = false;
m_localTimestamp = time(nullptr);
m_localTimestamp = seconds_since_epoch();
return 0;
}
+14 -2
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,9 +19,11 @@
#include "pow_hash.h"
#include "p2pool.h"
#include "params.h"
#ifdef WITH_RANDOMX
#include "randomx.h"
#include "configuration.h"
#include "virtual_machine.hpp"
#endif
#include "json_rpc_request.h"
#include "json_parsers.h"
#include <rapidjson/document.h>
@@ -31,6 +33,7 @@ static constexpr char log_category_prefix[] = "RandomX_Hasher ";
namespace p2pool {
#ifdef WITH_RANDOMX
RandomX_Hasher::RandomX_Hasher(p2pool* pool)
: m_pool(pool)
, m_cache{}
@@ -38,6 +41,7 @@ RandomX_Hasher::RandomX_Hasher(p2pool* pool)
, m_seed{}
, m_index(0)
, m_seedCounter(0)
, m_oldSeedCounter(0)
{
uint64_t memory_allocated = 0;
@@ -220,6 +224,11 @@ void RandomX_Hasher::set_seed(const hash& seed)
numThreads /= 2;
}
// wait for set_old_seed() before initializing dataset
while (m_oldSeedCounter.load() == 0) {
std::this_thread::yield();
}
LOGINFO(1, log::LightCyan() << "running " << numThreads << " threads to update dataset");
ReadLock lock2(m_cacheLock);
@@ -271,7 +280,7 @@ void RandomX_Hasher::set_old_seed(const hash& seed)
{
// set_seed() must go first, wait for it
while (m_seedCounter.load() == 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
std::this_thread::yield();
}
LOGINFO(1, "old seed " << log::LightBlue() << seed);
@@ -279,6 +288,8 @@ void RandomX_Hasher::set_old_seed(const hash& seed)
{
WriteLock lock(m_cacheLock);
m_oldSeedCounter.fetch_add(1);
const uint32_t old_index = m_index ^ 1;
m_seed[old_index] = seed;
@@ -357,6 +368,7 @@ bool RandomX_Hasher::calculate(const void* data, size_t size, uint64_t /*height*
return false;
}
#endif
RandomX_Hasher_RPC::RandomX_Hasher_RPC(p2pool* pool)
: m_pool(pool)
+4 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -43,6 +43,7 @@ public:
virtual bool calculate(const void* data, size_t size, uint64_t height, const hash& seed, hash& result) = 0;
};
#ifdef WITH_RANDOMX
class RandomX_Hasher : public RandomX_Hasher_Base
{
public:
@@ -89,7 +90,9 @@ private:
uint32_t m_index;
std::atomic<uint32_t> m_seedCounter;
std::atomic<uint32_t> m_oldSeedCounter;
};
#endif
class RandomX_Hasher_RPC : public RandomX_Hasher_Base
{
+46 -27
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,10 +21,12 @@
#include "pool_block.h"
#include "wallet.h"
#include "block_template.h"
#ifdef WITH_RANDOMX
#include "randomx.h"
#include "dataset.hpp"
#include "configuration.h"
#include "intrin_portable.h"
#endif
#include "keccak.h"
#include "p2p_server.h"
#include "stratum_server.h"
@@ -108,6 +110,7 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name)
m_consensusId.assign(mini_consensus_id, mini_consensus_id + HASH_SIZE);
}
else {
#ifdef WITH_RANDOMX
const randomx_flags flags = randomx_get_flags();
randomx_cache* cache = randomx_alloc_cache(flags | RANDOMX_FLAG_LARGE_PAGES);
if (!cache) {
@@ -142,6 +145,10 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name)
keccak(reinterpret_cast<uint8_t*>(scratchpad), static_cast<int>(scratchpad_size * sizeof(rx_vec_i128)), id.h, HASH_SIZE);
randomx_release_cache(cache);
m_consensusId.assign(id.h, id.h + HASH_SIZE);
#else
LOGERR(1, "Can't calculate consensus ID without RandomX library");
panic();
#endif
}
s.m_pos = 0;
@@ -149,7 +156,8 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name)
// Hide most consensus ID bytes, we only want it on screen to show that we're on the right sidechain
memset(buf + 8, '*', HASH_SIZE * 2 - 16);
LOGINFO(1, "consensus ID = " << log::LightCyan() << static_cast<char*>(buf));
m_consensusIdDisplayStr.assign(buf);
LOGINFO(1, "consensus ID = " << log::LightCyan() << m_consensusIdDisplayStr.c_str());
}
SideChain::~SideChain()
@@ -506,11 +514,6 @@ void SideChain::add_block(const PoolBlock& block)
", verified = " << (block.m_verified ? 1 : 0)
);
// Save it for faster syncing on the next p2pool start
if (p2pServer()) {
p2pServer()->store_in_cache(block);
}
PoolBlock* new_block = new PoolBlock(block);
MutexLock lock(m_sidechainLock);
@@ -533,6 +536,11 @@ void SideChain::add_block(const PoolBlock& block)
if (new_block->m_verified) {
if (!new_block->m_invalid) {
update_chain_tip(new_block);
// Save it for faster syncing on the next p2pool start
if (P2PServer* server = p2pServer()) {
server->store_in_cache(*new_block);
}
}
}
else {
@@ -738,31 +746,39 @@ void SideChain::print_status()
const uint64_t hashrate_est = total_reward ? udiv128(product[1], product[0], total_reward, &rem) : 0;
const double block_share = total_reward ? ((static_cast<double>(your_reward) * 100.0) / static_cast<double>(total_reward)) : 0.0;
uint32_t our_blocks_in_window_total = std::accumulate(our_blocks_in_window.begin(), our_blocks_in_window.end(), decltype(our_blocks_in_window)::value_type(0));
uint32_t our_uncles_in_window_total = std::accumulate(our_uncles_in_window.begin(), our_uncles_in_window.end(), decltype(our_uncles_in_window)::value_type(0));
const uint32_t our_blocks_in_window_total = std::accumulate(our_blocks_in_window.begin(), our_blocks_in_window.end(), 0U);
const uint32_t our_uncles_in_window_total = std::accumulate(our_uncles_in_window.begin(), our_uncles_in_window.end(), 0U);
std::string our_blocks_in_window_chart;
our_blocks_in_window_chart.reserve(our_blocks_in_window.size());
for(const auto& p : our_blocks_in_window){
our_blocks_in_window_chart += (p > 0 ? (p > 9 ? "+" : std::to_string(p)) : ".");
if (our_blocks_in_window_total) {
our_blocks_in_window_chart.reserve(our_blocks_in_window.size() + 32);
our_blocks_in_window_chart = "\nYour shares position = [";
for (uint32_t p : our_blocks_in_window) {
our_blocks_in_window_chart += (p ? ((p > 9) ? '+' : static_cast<char>('0' + p)) : '.');
}
our_blocks_in_window_chart += ']';
}
std::string our_uncles_in_window_chart;
our_uncles_in_window_chart.reserve(our_uncles_in_window.size());
for(const auto& p : our_uncles_in_window){
our_uncles_in_window_chart += (p > 0 ? (p > 9 ? "+" : std::to_string(p)) : ".");
if (our_uncles_in_window_total) {
our_uncles_in_window_chart.reserve(our_uncles_in_window.size() + 32);
our_uncles_in_window_chart = "\nYour uncles position = [";
for (uint32_t p : our_uncles_in_window) {
our_uncles_in_window_chart += (p ? ((p > 9) ? '+' : static_cast<char>('0' + p)) : '.');
}
our_uncles_in_window_chart += ']';
}
LOGINFO(0, "status" <<
"\nMain chain height = " << m_pool->block_template().height() <<
"\nMain chain hashrate = " << log::Hashrate(network_hashrate) <<
"\nSide chain ID = " << (is_default() ? "default" : (is_mini() ? "mini" : m_consensusIdDisplayStr.c_str())) <<
"\nSide chain height = " << tip_height + 1 <<
"\nSide chain hashrate = " << log::Hashrate(pool_hashrate) <<
(hashrate_est ? "\nYour hashrate (pool-side) = " : "") << (hashrate_est ? log::Hashrate(hashrate_est) : log::Hashrate()) <<
"\nPPLNS window = " << total_blocks_in_window << " blocks (+" << total_uncles_in_window << " uncles, " << total_orphans << " orphans)" <<
"\nYour shares = " << our_blocks_in_window_total << " blocks (+" << our_uncles_in_window_total << " uncles, " << our_orphans << " orphans)" <<
(our_blocks_in_window_total > 0 ? "\nYour shares position = " : "") << (our_blocks_in_window_total > 0 ? "[" + our_blocks_in_window_chart + "]" : "") <<
(our_uncles_in_window_total > 0 ? "\nYour uncles position = " : "") << (our_uncles_in_window_total > 0 ? "[" + our_uncles_in_window_chart + "]" : "") <<
"\nYour shares = " << our_blocks_in_window_total << " blocks (+" << our_uncles_in_window_total << " uncles, " << our_orphans << " orphans)"
<< our_blocks_in_window_chart << our_uncles_in_window_chart <<
"\nBlock reward share = " << block_share << "% (" << log::XMRAmount(your_reward) << ')'
);
}
@@ -774,7 +790,7 @@ difficulty_type SideChain::total_hashes() const
uint64_t SideChain::miner_count()
{
const time_t cur_time = time(nullptr);
const uint64_t cur_time = seconds_since_epoch();
MutexLock lock(m_sidechainLock);
@@ -791,7 +807,7 @@ uint64_t SideChain::miner_count()
return m_seenWallets.size();
}
time_t SideChain::last_updated() const
uint64_t SideChain::last_updated() const
{
return m_chainTip ? m_chainTip->m_localTimestamp : 0;
}
@@ -997,17 +1013,19 @@ void SideChain::verify_loop(PoolBlock* block)
", height " << block->m_sidechainHeight);
}
P2PServer* server = p2pServer();
// If it came through a broadcast, send it to our peers
if (block->m_wantBroadcast && !block->m_broadcasted) {
block->m_broadcasted = true;
if (p2pServer() && (block->m_depth < UNCLE_BLOCK_DEPTH)) {
p2pServer()->broadcast(*block);
if (server && (block->m_depth < UNCLE_BLOCK_DEPTH)) {
server->broadcast(*block);
}
}
// Save it for faster syncing on the next p2pool start
if (p2pServer()) {
p2pServer()->store_in_cache(*block);
if (server) {
server->store_in_cache(*block);
}
// Try to verify blocks on top of this one
@@ -1577,7 +1595,8 @@ void SideChain::prune_old_blocks()
const uint64_t prune_distance = m_chainWindowSize * 2 + 120 / m_targetBlockTime;
// Remove old blocks from alternative unconnected chains after long enough time
const time_t prune_time = time(nullptr) - m_chainWindowSize * 4 * m_targetBlockTime;
const uint64_t cur_time = seconds_since_epoch();
const uint64_t prune_delay = m_chainWindowSize * 4 * m_targetBlockTime;
if (m_chainTip->m_sidechainHeight < prune_distance) {
return;
@@ -1592,9 +1611,9 @@ void SideChain::prune_old_blocks()
std::vector<PoolBlock*>& v = it->second;
v.erase(std::remove_if(v.begin(), v.end(),
[this, prune_distance, prune_time, &num_blocks_pruned, height](PoolBlock* block)
[this, prune_distance, cur_time, prune_delay, &num_blocks_pruned, height](PoolBlock* block)
{
if ((block->m_depth >= prune_distance) || (block->m_localTimestamp <= prune_time)) {
if ((block->m_depth >= prune_distance) || (cur_time >= block->m_localTimestamp + prune_delay)) {
auto it2 = m_blocksById.find(block->m_sidechainId);
if (it2 != m_blocksById.end()) {
m_blocksById.erase(it2);
+4 -3
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -69,7 +69,7 @@ public:
difficulty_type total_hashes() const;
uint64_t block_time() const { return m_targetBlockTime; }
uint64_t miner_count();
time_t last_updated() const;
uint64_t last_updated() const;
bool is_default() const;
bool is_mini() const;
@@ -102,7 +102,7 @@ private:
PoolBlock* m_chainTip;
std::map<uint64_t, std::vector<PoolBlock*>> m_blocksByHeight;
unordered_map<hash, PoolBlock*> m_blocksById;
unordered_map<hash, time_t> m_seenWallets;
unordered_map<hash, uint64_t> m_seenWallets;
std::vector<MinerShare> m_tmpShares;
std::vector<uint64_t> m_tmpRewards;
@@ -119,6 +119,7 @@ private:
uint64_t m_unclePenalty;
std::vector<uint8_t> m_consensusId;
std::string m_consensusIdDisplayStr;
difficulty_type m_curDifficulty;
+12 -10
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -39,8 +39,7 @@ StratumServer::StratumServer(p2pool* pool)
: TCPServer(StratumClient::allocate)
, m_pool(pool)
, m_extraNonce(0)
, m_rd{}
, m_rng(m_rd())
, m_rng(RandomDeviceSeed::instance)
, m_cumulativeHashes(0)
, m_cumulativeHashesAtLastShare(0)
, m_hashrateDataHead(0)
@@ -51,7 +50,10 @@ StratumServer::StratumServer(p2pool* pool)
, m_totalFoundShares(0)
, m_apiLastUpdateTime(0)
{
m_hashrateData[0] = { time(nullptr), 0 };
// Diffuse the initial state in case it has low quality
m_rng.discard(10000);
m_hashrateData[0] = { seconds_since_epoch(), 0 };
uv_mutex_init_checked(&m_blobsQueueLock);
uv_mutex_init_checked(&m_rngLock);
@@ -435,7 +437,7 @@ uint64_t StratumServer::get_random64()
void StratumServer::print_status()
{
update_hashrate_data(0, time(nullptr));
update_hashrate_data(0, seconds_since_epoch());
print_stratum_status();
}
@@ -525,7 +527,7 @@ void StratumServer::on_blobs_ready()
size_t numClientsProcessed = 0;
uint32_t extra_nonce = 0;
const time_t cur_time = time(nullptr);
const uint64_t cur_time = seconds_since_epoch();
{
MutexLock lock2(m_clientsListLock);
@@ -603,7 +605,7 @@ void StratumServer::on_blobs_ready()
LOGINFO(3, "sent new job to " << extra_nonce << '/' << numClientsProcessed << " clients");
}
void StratumServer::update_hashrate_data(uint64_t hashes, time_t timestamp)
void StratumServer::update_hashrate_data(uint64_t hashes, uint64_t timestamp)
{
constexpr size_t N = array_size(&StratumServer::m_hashrateData);
@@ -705,7 +707,7 @@ void StratumServer::on_share_found(uv_work_t* req)
const uint64_t value = *reinterpret_cast<uint64_t*>(share->m_resultHash.h + HASH_SIZE - sizeof(uint64_t));
if (LIKELY(value < target)) {
const time_t timestamp = time(nullptr);
const uint64_t timestamp = seconds_since_epoch();
server->update_hashrate_data(hashes, timestamp);
server->api_update_local_stats(timestamp);
share->m_result = SubmittedShare::Result::OK;
@@ -801,7 +803,7 @@ void StratumServer::StratumClient::reset()
bool StratumServer::StratumClient::on_connect()
{
m_connectedTime = time(nullptr);
m_connectedTime = seconds_since_epoch();
return true;
}
@@ -991,7 +993,7 @@ bool StratumServer::StratumClient::process_submit(rapidjson::Document& doc, uint
return static_cast<StratumServer*>(m_owner)->on_submit(this, id, job_id.GetString(), nonce.GetString(), result.GetString());
}
void StratumServer::api_update_local_stats(time_t timestamp)
void StratumServer::api_update_local_stats(uint64_t timestamp)
{
if (!m_pool->api() || !m_pool->params().m_localStats) {
return;
+6 -8
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,7 +19,6 @@
#include "tcp_server.h"
#include <rapidjson/document.h>
#include <random>
namespace p2pool {
@@ -53,7 +52,7 @@ public:
bool process_submit(rapidjson::Document& doc, uint32_t id);
uint32_t m_rpcId;
time_t m_connectedTime;
uint64_t m_connectedTime;
uv_mutex_t m_jobsLock;
@@ -109,7 +108,6 @@ private:
std::atomic<uint32_t> m_extraNonce;
uv_mutex_t m_rngLock;
std::random_device m_rd;
std::mt19937_64 m_rng;
struct SubmittedShare
@@ -142,7 +140,7 @@ private:
struct HashrateData
{
time_t m_timestamp;
uint64_t m_timestamp;
uint64_t m_cumulativeHashes;
};
@@ -159,10 +157,10 @@ private:
double m_cumulativeFoundSharesDiff;
uint32_t m_totalFoundShares;
time_t m_apiLastUpdateTime;
uint64_t m_apiLastUpdateTime;
void update_hashrate_data(uint64_t hashes, time_t timestamp);
void api_update_local_stats(time_t timestamp);
void update_hashrate_data(uint64_t hashes, uint64_t timestamp);
void api_update_local_stats(uint64_t timestamp);
};
} // namespace p2pool
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+4 -2
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,7 +32,7 @@ namespace p2pool {
#define STR2(X) STR(X)
#define STR(X) #X
const char* VERSION = "v1.8 (built"
const char* VERSION = "v1.9 (built"
#if defined(__clang__)
" with clang/" __clang_version__
#elif defined(__GNUC__)
@@ -382,4 +382,6 @@ bool resolve_host(std::string& host, bool& is_v6)
return true;
}
RandomDeviceSeed RandomDeviceSeed::instance;
} // namespace p2pool
+25 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -145,6 +145,30 @@ using unordered_map = robin_hood::detail::Table<false, 80, Key, T, robin_hood::h
template <typename Key>
using unordered_set = robin_hood::detail::Table<false, 80, Key, void, robin_hood::hash<Key>, std::equal_to<Key>>;
// Fills the whole initial MT19937-64 state with non-deterministic random numbers
struct RandomDeviceSeed
{
using result_type = std::random_device::result_type;
static_assert(sizeof(result_type) >= 4, "result_type must have at least 32 bits");
template<typename T>
static void generate(T begin, T end)
{
std::random_device rd;
for (T i = begin; i != end; ++i) {
*i = rd();
}
}
static RandomDeviceSeed instance;
};
FORCEINLINE uint64_t seconds_since_epoch()
{
using namespace std::chrono;
return duration_cast<seconds>(steady_clock::now().time_since_epoch()).count();
}
} // namespace p2pool
namespace robin_hood {
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
* Portions Copyright (c) 2012-2013 The Cryptonote developers
* Portions Copyright (c) 2014-2021 The Monero Project
* Portions Copyright (c) 2021 XMRig <https://github.com/xmrig>
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+4 -5
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,7 +19,6 @@
#include "zmq_reader.h"
#include "json_parsers.h"
#include <rapidjson/document.h>
#include <random>
static constexpr char log_category_prefix[] = "ZMQReader ";
@@ -160,10 +159,10 @@ bool ZMQReader::connect(const char* address)
m_subscriber.connect(address);
using namespace std::chrono;
system_clock::time_point start_time = system_clock::now();
steady_clock::time_point start_time = steady_clock::now();
while (!monitor.connected && monitor.check_event(-1)) {
const system_clock::time_point cur_time = system_clock::now();
const steady_clock::time_point cur_time = steady_clock::now();
const int64_t elapsed_time = duration_cast<milliseconds>(cur_time - start_time).count();
if (elapsed_time >= 3000) {
LOGERR(1, "failed to connect to " << address);
@@ -208,7 +207,7 @@ void ZMQReader::parse(char* data, size_t size)
return;
}
m_tx.time_received = time(nullptr);
m_tx.time_received = seconds_since_epoch();
for (SizeType i = 0, n = doc.Size(); i < n; ++i) {
const auto& v = doc[i];
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+1
View File
@@ -19,6 +19,7 @@ set(LIBS gtest)
add_subdirectory(../external/src/RandomX RandomX)
set(LIBS ${LIBS} randomx)
add_definitions(-DWITH_RANDOMX)
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(WARNING_FLAGS "")
+4 -4
View File
@@ -254,7 +254,7 @@ TEST(difficulty_type, check_pow)
// Max hash value that passes this difficulty
memcpy(h.h, data, HASH_SIZE);
EXPECT_EQ(diff.check_pow(h), true);
ASSERT_EQ(diff.check_pow(h), true);
// Add 1 to data (256-bit number)
for (int j = 0; j <= 3; ++j) {
@@ -267,7 +267,7 @@ TEST(difficulty_type, check_pow)
// Min hash value that fails this difficulty
memcpy(h.h, data, HASH_SIZE);
EXPECT_EQ(diff.check_pow(h), false);
ASSERT_EQ(diff.check_pow(h), false);
}
const uint64_t target = diff.target();
@@ -276,14 +276,14 @@ TEST(difficulty_type, check_pow)
for (int j = 0; j < 10000; ++j) {
const uint64_t data[4] = { r(), r(), r(), r() % target };
memcpy(h.h, data, HASH_SIZE);
EXPECT_EQ(diff.check_pow(h), true);
ASSERT_EQ(diff.check_pow(h), true);
}
// Random values that fail
for (int j = 0; j < 10000; ++j) {
const uint64_t data[4] = { r(), r(), r(), target + (r() % (std::numeric_limits<uint64_t>::max() - target + 1)) };
memcpy(h.h, data, HASH_SIZE);
EXPECT_EQ(diff.check_pow(h), false);
ASSERT_EQ(diff.check_pow(h), false);
}
}
}