Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f3e96d7138 | |||
| 2b47218406 | |||
| c49f12b41d | |||
| 2eea660184 | |||
| 4b1c077b4a | |||
| de25ef0162 | |||
| ad49afb34b | |||
| 8aad4a16b3 | |||
| 8960365f82 | |||
| c967c84e0e | |||
| 61cc29a260 | |||
| cb3b4de1a5 | |||
| 127dcc04bf | |||
| cb8ea37dab | |||
| ebb6fe6942 | |||
| eb490d89c2 | |||
| 64a199be6d | |||
| b01ba2e116 | |||
| 0bada79b6b | |||
| 8894da4f93 | |||
| 37bf8554fc | |||
| ce6553863a | |||
| b16cf00dae |
@@ -423,11 +423,12 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {vs: Visual Studio 17 2022, os: 2022, vspath: "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise", rx: "ON", upnp: "ON", grpc: "ON"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, vspath: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise", rx: "ON", upnp: "ON", grpc: "ON"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, vspath: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise", rx: "ON", upnp: "ON", grpc: "OFF"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, vspath: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise", rx: "OFF", upnp: "ON", grpc: "OFF"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, vspath: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise", rx: "OFF", upnp: "OFF", grpc: "OFF"}
|
||||
- {vs: Visual Studio 17 2022, os: 2022, vspath: "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise", rx: "ON", upnp: "ON", grpc: "ON", tls: "ON"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, vspath: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise", rx: "ON", upnp: "ON", grpc: "ON", tls: "ON"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, vspath: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise", rx: "ON", upnp: "ON", grpc: "OFF", tls: "ON"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, vspath: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise", rx: "OFF", upnp: "ON", grpc: "OFF", tls: "ON"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, vspath: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise", rx: "OFF", upnp: "OFF", grpc: "OFF", tls: "ON"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, vspath: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise", rx: "OFF", upnp: "OFF", grpc: "OFF", tls: "OFF"}
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -442,7 +443,7 @@ jobs:
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "${{ matrix.config.vs }}" -DCMAKE_SYSTEM_VERSION="10.0" -DWITH_RANDOMX=${{ matrix.config.rx }} -DWITH_UPNP=${{ matrix.config.upnp }} -DWITH_GRPC=${{ matrix.config.grpc }}
|
||||
cmake .. -G "${{ matrix.config.vs }}" -DCMAKE_SYSTEM_VERSION="10.0" -DWITH_RANDOMX=${{ matrix.config.rx }} -DWITH_UPNP=${{ matrix.config.upnp }} -DWITH_GRPC=${{ matrix.config.grpc }} -DWITH_TLS=${{ matrix.config.tls }}
|
||||
& "${{ matrix.config.vspath }}\\MSBuild\\Current\\Bin\\amd64\\msbuild" -v:m /m /p:Configuration=Release p2pool.vcxproj
|
||||
|
||||
- name: Check Windows 7 compatibility
|
||||
@@ -480,7 +481,7 @@ jobs:
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: p2pool-vs-${{ matrix.config.os }}-randomx-${{ matrix.config.rx }}-upnp-${{ matrix.config.upnp }}-grpc-${{ matrix.config.grpc }}.exe
|
||||
name: p2pool-vs-${{ matrix.config.os }}-randomx-${{ matrix.config.rx }}-upnp-${{ matrix.config.upnp }}-grpc-${{ matrix.config.grpc }}-tls-${{ matrix.config.tls }}.exe
|
||||
path: build/Release/p2pool.exe
|
||||
|
||||
build-macos:
|
||||
|
||||
@@ -415,12 +415,14 @@ jobs:
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
cd build/RelWithDebInfo
|
||||
Remove-Item p2pool.cache -Force
|
||||
findstr /C:"Synchronization finished successfully" p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
if: '!cancelled()'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: p2pool_windows_data_leaks
|
||||
path: |
|
||||
build/RelWithDebInfo/*.log
|
||||
build/RelWithDebInfo/p2pool.*
|
||||
build/RelWithDebInfo/data/
|
||||
|
||||
@@ -436,12 +436,14 @@ jobs:
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
cd build/RelWithDebInfo
|
||||
Remove-Item p2pool.cache -Force
|
||||
findstr /C:"Synchronization finished successfully" p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
if: '!cancelled()'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: p2pool_windows_data_leaks
|
||||
path: |
|
||||
build/RelWithDebInfo/*.log
|
||||
build/RelWithDebInfo/p2pool.*
|
||||
build/RelWithDebInfo/data/
|
||||
|
||||
@@ -17,6 +17,7 @@ option(WITH_RANDOMX "Include the RandomX library in the build. If this is turned
|
||||
option(WITH_LTO "Use link-time compiler optimization (if linking fails for you, run cmake with -DWITH_LTO=OFF)" ON)
|
||||
option(WITH_UPNP "Include UPnP support. If this is turned off, p2pool will not be able to configure port forwarding on UPnP-enabled routers." ON)
|
||||
option(WITH_GRPC "Include gRPC support. If this is turned off, p2pool will not be able to merge mine with Tari." ON)
|
||||
option(WITH_TLS "Include TLS support. If this is turned off, p2pool will not support Stratum TLS connections." ON)
|
||||
|
||||
option(DEV_TEST_SYNC "[Developer only] Sync test, stop p2pool after sync is complete" OFF)
|
||||
option(DEV_WITH_TSAN "[Developer only] Compile with thread sanitizer" OFF)
|
||||
@@ -37,6 +38,9 @@ if (WITH_GRPC)
|
||||
include(cmake/grpc.cmake)
|
||||
|
||||
add_subdirectory(external/src/Tari)
|
||||
elseif (WITH_TLS)
|
||||
add_subdirectory(cmake/ssl)
|
||||
include_directories(external/src/grpc/third_party/boringssl-with-bazel/src/include)
|
||||
endif()
|
||||
|
||||
if (WITH_RANDOMX)
|
||||
@@ -166,6 +170,13 @@ if (WITH_GRPC)
|
||||
set(SOURCES ${SOURCES} src/merge_mining_client_tari.cpp)
|
||||
endif()
|
||||
|
||||
if (WITH_TLS)
|
||||
add_definitions(-DWITH_TLS)
|
||||
|
||||
set(HEADERS ${HEADERS} src/tls.h)
|
||||
set(SOURCES ${SOURCES} src/tls.cpp)
|
||||
endif()
|
||||
|
||||
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Header Files" FILES ${HEADERS})
|
||||
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Source Files" FILES ${SOURCES})
|
||||
|
||||
@@ -404,6 +415,8 @@ if (STATIC_BINARY OR STATIC_LIBS)
|
||||
|
||||
if (WITH_GRPC)
|
||||
set(STATIC_LIBS ${STATIC_LIBS} Tari_gRPC grpc grpc++ libprotobuf)
|
||||
elseif(WITH_TLS)
|
||||
set(STATIC_LIBS ${STATIC_LIBS} ssl crypto)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}
|
||||
@@ -415,6 +428,8 @@ if (STATIC_BINARY OR STATIC_LIBS)
|
||||
else()
|
||||
if (WITH_GRPC)
|
||||
set(LIBS ${LIBS} Tari_gRPC grpc grpc++ libprotobuf)
|
||||
elseif(WITH_TLS)
|
||||
set(LIBS ${LIBS} ssl crypto)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} debug ${ZMQ_LIBRARY_DEBUG} debug ${UV_LIBRARY_DEBUG} debug ${CURL_LIBRARY_DEBUG} optimized ${ZMQ_LIBRARY} optimized ${UV_LIBRARY} optimized ${CURL_LIBRARY} ${LIBS})
|
||||
|
||||
+2
-2
@@ -30,7 +30,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
if (DEV_WITH_TSAN OR DEV_WITH_UBSAN OR DEV_WITH_ASAN)
|
||||
set(OPTIMIZATION_FLAGS "-Og -g")
|
||||
else()
|
||||
set(OPTIMIZATION_FLAGS "-Ofast -s")
|
||||
set(OPTIMIZATION_FLAGS "-O3 -ffast-math -s")
|
||||
endif()
|
||||
|
||||
if (WITH_LTO)
|
||||
@@ -102,7 +102,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
if (DEV_WITH_MSAN)
|
||||
set(OPTIMIZATION_FLAGS "-Og -g")
|
||||
else()
|
||||
set(OPTIMIZATION_FLAGS "-Ofast -funroll-loops -fmerge-all-constants")
|
||||
set(OPTIMIZATION_FLAGS "-O3 -ffast-math -funroll-loops -fmerge-all-constants")
|
||||
endif()
|
||||
|
||||
if (WITH_LTO)
|
||||
|
||||
@@ -35,5 +35,6 @@ add_definitions(-DPROTOBUF_ENABLE_DEBUG_LOGGING_MAY_LEAK_PII=0)
|
||||
add_subdirectory(external/src/grpc)
|
||||
|
||||
include_directories(external/src/grpc/third_party/abseil-cpp)
|
||||
include_directories(external/src/grpc/third_party/boringssl-with-bazel/src/include)
|
||||
include_directories(external/src/grpc/third_party/protobuf/src)
|
||||
include_directories(external/src/grpc/include)
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
project(P2Pool_SSL LANGUAGES C CXX)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /W0 /Zi /Od /Ob0 /MP /MTd")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W0 /Zi /Od /Ob0 /MP /MTd")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /W0 /O1 /Ob2 /Oi /Os /Oy /MP /MT")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /W0 /O1 /Ob2 /Oi /Os /Oy /MP /MT")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /W0 /Ob1 /Ot /Zi /MP /MT")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /W0 /Ob1 /Ot /Zi /MP /MT")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Os -w")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os -w")
|
||||
endif()
|
||||
|
||||
if(CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||
if(CMAKE_VERSION VERSION_LESS 3.13)
|
||||
message(WARNING "Disabling SSL assembly support because CMake version ${CMAKE_VERSION} is too old (less than 3.13)")
|
||||
set(OPENSSL_NO_ASM ON)
|
||||
else()
|
||||
include(CheckLanguage)
|
||||
check_language(ASM_NASM)
|
||||
if(NOT CMAKE_ASM_NASM_COMPILER)
|
||||
message(WARNING "Disabling SSL assembly support because NASM could not be found")
|
||||
set(OPENSSL_NO_ASM ON)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(../../external/src/grpc/third_party/boringssl-with-bazel BoringSSL)
|
||||
@@ -31,6 +31,8 @@
|
||||
--upnp-stratum Port forward Stratum port (it's not forwarded by default)
|
||||
--merge-mine IP:port and wallet address for another blockchain to merge mine with
|
||||
--version Print p2pool's version and build details
|
||||
--tls-cert file Load TLS certificate chain from "file" in the PEM format
|
||||
--tls-cert-key file Load TLS certificate private key from "file" in the PEM format
|
||||
```
|
||||
|
||||
### Example command line
|
||||
@@ -68,3 +70,13 @@ Merge mining will be available in P2Pool after the fork on October 12th, 2024. V
|
||||
p2pool.exe --wallet YOUR_MONERO_WALLET_ADDRESS --merge-mine tari://IP:port TARI_WALLET_ADDRESS
|
||||
```
|
||||
Merge mining is available for testing in Tari's [v1.0.0-pre.14 release](https://github.com/tari-project/tari/releases/tag/v1.0.0-pre.14) (Esmeralda testnet).
|
||||
|
||||
### TLS
|
||||
|
||||
All `--tls...` parameters are optional. If they are not provided, P2Pool will generate a self-signed certificate upon startup.
|
||||
|
||||
If you want to use your own certificate, please refer to your certificate provider's documentation (or OpenSSL documentation) on how to generate the appropriate PEM files.
|
||||
|
||||
Note that you need to use certificate files and `--tls...` parameters to be able to use certificate pinning in XMRig miners that connect to your P2Pool instance.
|
||||
|
||||
`--tls-cert` and `--tls-cert-key` parameters must always be used together.
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
+1
-1
Submodule external/src/curl updated: fd567d4f06...83bedbd730
Vendored
+1
-1
Submodule external/src/grpc updated: f92105c06e...627ccb881e
Vendored
+1
-1
Submodule external/src/miniupnp updated: 943ba89358...a2eda5c4db
+8
-4
@@ -38,10 +38,14 @@ struct parse_wrapper<T, out_type> \
|
||||
{ \
|
||||
static FORCEINLINE bool parse(T& v, const char* name, out_type& out_value) \
|
||||
{ \
|
||||
if (v.IsObject() && v.HasMember(name)) { \
|
||||
const auto& t = v[name]; \
|
||||
if (t.Is##type()) { \
|
||||
out_value = static_cast<out_type>(t.Get##type()); \
|
||||
if (!v.IsObject()) { \
|
||||
return false; \
|
||||
} \
|
||||
const auto t = v.FindMember(name); \
|
||||
if (t != v.MemberEnd()) { \
|
||||
const auto& value = t->value; \
|
||||
if (value.Is##type()) { \
|
||||
out_value = static_cast<out_type>(value.Get##type()); \
|
||||
return true; \
|
||||
} \
|
||||
} \
|
||||
|
||||
@@ -64,6 +64,10 @@ void p2pool_usage()
|
||||
#endif
|
||||
"--merge-mine IP:port and wallet address for another blockchain to merge mine with\n"
|
||||
"--version Print p2pool's version and build details\n"
|
||||
#ifdef WITH_TLS
|
||||
"--tls-cert file Load TLS certificate chain from \"file\" in the PEM format\n"
|
||||
"--tls-cert-key file Load TLS certificate private key from \"file\" in the PEM format\n"
|
||||
#endif
|
||||
"--help Show this help message\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",
|
||||
|
||||
@@ -137,6 +137,28 @@ void show_top_10_allocations()
|
||||
VirtualFree(buf, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
static DWORD WINAPI minidump_and_crash_thread(LPVOID param)
|
||||
{
|
||||
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
|
||||
|
||||
const size_t delay = reinterpret_cast<size_t>(param);
|
||||
Sleep(static_cast<DWORD>(delay));
|
||||
|
||||
HANDLE h = CreateFile(TEXT("p2pool.dmp"), GENERIC_ALL, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), h, MiniDumpWithHandleData, nullptr, nullptr, nullptr);
|
||||
CloseHandle(h);
|
||||
|
||||
TerminateProcess(GetCurrentProcess(), 123);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void minidump_and_crash(size_t delay)
|
||||
{
|
||||
HANDLE h = CreateThread(nullptr, 0, minidump_and_crash_thread, reinterpret_cast<LPVOID>(delay), 0, nullptr);
|
||||
CloseHandle(h);
|
||||
}
|
||||
|
||||
FORCEINLINE static void add_alocation(void* p, size_t size)
|
||||
{
|
||||
if (!track_memory) {
|
||||
|
||||
@@ -100,6 +100,10 @@ MergeMiningClientJSON_RPC::~MergeMiningClientJSON_RPC()
|
||||
|
||||
void MergeMiningClientJSON_RPC::on_timer()
|
||||
{
|
||||
if (m_pool->stopped()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MinerData data = m_pool->miner_data();
|
||||
merge_mining_get_aux_block(data.height, data.prev_id, m_auxWallet);
|
||||
}
|
||||
|
||||
+33
-16
@@ -204,13 +204,14 @@ p2pool::~p2pool()
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<IMergeMiningClient*> merge_mining_clients;
|
||||
{
|
||||
WriteLock lock(m_mergeMiningClientsLock);
|
||||
merge_mining_clients.swap(m_mergeMiningClients);
|
||||
}
|
||||
|
||||
for (const IMergeMiningClient* c : m_mergeMiningClients) {
|
||||
delete c;
|
||||
}
|
||||
m_mergeMiningClients.clear();
|
||||
for (const IMergeMiningClient* c : merge_mining_clients) {
|
||||
delete c;
|
||||
}
|
||||
|
||||
uv_rwlock_destroy(&m_mainchainLock);
|
||||
@@ -520,7 +521,7 @@ void p2pool::handle_chain_main(ChainMain& data, const char* extra)
|
||||
LOGINFO(0, log::LightCyan() << "Your wallet " << log::LightYellow() << w << log::LightCyan() << " didn't get a payout in block " << log::LightYellow() << data.height << log::LightCyan() << " because you had no shares in PPLNS window");
|
||||
}
|
||||
|
||||
api_update_block_found(&data, block);
|
||||
api_update_block_found(&data, block, false);
|
||||
}
|
||||
else {
|
||||
side_chain().watch_mainchain_block(data, merkle_root);
|
||||
@@ -534,6 +535,10 @@ void p2pool::handle_chain_main(ChainMain& data, const char* extra)
|
||||
|
||||
void p2pool::update_aux_data(const hash& chain_id)
|
||||
{
|
||||
if (m_stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
MinerData data;
|
||||
std::vector<hash> aux_id;
|
||||
|
||||
@@ -1026,17 +1031,18 @@ void p2pool::download_block_headers(uint64_t current_height)
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<IMergeMiningClient*> merge_mining_clients;
|
||||
|
||||
for (const auto& h : m_params->m_mergeMiningHosts) {
|
||||
IMergeMiningClient* c = IMergeMiningClient::create(this, h.m_host, h.m_wallet);
|
||||
if (c) {
|
||||
merge_mining_clients.push_back(c);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
WriteLock lock(m_mergeMiningClientsLock);
|
||||
|
||||
m_mergeMiningClients.clear();
|
||||
|
||||
for (const auto& h : m_params->m_mergeMiningHosts) {
|
||||
IMergeMiningClient* c = IMergeMiningClient::create(this, h.m_host, h.m_wallet);
|
||||
if (c) {
|
||||
m_mergeMiningClients.push_back(c);
|
||||
}
|
||||
}
|
||||
m_mergeMiningClients = std::move(merge_mining_clients);
|
||||
}
|
||||
|
||||
m_startupFinished = true;
|
||||
@@ -1674,7 +1680,7 @@ void p2pool::cleanup_mainchain_data(uint64_t height)
|
||||
}
|
||||
}
|
||||
|
||||
void p2pool::api_update_block_found(const ChainMain* data, const PoolBlock* block)
|
||||
void p2pool::api_update_block_found(const ChainMain* data, const PoolBlock* block, bool update_stats_mod)
|
||||
{
|
||||
if (!m_api || m_stopped) {
|
||||
return;
|
||||
@@ -1721,7 +1727,9 @@ void p2pool::api_update_block_found(const ChainMain* data, const PoolBlock* bloc
|
||||
s << ']';
|
||||
});
|
||||
|
||||
api_update_stats_mod();
|
||||
if (update_stats_mod) {
|
||||
api_update_stats_mod();
|
||||
}
|
||||
}
|
||||
|
||||
bool p2pool::get_difficulty_at_height(uint64_t height, difficulty_type& diff)
|
||||
@@ -1897,6 +1905,15 @@ int p2pool::run()
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef WITH_TLS
|
||||
if (!m_params->m_tlsCert.empty() && !m_params->m_tlsCertKey.empty()) {
|
||||
if (!ServerTls::load_from_files(m_params->m_tlsCert.c_str(), m_params->m_tlsCertKey.c_str())) {
|
||||
LOGERR(1, "Failed to load TLS files");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Init default loop user data before running it
|
||||
uv_loop_t* loop = uv_default_loop_checked();
|
||||
loop->data = nullptr;
|
||||
|
||||
+1
-1
@@ -110,7 +110,7 @@ public:
|
||||
|
||||
bool chainmain_get_by_hash(const hash& id, ChainMain& data) const;
|
||||
|
||||
void api_update_block_found(const ChainMain* data, const PoolBlock* block);
|
||||
void api_update_block_found(const ChainMain* data, const PoolBlock* block, bool update_stats_mod = true);
|
||||
|
||||
bool get_difficulty_at_height(uint64_t height, difficulty_type& diff);
|
||||
|
||||
|
||||
+17
-10
@@ -130,29 +130,36 @@ void p2pool_api::dump_to_file_async_internal(Category category, const char* file
|
||||
}
|
||||
|
||||
MutexLock lock(m_dumpDataLock);
|
||||
m_dumpData[path] = std::move(buf);
|
||||
|
||||
if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(&m_dumpToFileAsync))) {
|
||||
uv_async_send(&m_dumpToFileAsync);
|
||||
std::pair<std::vector<char>, bool>& data = m_dumpData[path];
|
||||
|
||||
if (data.first != buf) {
|
||||
data.first = buf;
|
||||
data.second = true;
|
||||
|
||||
if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(&m_dumpToFileAsync))) {
|
||||
uv_async_send(&m_dumpToFileAsync);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void p2pool_api::dump_to_file()
|
||||
{
|
||||
unordered_map<std::string, std::vector<char>> data;
|
||||
{
|
||||
MutexLock lock(m_dumpDataLock);
|
||||
data = std::move(m_dumpData);
|
||||
}
|
||||
MutexLock lock(m_dumpDataLock);
|
||||
|
||||
char buf[log::Stream::BUF_SIZE + 1];
|
||||
buf[0] = '\0';
|
||||
|
||||
for (auto& it : data) {
|
||||
for (auto& it : m_dumpData) {
|
||||
if (!it.second.second) {
|
||||
continue;
|
||||
}
|
||||
it.second.second = false;
|
||||
|
||||
log::Stream s(buf);
|
||||
s << it.first << m_counter << '\0';
|
||||
|
||||
DumpFileWork* work = new DumpFileWork{ {}, 0, it.first, buf, std::move(it.second) };
|
||||
DumpFileWork* work = new DumpFileWork{ {}, 0, it.first, buf, it.second.first };
|
||||
work->req.data = work;
|
||||
++m_counter;
|
||||
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ private:
|
||||
std::string m_localPath;
|
||||
|
||||
uv_mutex_t m_dumpDataLock;
|
||||
unordered_map<std::string, std::vector<char>> m_dumpData;
|
||||
unordered_map<std::string, std::pair<std::vector<char>, bool>> m_dumpData;
|
||||
|
||||
uv_async_t m_dumpToFileAsync;
|
||||
|
||||
|
||||
@@ -195,6 +195,18 @@ Params::Params(int argc, char* const argv[])
|
||||
ok = true;
|
||||
}
|
||||
|
||||
#ifdef WITH_TLS
|
||||
if ((strcmp(argv[i], "--tls-cert") == 0) && (i + 1 < argc)) {
|
||||
m_tlsCert = argv[++i];
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--tls-cert-key") == 0) && (i + 1 < argc)) {
|
||||
m_tlsCertKey = argv[++i];
|
||||
ok = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ok) {
|
||||
fprintf(stderr, "Unknown command line parameter %s\n\n", argv[i]);
|
||||
p2pool_usage();
|
||||
@@ -240,6 +252,13 @@ bool Params::valid() const
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef WITH_TLS
|
||||
if (m_tlsCert.empty() != m_tlsCertKey.empty()) {
|
||||
LOGERR(1, "Both --tls-cert and --tls-cert-key files must be specified");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,6 +92,10 @@ struct Params
|
||||
bool m_upnp = false;
|
||||
bool m_upnpStratum = false;
|
||||
#endif
|
||||
#ifdef WITH_TLS
|
||||
std::string m_tlsCert;
|
||||
std::string m_tlsCertKey;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
+3
-3
@@ -42,7 +42,7 @@ class SideChain;
|
||||
* |xxxNONCExxxEXTRA_NONCExHASHxxx|xxxxxxxxxxxxxxxxx|
|
||||
* --------------------------------------------------
|
||||
*
|
||||
* HASH comes in TX_EXTRA_MERGE_MINING_TAG directly after EXTRA_NONCE
|
||||
* HASH (or Merkle tree root hash) comes in TX_EXTRA_MERGE_MINING_TAG directly after EXTRA_NONCE
|
||||
* HASH is calculated from all pool block's bytes and consensus ID (NONCE, EXTRA_NONCE and HASH itself are replaced with 0's when calculating HASH)
|
||||
* Pool block's PoW hash is calculated from the Monero block template part using Monero's consensus rules
|
||||
*/
|
||||
@@ -66,8 +66,8 @@ static constexpr uint64_t LOG2_MERGE_MINING_MAX_CHAINS = 8;
|
||||
// Oct 12 2024 20:00:00 GMT+0000
|
||||
static constexpr uint64_t MERGE_MINING_FORK_TIME = 1728763200;
|
||||
|
||||
// Jun 18 2024 20:00:00 GMT+0000
|
||||
static constexpr uint64_t MERGE_MINING_TESTNET_FORK_TIME = 1718740800;
|
||||
// Aug 11 2024 20:00:00 GMT+0000
|
||||
static constexpr uint64_t MERGE_MINING_TESTNET_FORK_TIME = 1723406400;
|
||||
|
||||
struct DifficultyData
|
||||
{
|
||||
|
||||
@@ -2185,6 +2185,11 @@ void SideChain::prune_old_blocks()
|
||||
|
||||
m_pool->print_hosts();
|
||||
m_pool->stop();
|
||||
|
||||
#ifdef DEV_TRACK_MEMORY
|
||||
// Give it 1 minute to shut down, otherwise save a minidump
|
||||
minidump_and_crash(60 * 1000);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+131
-46
@@ -272,17 +272,17 @@ bool StratumServer::on_login(StratumClient* client, uint32_t id, const char* log
|
||||
target = std::max(target, aux_diff.target());
|
||||
|
||||
if (get_custom_diff(login, client->m_customDiff)) {
|
||||
LOGINFO(5, "client " << log::Gray() << static_cast<char*>(client->m_addrString) << " set custom difficulty " << client->m_customDiff);
|
||||
LOGINFO(5, "client " << log::Gray() << static_cast<char*>(client->m_addrString) << log::NoColor() << " set custom difficulty " << client->m_customDiff);
|
||||
target = std::max(target, client->m_customDiff.target());
|
||||
}
|
||||
else if (m_autoDiff) {
|
||||
// Limit autodiff to 4000000 for maximum compatibility
|
||||
target = std::max(std::max(target, AUTODIFF_START), TARGET_4_BYTES_LIMIT);
|
||||
target = std::max(target, std::max(AUTODIFF_START, TARGET_4_BYTES_LIMIT));
|
||||
}
|
||||
|
||||
if (get_custom_user(login, client->m_customUser)) {
|
||||
const char* s = client->m_customUser;
|
||||
LOGINFO(5, "client " << log::Gray() << static_cast<char*>(client->m_addrString) << " set custom user " << s);
|
||||
LOGINFO(5, "client " << log::Gray() << static_cast<char*>(client->m_addrString) << log::NoColor() << " set custom user " << s);
|
||||
}
|
||||
|
||||
uint32_t job_id;
|
||||
@@ -541,6 +541,7 @@ void StratumServer::show_workers()
|
||||
size_t n = 0;
|
||||
|
||||
LOGINFO(0, log::pad_right("IP:port", addr_len + 8)
|
||||
<< "TLS "
|
||||
<< log::pad_right("uptime", 20)
|
||||
<< log::pad_right("difficulty", 20)
|
||||
<< log::pad_right("hashrate", 15)
|
||||
@@ -557,7 +558,15 @@ void StratumServer::show_workers()
|
||||
++diff.lo;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_TLS
|
||||
const bool is_tls = c->m_tls.is_empty();
|
||||
#else
|
||||
constexpr bool is_tls = false;
|
||||
#endif
|
||||
|
||||
LOGINFO(0, log::pad_right(static_cast<const char*>(c->m_addrString), addr_len + 8)
|
||||
<< (is_tls ? "no " : "yes ")
|
||||
<< log::pad_right(log::Duration(cur_time - c->m_connectedTime), 20)
|
||||
<< log::pad_right(diff, 20)
|
||||
<< log::pad_right(log::Hashrate(c->m_autoDiff.lo / AUTO_DIFF_TARGET_TIME, m_autoDiff && (c->m_autoDiff != 0)), 15)
|
||||
@@ -1080,7 +1089,8 @@ void StratumServer::on_shutdown()
|
||||
}
|
||||
|
||||
StratumServer::StratumClient::StratumClient()
|
||||
: Client(m_stratumReadBuf, sizeof(m_stratumReadBuf))
|
||||
: Client(m_rawReadBuf, sizeof(m_rawReadBuf))
|
||||
, m_stratumReadBufBytes(0)
|
||||
, m_rpcId(0)
|
||||
, m_perConnectionJobId(0)
|
||||
, m_connectedTime(0)
|
||||
@@ -1100,6 +1110,10 @@ StratumServer::StratumClient::StratumClient()
|
||||
void StratumServer::StratumClient::reset()
|
||||
{
|
||||
Client::reset();
|
||||
|
||||
m_stratumReadBuf[0] = '\0';
|
||||
m_stratumReadBufBytes = 0;
|
||||
|
||||
m_rpcId = 0;
|
||||
m_perConnectionJobId = 0;
|
||||
m_connectedTime = 0;
|
||||
@@ -1127,41 +1141,84 @@ bool StratumServer::StratumClient::on_connect()
|
||||
|
||||
bool StratumServer::StratumClient::on_read(char* data, uint32_t size)
|
||||
{
|
||||
if ((data != m_readBuf + m_numRead) || (data + size > m_readBuf + m_readBufSize)) {
|
||||
LOGERR(1, "client: invalid data pointer or size in on_read()");
|
||||
ban(DEFAULT_BAN_TIME);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_numRead += size;
|
||||
|
||||
char* line_start = m_readBuf;
|
||||
for (char* c = data; c < m_readBuf + m_numRead; ++c) {
|
||||
if (*c == '\n') {
|
||||
*c = '\0';
|
||||
if (!process_request(line_start, static_cast<uint32_t>(c - line_start))) {
|
||||
ban(DEFAULT_BAN_TIME);
|
||||
#ifdef WITH_TLS
|
||||
if (!m_tlsChecked) {
|
||||
if (data[0] == 0x16) {
|
||||
if (!m_tls.init()) {
|
||||
LOGWARN(5, "client " << static_cast<const char*>(m_addrString) << ": TLS init failed");
|
||||
return false;
|
||||
}
|
||||
line_start = c + 1;
|
||||
LOGINFO(5, "client " << log::Gray() << static_cast<const char*>(m_addrString) << log::NoColor() << " is using TLS");
|
||||
}
|
||||
m_tlsChecked = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Move the possible unfinished line to the beginning of m_readBuf to free up more space for reading
|
||||
if (line_start != m_readBuf) {
|
||||
m_numRead = static_cast<uint32_t>(m_readBuf + m_numRead - line_start);
|
||||
if (m_numRead > 0) {
|
||||
memmove(m_readBuf, line_start, m_numRead);
|
||||
auto on_parse = [this](char* data, uint32_t size) {
|
||||
if (static_cast<size_t>(m_stratumReadBufBytes) + size > STRATUM_BUF_SIZE) {
|
||||
LOGWARN(4, "client " << static_cast<const char*>(m_addrString) << " sent too long Stratum message");
|
||||
ban(DEFAULT_BAN_TIME);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
memcpy(m_stratumReadBuf + m_stratumReadBufBytes, data, size);
|
||||
m_stratumReadBufBytes += size;
|
||||
|
||||
char* line_start = m_stratumReadBuf;
|
||||
for (char *e = line_start + m_stratumReadBufBytes, *c = e - size; c < e; ++c) {
|
||||
if (*c == '\n') {
|
||||
// Check if the line starts with "GET " (an HTTP request)
|
||||
if ((c - line_start >= 4) && (*reinterpret_cast<uint32_t*>(line_start) == 0x20544547U)) {
|
||||
LOGINFO(5, "client " << log::Gray() << static_cast<const char*>(m_addrString) << log::NoColor() << " sent an HTTP request");
|
||||
send_http_response();
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
|
||||
*c = '\0';
|
||||
if (!process_request(line_start, static_cast<uint32_t>(c - line_start))) {
|
||||
ban(DEFAULT_BAN_TIME);
|
||||
return false;
|
||||
}
|
||||
|
||||
line_start = c + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Move the possible unfinished line to the beginning of m_stratumReadBuf to free up more space for reading
|
||||
if (line_start != m_stratumReadBuf) {
|
||||
m_stratumReadBufBytes = static_cast<uint32_t>(m_stratumReadBuf + m_stratumReadBufBytes - line_start);
|
||||
if (m_stratumReadBufBytes > 0) {
|
||||
memmove(m_stratumReadBuf, line_start, m_stratumReadBufBytes);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
#ifdef WITH_TLS
|
||||
if (!m_tls.is_empty()) {
|
||||
auto on_write = [this](const uint8_t* data, size_t size) {
|
||||
return m_owner->send(this, [data, size](uint8_t* buf, size_t buf_size) -> size_t {
|
||||
if (buf_size < size) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(buf, data, size);
|
||||
return size;
|
||||
}, true);
|
||||
};
|
||||
|
||||
return m_tls.on_read(data, size, std::move(on_parse), std::move(on_write));
|
||||
}
|
||||
#endif
|
||||
|
||||
return on_parse(data, size);
|
||||
}
|
||||
|
||||
bool StratumServer::StratumClient::process_request(char* data, uint32_t /*size*/)
|
||||
bool StratumServer::StratumClient::process_request(char* data, uint32_t size)
|
||||
{
|
||||
rapidjson::Document doc;
|
||||
if (doc.ParseInsitu(data).HasParseError()) {
|
||||
if (doc.Parse(data, size).HasParseError()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid JSON request (parse error)");
|
||||
return false;
|
||||
}
|
||||
@@ -1171,23 +1228,25 @@ bool StratumServer::StratumClient::process_request(char* data, uint32_t /*size*/
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!doc.HasMember("id")) {
|
||||
const auto id_it = doc.FindMember("id");
|
||||
if (id_it == doc.MemberEnd()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid JSON request ('id' field not found)");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& id = doc["id"];
|
||||
const auto& id = id_it->value;
|
||||
if (!id.IsUint()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid JSON request ('id' field is not an integer)");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!doc.HasMember("method")) {
|
||||
const auto method_it = doc.FindMember("method");
|
||||
if (method_it == doc.MemberEnd()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid JSON request ('method' field not found)");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& method = doc["method"];
|
||||
const auto& method = method_it->value;
|
||||
if (!method.IsString()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid JSON request ('method' field is not a string)");
|
||||
return false;
|
||||
@@ -1213,23 +1272,25 @@ bool StratumServer::StratumClient::process_request(char* data, uint32_t /*size*/
|
||||
|
||||
bool StratumServer::StratumClient::process_login(rapidjson::Document& doc, uint32_t id)
|
||||
{
|
||||
if (!doc.HasMember("params")) {
|
||||
const auto params_it = doc.FindMember("params");
|
||||
if (params_it == doc.MemberEnd()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid JSON login request ('params' field not found)");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& params = doc["params"];
|
||||
const auto& params = params_it->value;
|
||||
if (!params.IsObject()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid JSON login request ('params' field is not an object)");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!params.HasMember("login")) {
|
||||
const auto login_it = params.FindMember("login");
|
||||
if (login_it == params.MemberEnd()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid login params ('login' field not found)");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& login = params["login"];
|
||||
const auto& login = login_it->value;
|
||||
if (!login.IsString()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid login params ('login' field is not a string)");
|
||||
return false;
|
||||
@@ -1240,45 +1301,49 @@ bool StratumServer::StratumClient::process_login(rapidjson::Document& doc, uint3
|
||||
|
||||
bool StratumServer::StratumClient::process_submit(rapidjson::Document& doc, uint32_t id)
|
||||
{
|
||||
if (!doc.HasMember("params")) {
|
||||
const auto params_it = doc.FindMember("params");
|
||||
if (params_it == doc.MemberEnd()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid JSON submit request ('params' field not found)");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& params = doc["params"];
|
||||
const auto& params = params_it->value;
|
||||
if (!params.IsObject()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid JSON submit request ('params' field is not an object)");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!params.HasMember("id")) {
|
||||
const auto rpcId_it = params.FindMember("id");
|
||||
if (rpcId_it == params.MemberEnd()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid submit params ('id' field not found)");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& rpcId = params["id"];
|
||||
const auto& rpcId = rpcId_it->value;
|
||||
if (!rpcId.IsString()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid submit params ('id' field is not a string)");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!params.HasMember("job_id")) {
|
||||
const auto job_id_it = params.FindMember("job_id");
|
||||
if (job_id_it == params.MemberEnd()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid submit params ('job_id' field not found)");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& job_id = params["job_id"];
|
||||
const auto& job_id = job_id_it->value;
|
||||
if (!job_id.IsString()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid submit params ('job_id' field is not a string)");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!params.HasMember("nonce")) {
|
||||
const auto nonce_it = params.FindMember("nonce");
|
||||
if (nonce_it == params.MemberEnd()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid submit params ('nonce' field not found)");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& nonce = params["nonce"];
|
||||
const auto& nonce = nonce_it->value;
|
||||
if (!nonce.IsString()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid submit params ('nonce' field is not a string)");
|
||||
return false;
|
||||
@@ -1289,12 +1354,13 @@ bool StratumServer::StratumClient::process_submit(rapidjson::Document& doc, uint
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!params.HasMember("result")) {
|
||||
const auto result_it = params.FindMember("result");
|
||||
if (result_it == params.MemberEnd()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid submit params ('result' field not found)");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& result = params["result"];
|
||||
const auto& result = result_it->value;
|
||||
if (!result.IsString()) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(m_addrString) << " invalid submit params ('result' field is not a string)");
|
||||
return false;
|
||||
@@ -1308,6 +1374,25 @@ 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());
|
||||
}
|
||||
|
||||
bool StratumServer::StratumClient::send_http_response()
|
||||
{
|
||||
return m_owner->send(this, [](uint8_t *buf, size_t buf_size) -> size_t {
|
||||
static constexpr uint8_t data[] =
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Content-Length: 21\r\n"
|
||||
"Content-Type: text/html\r\n"
|
||||
"Connection: Closed\r\n\r\n"
|
||||
"P2Pool Stratum online";
|
||||
|
||||
if (buf_size < sizeof(data)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buf, data, sizeof(data));
|
||||
return sizeof(data);
|
||||
});
|
||||
}
|
||||
|
||||
void StratumServer::api_update_local_stats(uint64_t timestamp)
|
||||
{
|
||||
if (!m_pool->api() || !m_pool->params().m_localStats || m_pool->stopped()) {
|
||||
|
||||
@@ -52,7 +52,12 @@ public:
|
||||
[[nodiscard]] bool process_login(rapidjson::Document& doc, uint32_t id);
|
||||
[[nodiscard]] bool process_submit(rapidjson::Document& doc, uint32_t id);
|
||||
|
||||
bool send_http_response();
|
||||
|
||||
alignas(8) char m_rawReadBuf[STRATUM_BUF_SIZE];
|
||||
|
||||
alignas(8) char m_stratumReadBuf[STRATUM_BUF_SIZE];
|
||||
uint32_t m_stratumReadBufBytes;
|
||||
|
||||
uint32_t m_rpcId;
|
||||
uint32_t m_perConnectionJobId;
|
||||
|
||||
+48
-24
@@ -538,7 +538,7 @@ void TCPServer::print_bans()
|
||||
}
|
||||
}
|
||||
|
||||
bool TCPServer::send_internal(Client* client, Callback<size_t, uint8_t*, size_t>::Base&& callback)
|
||||
bool TCPServer::send_internal(Client* client, Callback<size_t, uint8_t*, size_t>::Base&& callback, bool raw)
|
||||
{
|
||||
check_event_loop_thread(__func__);
|
||||
|
||||
@@ -559,34 +559,50 @@ bool TCPServer::send_internal(Client* client, Callback<size_t, uint8_t*, size_t>
|
||||
return false;
|
||||
}
|
||||
|
||||
WriteBuf* buf = get_write_buffer(bytes_written);
|
||||
auto on_write = [this, client](const uint8_t* data, size_t size) {
|
||||
WriteBuf* buf = get_write_buffer(size);
|
||||
|
||||
buf->m_write.data = buf;
|
||||
buf->m_client = client;
|
||||
buf->m_write.data = buf;
|
||||
buf->m_client = client;
|
||||
|
||||
if (buf->m_dataCapacity < bytes_written) {
|
||||
buf->m_dataCapacity = round_up(bytes_written, 64);
|
||||
buf->m_data = realloc_hook(buf->m_data, buf->m_dataCapacity);
|
||||
if (!buf->m_data) {
|
||||
LOGERR(0, "failed to allocate " << buf->m_dataCapacity << " bytes to send data");
|
||||
PANIC_STOP();
|
||||
if (buf->m_dataCapacity < size) {
|
||||
buf->m_dataCapacity = round_up(size, 64);
|
||||
buf->m_data = realloc_hook(buf->m_data, buf->m_dataCapacity);
|
||||
if (!buf->m_data) {
|
||||
LOGERR(0, "failed to allocate " << buf->m_dataCapacity << " bytes to send data");
|
||||
PANIC_STOP();
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(buf->m_data, data, size);
|
||||
|
||||
uv_buf_t bufs[1];
|
||||
bufs[0].base = reinterpret_cast<char*>(buf->m_data);
|
||||
bufs[0].len = static_cast<int>(size);
|
||||
|
||||
const int err = uv_write(&buf->m_write, reinterpret_cast<uv_stream_t*>(&client->m_socket), bufs, 1, Client::on_write);
|
||||
if (err) {
|
||||
LOGWARN(1, "failed to start writing data to client connection " << static_cast<const char*>(client->m_addrString) << ", error " << uv_err_name(err));
|
||||
return_write_buffer(buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
#ifdef WITH_TLS
|
||||
if (!client->m_tls.is_empty() && !raw) {
|
||||
if (!client->m_tls.on_write(m_callbackBuf.data(), bytes_written, std::move(on_write))) {
|
||||
LOGWARN(1, "TLS write failed to client connection " << static_cast<const char*>(client->m_addrString));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
(void)raw;
|
||||
#endif
|
||||
|
||||
memcpy(buf->m_data, m_callbackBuf.data(), bytes_written);
|
||||
|
||||
uv_buf_t bufs[1];
|
||||
bufs[0].base = reinterpret_cast<char*>(buf->m_data);
|
||||
bufs[0].len = static_cast<int>(bytes_written);
|
||||
|
||||
const int err = uv_write(&buf->m_write, reinterpret_cast<uv_stream_t*>(&client->m_socket), bufs, 1, Client::on_write);
|
||||
if (err) {
|
||||
LOGWARN(1, "failed to start writing data to client connection " << static_cast<const char*>(client->m_addrString) << ", error " << uv_err_name(err));
|
||||
return_write_buffer(buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return on_write(m_callbackBuf.data(), bytes_written);
|
||||
}
|
||||
|
||||
const char* TCPServer::get_log_category() const
|
||||
@@ -999,6 +1015,9 @@ TCPServer::Client::Client(char* read_buf, size_t size)
|
||||
, m_addrString{}
|
||||
, m_socks5ProxyState(Socks5ProxyState::Default)
|
||||
, m_resetCounter{ 0 }
|
||||
#ifdef WITH_TLS
|
||||
, m_tlsChecked(false)
|
||||
#endif
|
||||
{
|
||||
m_readBuf[0] = '\0';
|
||||
m_readBuf[m_readBufSize - 1] = '\0';
|
||||
@@ -1023,6 +1042,11 @@ void TCPServer::Client::reset()
|
||||
m_socks5ProxyState = Socks5ProxyState::Default;
|
||||
m_readBuf[0] = '\0';
|
||||
m_readBuf[m_readBufSize - 1] = '\0';
|
||||
|
||||
#ifdef WITH_TLS
|
||||
m_tls.reset();
|
||||
m_tlsChecked = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void TCPServer::Client::on_alloc(uv_handle_t* handle, size_t /*suggested_size*/, uv_buf_t* buf)
|
||||
|
||||
+12
-2
@@ -18,6 +18,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "uv_util.h"
|
||||
|
||||
#ifdef WITH_TLS
|
||||
#include "tls.h"
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace p2pool {
|
||||
@@ -106,6 +111,11 @@ public:
|
||||
} m_socks5ProxyState;
|
||||
|
||||
std::atomic<uint32_t> m_resetCounter;
|
||||
|
||||
#ifdef WITH_TLS
|
||||
ServerTls m_tls;
|
||||
bool m_tlsChecked;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct WriteBuf
|
||||
@@ -128,7 +138,7 @@ public:
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] FORCEINLINE bool send(Client* client, T&& callback) { return send_internal(client, Callback<size_t, uint8_t*, size_t>::Derived<T>(std::move(callback))); }
|
||||
[[nodiscard]] FORCEINLINE bool send(Client* client, T&& callback, bool raw = false) { return send_internal(client, Callback<size_t, uint8_t*, size_t>::Derived<T>(std::move(callback)), raw); }
|
||||
|
||||
private:
|
||||
static void on_new_connection(uv_stream_t* server, int status);
|
||||
@@ -138,7 +148,7 @@ private:
|
||||
void on_new_client(uv_stream_t* server);
|
||||
void on_new_client(uv_stream_t* server, Client* client);
|
||||
|
||||
[[nodiscard]] bool send_internal(Client* client, Callback<size_t, uint8_t*, size_t>::Base&& callback);
|
||||
[[nodiscard]] bool send_internal(Client* client, Callback<size_t, uint8_t*, size_t>::Base&& callback, bool raw);
|
||||
|
||||
allocate_client_callback m_allocateNewClient;
|
||||
|
||||
|
||||
+321
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021-2024 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
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "tls.h"
|
||||
|
||||
LOG_CATEGORY(TLS)
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
static bssl::UniquePtr<EVP_PKEY> init_evp_pkey()
|
||||
{
|
||||
bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
|
||||
|
||||
if (!evp_pkey.get()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
|
||||
|
||||
if (!ec_key || !EC_KEY_generate_key(ec_key.get())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!EVP_PKEY_assign_EC_KEY(evp_pkey.get(), ec_key.release())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//FILE* fp;
|
||||
//if (fopen_s(&fp, "cert_key.pem", "wb") == 0) {
|
||||
// PEM_write_PrivateKey(fp, evp_pkey.get(), nullptr, nullptr, 0, nullptr, nullptr);
|
||||
// fclose(fp);
|
||||
//}
|
||||
|
||||
return evp_pkey;
|
||||
}
|
||||
|
||||
static bssl::UniquePtr<EVP_PKEY> s_evp_pkey = init_evp_pkey();
|
||||
|
||||
static bssl::UniquePtr<X509> init_cert()
|
||||
{
|
||||
bssl::UniquePtr<X509> x509(X509_new());
|
||||
|
||||
if (!x509.get()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!X509_set_version(x509.get(), X509_VERSION_3)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::mt19937_64 rng(RandomDeviceSeed::instance);
|
||||
rng.discard(10000);
|
||||
|
||||
const uint64_t serial = rng();
|
||||
|
||||
if (!ASN1_INTEGER_set_uint64(X509_get_serialNumber(x509.get()), serial)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
constexpr int64_t YEAR = 31557600;
|
||||
|
||||
const time_t cur_time = time(nullptr);
|
||||
|
||||
const time_t t0 = cur_time - (cur_time % YEAR);
|
||||
const time_t t1 = t0 - YEAR * 10;
|
||||
const time_t t2 = t0 + YEAR * 10;
|
||||
|
||||
if (!ASN1_TIME_set(X509_get_notBefore(x509.get()), t1) || !ASN1_TIME_set(X509_get_notAfter(x509.get()), t2)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
X509_NAME* subject = X509_get_subject_name(x509.get());
|
||||
|
||||
if (!X509_NAME_add_entry_by_txt(subject, "C", MBSTRING_ASC, reinterpret_cast<const uint8_t*>("US"), -1, -1, 0) ||
|
||||
!X509_NAME_add_entry_by_txt(subject, "O", MBSTRING_ASC, reinterpret_cast<const uint8_t*>("BoringSSL"), -1, -1, 0) ||
|
||||
!X509_set_issuer_name(x509.get(), subject)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bssl::UniquePtr<STACK_OF(ASN1_OBJECT)> ekus(sk_ASN1_OBJECT_new_null());
|
||||
|
||||
if (!ekus || !sk_ASN1_OBJECT_push(ekus.get(), OBJ_nid2obj(NID_server_auth)) || !X509_add1_ext_i2d(x509.get(), NID_ext_key_usage, ekus.get(), 1, 0)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!X509_set_pubkey(x509.get(), s_evp_pkey.get())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!X509_sign(x509.get(), s_evp_pkey.get(), EVP_sha256())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//FILE* fp;
|
||||
//if (fopen_s(&fp, "cert.pem", "wb") == 0) {
|
||||
// PEM_write_X509(fp, x509.get());
|
||||
// fclose(fp);
|
||||
//}
|
||||
|
||||
return x509;
|
||||
}
|
||||
|
||||
static bssl::UniquePtr<X509> s_cert = init_cert();
|
||||
|
||||
static bssl::UniquePtr<SSL_CTX> init_ctx()
|
||||
{
|
||||
if (!s_evp_pkey.get() || !s_cert.get()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
|
||||
|
||||
if (!ctx.get()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!SSL_CTX_use_PrivateKey(ctx.get(), s_evp_pkey.get())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!SSL_CTX_use_certificate(ctx.get(), s_cert.get())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static bssl::UniquePtr<SSL_CTX> s_ctx = init_ctx();
|
||||
|
||||
bool ServerTls::load_from_files(const char* cert, const char* cert_key)
|
||||
{
|
||||
if (!cert) {
|
||||
LOGERR(0, "No cert file specified");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cert_key) {
|
||||
LOGERR(0, "No cert_key file specified");
|
||||
return false;
|
||||
}
|
||||
|
||||
bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
|
||||
|
||||
if (!ctx.get()) {
|
||||
LOGERR(0, "Failed to create SSL context");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SSL_CTX_use_certificate_chain_file(ctx.get(), cert) <= 0) {
|
||||
LOGERR(0, "Failed to load " << cert);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SSL_CTX_use_PrivateKey_file(ctx.get(), cert_key, SSL_FILETYPE_PEM) <= 0) {
|
||||
LOGERR(0, "Failed to load " << cert_key);
|
||||
return false;
|
||||
}
|
||||
|
||||
SSL_CTX_set_options(ctx.get(), SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||
|
||||
LOGINFO(1, log::LightCyan() << "Loaded " << cert << ", " << cert_key);
|
||||
|
||||
s_ctx.reset(ctx.release());
|
||||
return true;
|
||||
}
|
||||
|
||||
void ServerTls::reset()
|
||||
{
|
||||
m_ssl.reset(nullptr);
|
||||
}
|
||||
|
||||
bool ServerTls::init()
|
||||
{
|
||||
if (!s_ctx.get()) {
|
||||
static std::atomic<uint32_t> ctx_error_shown = 0;
|
||||
if (ctx_error_shown.exchange(1) == 0) {
|
||||
LOGERR(0, "Failed to initialize an SSL context");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
m_ssl.reset(SSL_new(s_ctx.get()));
|
||||
|
||||
if (!m_ssl.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SSL_set_accept_state(m_ssl.get());
|
||||
|
||||
BIO* rbio = BIO_new(BIO_s_mem());
|
||||
BIO* wbio = BIO_new(BIO_s_mem());
|
||||
|
||||
if (!rbio || !wbio) {
|
||||
BIO_free(rbio);
|
||||
BIO_free(wbio);
|
||||
|
||||
m_ssl.reset(nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
SSL_set_bio(m_ssl.get(), rbio, wbio);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServerTls::on_read_internal(char* data, uint32_t size, ReadCallback::Base&& read_callback, WriteCallback::Base&& write_callback)
|
||||
{
|
||||
SSL* ssl = m_ssl.get();
|
||||
if (!ssl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!BIO_write_all(SSL_get_rbio(ssl), data, size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SSL_is_init_finished(ssl)) {
|
||||
const int result = SSL_do_handshake(ssl);
|
||||
|
||||
if (!result) {
|
||||
// EOF
|
||||
return false;
|
||||
}
|
||||
|
||||
// Send pending handshake data, if any
|
||||
BIO* wbio = SSL_get_wbio(ssl);
|
||||
if (!wbio) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8_t* bio_data;
|
||||
size_t bio_len;
|
||||
|
||||
if (!BIO_mem_contents(wbio, &bio_data, &bio_len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bio_len > 0) {
|
||||
if (!write_callback(bio_data, bio_len)) {
|
||||
return false;
|
||||
}
|
||||
if (!BIO_reset(wbio)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((result < 0) && (SSL_get_error(ssl, result) == SSL_ERROR_WANT_READ)) {
|
||||
// Continue handshake, nothing to read yet
|
||||
return true;
|
||||
}
|
||||
else if (result == 1) {
|
||||
// Handshake finished, skip to "SSL_read" further down
|
||||
}
|
||||
else {
|
||||
// Some other error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int bytes_read;
|
||||
char buf[1024];
|
||||
|
||||
while ((bytes_read = SSL_read(ssl, buf, sizeof(buf))) > 0) {
|
||||
if (!read_callback(buf, static_cast<uint32_t>(bytes_read))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServerTls::on_write_internal(const uint8_t* data, size_t size, WriteCallback::Base&& write_callback)
|
||||
{
|
||||
SSL* ssl = m_ssl.get();
|
||||
if (!ssl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SSL_write(ssl, data, static_cast<int>(size)) <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BIO* wbio = SSL_get_wbio(ssl);
|
||||
if (!wbio) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8_t* bio_data;
|
||||
size_t bio_len;
|
||||
|
||||
if (!BIO_mem_contents(wbio, &bio_data, &bio_len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bio_len > 0) {
|
||||
if (!write_callback(bio_data, bio_len)) {
|
||||
return false;
|
||||
}
|
||||
if (!BIO_reset(wbio)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace p2pool
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021-2024 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
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||
#endif
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
class ServerTls
|
||||
{
|
||||
public:
|
||||
FORCEINLINE ServerTls() { reset(); }
|
||||
|
||||
[[nodiscard]] static bool load_from_files(const char* cert, const char* cert_key);
|
||||
|
||||
void reset();
|
||||
[[nodiscard]] bool init();
|
||||
|
||||
template<typename T, typename U>
|
||||
[[nodiscard]] FORCEINLINE bool on_read(char* data, uint32_t size, T&& read_callback, U&& write_callback)
|
||||
{
|
||||
return on_read_internal(data, size, ReadCallback::Derived<T>(std::move(read_callback)), WriteCallback::Derived<U>(std::move(write_callback)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] FORCEINLINE bool on_write(const uint8_t* data, size_t size, T&& write_callback)
|
||||
{
|
||||
return on_write_internal(data, size, WriteCallback::Derived<T>(std::move(write_callback)));
|
||||
}
|
||||
|
||||
[[nodiscard]] FORCEINLINE bool is_empty() const { return m_ssl.get() == nullptr; }
|
||||
|
||||
private:
|
||||
typedef Callback<bool, char*, uint32_t> ReadCallback;
|
||||
typedef Callback<bool, const uint8_t*, size_t> WriteCallback;
|
||||
|
||||
[[nodiscard]] bool on_read_internal(char* data, uint32_t size, ReadCallback::Base&& read_callback, WriteCallback::Base&& write_callback);
|
||||
[[nodiscard]] bool on_write_internal(const uint8_t* data, size_t size, WriteCallback::Base&& write_callback);
|
||||
|
||||
private:
|
||||
bssl::UniquePtr<SSL> m_ssl;
|
||||
};
|
||||
|
||||
} // namespace p2pool
|
||||
+2
-1
@@ -35,7 +35,7 @@
|
||||
namespace p2pool {
|
||||
|
||||
#define P2POOL_VERSION_MAJOR 4
|
||||
#define P2POOL_VERSION_MINOR 0
|
||||
#define P2POOL_VERSION_MINOR 1
|
||||
#define P2POOL_VERSION_PATCH 0
|
||||
|
||||
constexpr uint32_t P2POOL_VERSION = (P2POOL_VERSION_MAJOR << 16) | (P2POOL_VERSION_MINOR << 8) | P2POOL_VERSION_PATCH;
|
||||
@@ -358,6 +358,7 @@ FORCEINLINE bool get_dns_txt_records(const std::string& host, T&& callback) { re
|
||||
|
||||
#ifdef DEV_TRACK_MEMORY
|
||||
void show_top_10_allocations();
|
||||
void minidump_and_crash(size_t delay);
|
||||
#endif
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
+5
-1
@@ -42,7 +42,10 @@ ZMQReader::ZMQReader(const std::string& address, uint32_t zmq_port, const std::s
|
||||
addr_buf[0] = '\0';
|
||||
|
||||
std::random_device rd;
|
||||
for (uint32_t port = 49152 + (rd() % 16384), i = 0; i < 100; ++i, port = (port < 65535) ? (port + 1) : 49152) {
|
||||
|
||||
for (uint32_t i = 0; i < 100; ++i) {
|
||||
const uint32_t port = 49152 + (rd() % 16384);
|
||||
|
||||
try {
|
||||
log::Stream s(addr_buf);
|
||||
s << "tcp://127.0.0.1:" << port << '\0';
|
||||
@@ -52,6 +55,7 @@ ZMQReader::ZMQReader(const std::string& address, uint32_t zmq_port, const std::s
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
LOGWARN(1, "failed to to bind port " << port << " for ZMQ publisher, error " << e.what());
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
set(GENERAL_FLAGS "-pthread")
|
||||
set(WARNING_FLAGS "-Wall -Wextra")
|
||||
set(OPTIMIZATION_FLAGS "-Ofast -s")
|
||||
set(OPTIMIZATION_FLAGS "-O3 -ffast-math -s")
|
||||
|
||||
if (WITH_LTO)
|
||||
set(OPTIMIZATION_FLAGS "${OPTIMIZATION_FLAGS} -flto=auto -fuse-linker-plugin")
|
||||
@@ -45,7 +45,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
endif()
|
||||
|
||||
set(WARNING_FLAGS "-Wall -Wextra -Wno-undefined-internal")
|
||||
set(OPTIMIZATION_FLAGS "-Ofast -funroll-loops -fmerge-all-constants")
|
||||
set(OPTIMIZATION_FLAGS "-O3 -ffast-math -funroll-loops -fmerge-all-constants")
|
||||
|
||||
if (WITH_LTO)
|
||||
set(OPTIMIZATION_FLAGS "${OPTIMIZATION_FLAGS} -flto")
|
||||
|
||||
+1
-1
Submodule tests/googletest updated: f8d7d77c06...e397860881
@@ -291,6 +291,7 @@ allowedAPIs = {
|
||||
"CryptBinaryToStringW",
|
||||
"DeleteFileA",
|
||||
"GetFileAttributesA",
|
||||
"OpenThreadToken",
|
||||
}
|
||||
|
||||
f = open(sys.argv[1], 'r')
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "mm_test2",
|
||||
"name": "mm_test3",
|
||||
"password": "",
|
||||
"block_time": 10,
|
||||
"min_diff": 100000,
|
||||
|
||||
@@ -17,17 +17,25 @@ import socket
|
||||
import time
|
||||
import sys
|
||||
import json
|
||||
import ssl
|
||||
|
||||
f = open('stratum_dummy' + sys.argv[1] + '.log', 'wb')
|
||||
|
||||
f.write(b'Connecting')
|
||||
f.flush()
|
||||
|
||||
context = ssl.create_default_context()
|
||||
context.check_hostname = False
|
||||
context.verify_mode = ssl.CERT_NONE
|
||||
|
||||
while True:
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.settimeout(1)
|
||||
sock.setblocking(True)
|
||||
|
||||
if (sys.argv[1] == '1'):
|
||||
sock = context.wrap_socket(sock);
|
||||
|
||||
if sock.connect_ex(('127.0.0.1', 3333)) == 0:
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user