From fce85519526bca05036d26db99393eb7cd119f2a Mon Sep 17 00:00:00 2001 From: div72 Date: Mon, 16 Dec 2024 18:46:14 +0300 Subject: [PATCH 1/8] rpc: remove deprecated resolver::query `boost::asio::ip::tcp::resolver::query` has been removed in 1.87 which causes compilation issues. This raises the minimum supported version of Boost to 1.66 which should be safe since near-EOL focal has 1.71. --- src/rpc/protocol.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index 6b8a752a1d..a18da9c479 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -143,8 +143,7 @@ class SSLIOStreamDevice : public boost::iostreams::device Date: Tue, 17 Dec 2024 01:41:56 +0300 Subject: [PATCH 2/8] [refactor] rpc: remove usage of resolver::iterator `boost::asio::ip::tcp::resolver::iterator` has been removed in Boost 1.87. --- src/rpc/protocol.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index a18da9c479..2e76e448e1 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -143,17 +143,18 @@ class SSLIOStreamDevice : public boost::iostreams::device Date: Tue, 17 Dec 2024 01:50:42 +0300 Subject: [PATCH 3/8] ci, cd: bump distro versions --- .github/workflows/ci.yml | 6 +++--- cd/00_setup_env.sh | 2 +- ci/test/00_setup_env.sh | 2 +- ci/test/00_setup_env_arm.sh | 2 +- ci/test/00_setup_env_native_old.sh | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 763548f922..d45d5e6319 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,11 +7,11 @@ env: jobs: test-linux: name: ${{ matrix.name }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 strategy: matrix: include: - - name: ARM [GOAL install] [buster] + - name: ARM [GOAL install] [bullseye] script-id: arm - name: Win32 script-id: win32 @@ -21,7 +21,7 @@ jobs: script-id: linux_i386 - name: x86_64 Linux [GOAL install] [GUI] [focal] [no depends] script-id: native - - name: x86_64 Linux [GOAL install] [GUI] [bionic] [no depends] + - name: x86_64 Linux [GOAL install] [GUI] [noble] [no depends] script-id: native_old - name: x86_64 Linux [ASan] [LSan] [UBSan] [integer] [jammy] [no depends] script-id: native_asan diff --git a/cd/00_setup_env.sh b/cd/00_setup_env.sh index 668a70a0b5..1e7079ef7b 100755 --- a/cd/00_setup_env.sh +++ b/cd/00_setup_env.sh @@ -32,7 +32,7 @@ export HOST=${HOST:-$("$BASE_ROOT_DIR/depends/config.guess")} # Whether to prefer BusyBox over GNU utilities export USE_BUSY_BOX=${USE_BUSY_BOX:-false} export CONTAINER_NAME=${CONTAINER_NAME:-ci_unnamed} -export DOCKER_NAME_TAG=${DOCKER_NAME_TAG:-ubuntu:18.04} +export DOCKER_NAME_TAG=${DOCKER_NAME_TAG:-ubuntu:20.04} # See man 7 debconf export DEBIAN_FRONTEND=noninteractive export CCACHE_SIZE=${CCACHE_SIZE:-300M} diff --git a/ci/test/00_setup_env.sh b/ci/test/00_setup_env.sh index bd4c6fe3d2..29d775ef57 100755 --- a/ci/test/00_setup_env.sh +++ b/ci/test/00_setup_env.sh @@ -37,7 +37,7 @@ export RUN_SECURITY_TESTS=${RUN_SECURITY_TESTS:-false} export TEST_RUNNER_ENV=${TEST_RUNNER_ENV:-} export RUN_FUZZ_TESTS=${RUN_FUZZ_TESTS:-false} export CONTAINER_NAME=${CONTAINER_NAME:-ci_unnamed} -export DOCKER_NAME_TAG=${DOCKER_NAME_TAG:-ubuntu:18.04} +export DOCKER_NAME_TAG=${DOCKER_NAME_TAG:-ubuntu:20.04} # Randomize test order. # See https://www.boost.org/doc/libs/1_71_0/libs/test/doc/html/boost_test/utf_reference/rt_param_reference/random.html export BOOST_TEST_RANDOM=${BOOST_TEST_RANDOM:-1} diff --git a/ci/test/00_setup_env_arm.sh b/ci/test/00_setup_env_arm.sh index d92a0067df..62db7a5b11 100755 --- a/ci/test/00_setup_env_arm.sh +++ b/ci/test/00_setup_env_arm.sh @@ -18,7 +18,7 @@ if [ -n "$QEMU_USER_CMD" ]; then fi export CONTAINER_NAME=ci_arm_linux # Use debian to avoid 404 apt errors when cross compiling -export DOCKER_NAME_TAG="debian:buster" +export DOCKER_NAME_TAG="debian:bullseye" export USE_BUSY_BOX=true export RUN_UNIT_TESTS=true export RUN_FUNCTIONAL_TESTS=false diff --git a/ci/test/00_setup_env_native_old.sh b/ci/test/00_setup_env_native_old.sh index 34f9b93e66..43edbc2dda 100755 --- a/ci/test/00_setup_env_native_old.sh +++ b/ci/test/00_setup_env_native_old.sh @@ -7,7 +7,7 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_old -export DOCKER_NAME_TAG=ubuntu:18.04 +export DOCKER_NAME_TAG=ubuntu:20.04 export PACKAGES="gcc-8 g++-8 libqt5gui5 libqt5core5a qtbase5-dev libqt5dbus5 qttools5-dev qttools5-dev-tools libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-iostreams-dev libboost-test-dev libboost-thread-dev libminiupnpc-dev libqrencode-dev libzip-dev zlib1g zlib1g-dev libcurl4-openssl-dev" export RUN_UNIT_TESTS=true # export RUN_FUNCTIONAL_TESTS=false From 4d91c8c299b388c0891d7626d6c669d539e37cc4 Mon Sep 17 00:00:00 2001 From: div72 Date: Tue, 17 Dec 2024 02:42:30 +0300 Subject: [PATCH 4/8] [refactor] rpc: boost 1.87 fixes for server --- src/rpc/server.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 497c8bbd30..25aba08644 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -500,15 +500,19 @@ bool ClientAllowed(const boost::asio::ip::address& address) { // Make sure that IPv4-compatible and IPv4-mapped IPv6 addresses are treated as IPv4 addresses if (address.is_v6() - && (address.to_v6().is_v4_compatible() - || address.to_v6().is_v4_mapped())) - return ClientAllowed(address.to_v6().to_v4()); + && (address.to_v6() <= boost::asio::ip::make_address_v6("::ffff:ffff") + || address.to_v6().is_v4_mapped())) { + auto address6 = address.to_v6(); + auto bytes = address6.to_bytes(); + + return ClientAllowed(boost::asio::ip::address_v4({bytes[12], bytes[13], bytes[14], bytes[15]})); + } if (address == asio::ip::address_v4::loopback() || address == asio::ip::address_v6::loopback() || (address.is_v4() // Check whether IPv4 addresses match 127.0.0.0/8 (loopback subnet) - && (address.to_v4().to_ulong() & 0xff000000) == 0x7f000000)) + && (address.to_v4().to_bytes()[0] == 127))) return true; const string strAddress = address.to_string(); @@ -661,7 +665,7 @@ void StartRPCThreads() acceptor->set_option(boost::asio::ip::v6_only(loopback), v6_only_error); acceptor->bind(endpoint); - acceptor->listen(socket_base::max_connections); + acceptor->listen(socket_base::max_listen_connections); RPCListen(acceptor, *rpc_ssl_context, fUseSSL); @@ -684,7 +688,7 @@ void StartRPCThreads() acceptor->open(endpoint.protocol()); acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); acceptor->bind(endpoint); - acceptor->listen(socket_base::max_connections); + acceptor->listen(socket_base::max_listen_connections); RPCListen(acceptor, *rpc_ssl_context, fUseSSL); From e8d990e3f2b069b51b8c567b9c63cf496242f911 Mon Sep 17 00:00:00 2001 From: div72 Date: Thu, 19 Dec 2024 16:19:04 +0300 Subject: [PATCH 5/8] [refactor] diagnose: fix for boost 1.87 I'm at a loss for words. --- src/wallet/diagnose.cpp | 91 +++++++---------------------------------- src/wallet/diagnose.h | 40 ++++-------------- 2 files changed, 22 insertions(+), 109 deletions(-) diff --git a/src/wallet/diagnose.cpp b/src/wallet/diagnose.cpp index 6a5c41102f..851e89986f 100644 --- a/src/wallet/diagnose.cpp +++ b/src/wallet/diagnose.cpp @@ -15,7 +15,7 @@ bool Diagnose::m_hasPoolProjects = false; bool Diagnose::m_configured_for_investor_mode = false; std::unordered_map Diagnose::m_name_to_test_map; CCriticalSection Diagnose::cs_diagnostictests; -boost::asio::io_service Diagnose::s_ioService; +boost::asio::io_context Diagnose::s_ioService; /** * The function check the time is correct on your PC. It checks the skew in the clock. @@ -102,102 +102,39 @@ void VerifyClock::timerHandle( void VerifyClock::connectToNTPHost() { m_startedTesting = true; - boost::asio::ip::udp::resolver resolver(s_ioService); try { FastRandomContext rng; std::string ntp_host = m_ntp_hosts[rng.randrange(m_ntp_hosts.size())]; -#if BOOST_VERSION > 106501 - // results_type is only in boost 1.66 and above. - boost::asio::ip::udp::resolver::results_type receiver_endpoint; + boost::asio::ip::udp::resolver resolver(s_ioService); + auto resolved = resolver.resolve(boost::asio::ip::udp::v4(), ntp_host, "ntp"); - receiver_endpoint = resolver.resolve(boost::asio::ip::udp::v4(), ntp_host, "ntp"); + if (m_udpSocket.is_open()) + m_udpSocket.close(); + m_udpSocket.open(boost::asio::ip::udp::v4()); + boost::asio::connect(m_udpSocket, resolved); - if (receiver_endpoint == boost::asio::ip::udp::resolver::iterator()) { - // If can not connect to server, then finish the test with a warning. - clkReportResults(0, true); - } else { - if (m_udpSocket.is_open()) - m_udpSocket.close(); - m_udpSocket.open(boost::asio::ip::udp::v4()); - - // Let's put the send here to reduce the complexity of this. No need for the send to be async. - size_t bytes_transferred = 0; - - try { - bytes_transferred = m_udpSocket.send_to(boost::asio::buffer(m_sendBuf), *receiver_endpoint); - } catch (boost::system::error_code& e) { - clkReportResults(0, true); - } - - if (bytes_transferred != 48) { - clkReportResults(0, true); - } else { - m_udpSocket.async_receive_from( - boost::asio::buffer(m_recvBuf), - m_sender_endpoint, - boost::bind(&VerifyClock::sockRecvHandle, this, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); - } - } + size_t bytes_transferred = m_udpSocket.send(boost::asio::buffer(m_sendBuf)); -#else - boost::asio::ip::udp::resolver::query query( - boost::asio::ip::udp::v4(), - ntp_host, - "ntp"); - - boost::asio::ip::udp::resolver::iterator endpoint_iterator = resolver.resolve(query); - - if (endpoint_iterator == boost::asio::ip::udp::resolver::iterator()) { - // If can not connect to server, then finish the test with a warning. + if (bytes_transferred != 48) { clkReportResults(0, true); } else { - if (m_udpSocket.is_open()) - m_udpSocket.close(); - m_udpSocket.open(boost::asio::ip::udp::v4()); - - // Let's put the send here to reduce the complexity of this. No need for the send to be async. - size_t bytes_transferred = 0; - - try { - bytes_transferred = m_udpSocket.send_to(boost::asio::buffer(m_sendBuf), *endpoint_iterator); - } catch (boost::system::error_code& e) { - clkReportResults(0, true); - } - - if (bytes_transferred != 48) { - clkReportResults(0, true); - } else { - boost::asio::ip::udp::endpoint sender_endpoint; - - m_udpSocket.async_receive_from( - boost::asio::buffer(m_recvBuf), - sender_endpoint, - boost::bind(&VerifyClock::sockRecvHandle, this, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); - } + m_udpSocket.async_receive( + boost::asio::buffer(m_recvBuf), + boost::bind(&VerifyClock::sockRecvHandle, this, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } -#endif } catch (...) { clkReportResults(0, true); } } -void VerifyTCPPort::handle_connect(const boost::system::error_code& err, - boost::asio::ip::tcp::resolver::iterator endpoint_iterator) +void VerifyTCPPort::handle_connect(const boost::system::error_code& err) { if (!err) { this->TCPFinished(); - } else if (endpoint_iterator != boost::asio::ip::tcp::resolver::iterator()) { - // The connection failed. Try the next endpoint in the list. - m_tcpSocket.close(); - boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator; - m_tcpSocket.async_connect(endpoint, - boost::bind(&VerifyTCPPort::handle_connect, this, - boost::asio::placeholders::error, ++endpoint_iterator)); } else { m_tcpSocket.close(); m_results = WARNING; diff --git a/src/wallet/diagnose.h b/src/wallet/diagnose.h index 606b0205ec..fdc541e0b5 100644 --- a/src/wallet/diagnose.h +++ b/src/wallet/diagnose.h @@ -185,7 +185,7 @@ class Diagnose static CCriticalSection cs_diagnostictests; //!< used to protect the critical sections, for multithreading TestNames m_test_name; //!< This must be defined for derived classes. Each derived class must declare the name of the test and add to the TestNames enum static std::unordered_map m_name_to_test_map; //!< a map to save the test and a pointer to it. Some tests are related and need to access the results of each other. - static boost::asio::io_service s_ioService; + static boost::asio::io_context s_ioService; }; /** @@ -349,7 +349,6 @@ class VerifyClock : public Diagnose boost::array m_sendBuf = {0x1b, 0, 0, 0, 0, 0, 0, 0, 0}; boost::array m_recvBuf; bool m_startedTesting = false; - boost::asio::ip::udp::endpoint m_sender_endpoint; // This has to be here to guarantee it is available for the callback void clkReportResults(const int64_t& time_offset, const bool& timeout_during_check = false); void sockRecvHandle(const boost::system::error_code& error, std::size_t bytes_transferred); @@ -381,7 +380,7 @@ class VerifyClock : public Diagnose connectToNTPHost(); - s_ioService.reset(); + s_ioService.restart(); s_ioService.run(); } } @@ -637,8 +636,7 @@ class VerifyTCPPort : public Diagnose { private: boost::asio::ip::tcp::socket m_tcpSocket; - void handle_connect(const boost::system::error_code& err, - boost::asio::ip::tcp::resolver::iterator endpoint_iterator); + void handle_connect(const boost::system::error_code& err); void TCPFinished(); @@ -649,7 +647,7 @@ class VerifyTCPPort : public Diagnose ~VerifyTCPPort() {} void runCheck() { - s_ioService.reset(); + s_ioService.restart(); m_results_string_arg.clear(); m_results_tip_arg.clear(); @@ -662,34 +660,12 @@ class VerifyTCPPort : public Diagnose } boost::asio::ip::tcp::resolver resolver(s_ioService); -#if BOOST_VERSION > 106501 - auto endpoint_iterator = resolver.resolve("portquiz.net", "http"); -#else - boost::asio::ip::tcp::resolver::query query( - "portquiz.net", - "http"); - auto endpoint_iterator = resolver.resolve(query); -#endif - - if (endpoint_iterator == boost::asio::ip::tcp::resolver::iterator()) { - m_tcpSocket.close(); - m_results = WARNING; - m_results_tip = _("Outbound communication to TCP port %1 appears to be blocked."); - std::string ss = ToString(GetListenPort()); - m_results_string_arg.push_back(ss); - } else { - // Attempt a connection to the first endpoint in the list. Each endpoint - // will be tried until we successfully establish a connection. - boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator; - if (m_tcpSocket.is_open()) - m_tcpSocket.close(); + auto resolved = resolver.resolve("portquiz.net", "http"); - m_tcpSocket.async_connect(endpoint, - boost::bind(&VerifyTCPPort::handle_connect, this, - boost::asio::placeholders::error, (++endpoint_iterator))); + // FIXME(div72): This whole portion was/is a BLOCKING asynchronous segment, what the hell. + boost::asio::async_connect(m_tcpSocket, resolved, boost::bind(&VerifyTCPPort::handle_connect, this, boost::asio::placeholders::error)); - s_ioService.run(); - } + s_ioService.run(); } }; From c6c45d0cd44d7d58db0f7868ae98702fe6a9f4f2 Mon Sep 17 00:00:00 2001 From: div72 Date: Thu, 9 Jan 2025 13:35:55 +0300 Subject: [PATCH 6/8] ci: enable MSYS2 for cmake ci --- .github/workflows/cmake-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/cmake-ci.yml b/.github/workflows/cmake-ci.yml index aae94cbc0c..f39f8096b5 100644 --- a/.github/workflows/cmake-ci.yml +++ b/.github/workflows/cmake-ci.yml @@ -196,8 +196,6 @@ jobs: retention-days: 7 test-msys2: - # MSYS2 is rolling release, only latest Boost is available. - if: false runs-on: windows-latest defaults: run: From aea93c5767b35d3660bfea8c9f96afaa6aca7a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anna=20=E2=80=9CCyberTailor=E2=80=9D?= Date: Thu, 9 Jan 2025 23:33:53 +0500 Subject: [PATCH 7/8] build: CMake: Use BoostConfig if available --- CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cb04cddcb..aace67a0cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -169,7 +169,13 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.30) # Allow to find old Boost (pre 1.70) with new CMake (3.30 and later). cmake_policy(SET CMP0167 OLD) endif() -find_package(Boost ${BOOST_MINIMUM_VERSION}...<1.87.0 COMPONENTS ${BOOST_COMPONENTS} REQUIRED) +find_package(Boost ${BOOST_MINIMUM_VERSION} REQUIRED) +if(Boost_VERSION VERSION_LESS 1.70.0) + find_package(Boost ${BOOST_MINIMUM_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED) +else() + # Better upstream-provided CMake config is available. + find_package(Boost ${BOOST_MINIMUM_VERSION} COMPONENTS ${BOOST_COMPONENTS} CONFIG REQUIRED) +endif() if(BUNDLED_OPENSSL) hunter_add_package(OpenSSL) From bd44d1e61501c4a5c19caf8cbb226fc4ec649fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anna=20=E2=80=9CCyberTailor=E2=80=9D?= Date: Thu, 9 Jan 2025 23:36:49 +0500 Subject: [PATCH 8/8] ci: CMake: Unpin Boost version on macOS --- .github/workflows/cmake-ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/cmake-ci.yml b/.github/workflows/cmake-ci.yml index f39f8096b5..a7921e20a2 100644 --- a/.github/workflows/cmake-ci.yml +++ b/.github/workflows/cmake-ci.yml @@ -150,7 +150,7 @@ jobs: - name: Install dependencies run: brew install --overwrite ${{matrix.deps}} - boost@1.85 + boost ccache libzip ninja @@ -168,7 +168,6 @@ jobs: -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache ${{matrix.options}} - -DBOOST_ROOT=$(brew --prefix boost@1.85) -DENABLE_TESTS=ON - name: Restore cache uses: actions/cache/restore@v4