diff --git a/.python-version b/.python-version index 43077b246094f..1445aee866ce6 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.9.18 +3.10.14 diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e2e1ec583b08..68e214aab2b0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -540,7 +540,7 @@ if(WERROR) unset(werror_flag) endif() -find_package(Python3 3.9 COMPONENTS Interpreter) +find_package(Python3 3.10 COMPONENTS Interpreter) if(Python3_EXECUTABLE) set(PYTHON_COMMAND ${Python3_EXECUTABLE}) else() diff --git a/README.md b/README.md index 94789bbc75ffc..4bd0a3f9e94aa 100644 --- a/README.md +++ b/README.md @@ -89,8 +89,10 @@ submit new unit tests for old code. Unit tests can be compiled and run (assuming they weren't disabled during the generation of the build system) with: `ctest`. Further details on running and extending unit tests can be found in [/src/test/README.md](/src/test/README.md). -Run configure with the --enable-debug option, then make. Or run configure with -CXXFLAGS="-g -ggdb -O0" or whatever debug flags you need. +There are also [regression and integration tests](/test), written +in Python. +These tests can be run (if the [test dependencies](/test) are installed) with: `build/test/functional/test_runner.py` +(assuming `build` is your build directory). The -debug=... command-line option controls debugging; running with just -debug will turn diff --git a/ci/test/00_setup_env_native_nowallet_libgroestlcoinkernel.sh b/ci/test/00_setup_env_native_nowallet_libgroestlcoinkernel.sh index 996bcd323891a..0acdb0f937e4c 100755 --- a/ci/test/00_setup_env_native_nowallet_libgroestlcoinkernel.sh +++ b/ci/test/00_setup_env_native_nowallet_libgroestlcoinkernel.sh @@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_nowallet_libgroestlcoinkernel export CI_IMAGE_NAME_TAG="docker.io/debian:bookworm" -# Use minimum supported python3.9 (or best-effort 3.11) and clang-16, see doc/dependencies.md +# Use minimum supported python3.10 (or best-effort 3.11) and clang-16, see doc/dependencies.md export PACKAGES="python3-zmq clang-16 llvm-16 libc++abi-16-dev libc++-16-dev" export DEP_OPTS="NO_WALLET=1 CC=clang-16 CXX='clang++-16 -stdlib=libc++'" export GOAL="install" diff --git a/ci/test/00_setup_env_native_previous_releases.sh b/ci/test/00_setup_env_native_previous_releases.sh index eae2c6916e65b..267bd11f1f6b3 100644 --- a/ci/test/00_setup_env_native_previous_releases.sh +++ b/ci/test/00_setup_env_native_previous_releases.sh @@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_previous_releases export CI_IMAGE_NAME_TAG="docker.io/ubuntu:22.04" -# Use minimum supported python3.9 (or best effort 3.10) and gcc-11, see doc/dependencies.md +# Use minimum supported python3.10 and gcc-11, see doc/dependencies.md export PACKAGES="gcc-11 g++-11 python3-zmq" export DEP_OPTS="NO_UPNP=1 DEBUG=1 CC=gcc-11 CXX=g++-11" export RUN_UNIT_TESTS_SEQUENTIAL="false" diff --git a/contrib/devtools/check-deps.sh b/contrib/devtools/check-deps.sh index 2fce249945ba1..cdfc4e7533d04 100755 --- a/contrib/devtools/check-deps.sh +++ b/contrib/devtools/check-deps.sh @@ -133,7 +133,7 @@ check_disallowed() { dst_obj=$(obj_names "$symbol" "${temp_dir}/${dst}_exports.txt") while read src_obj; do if ! check_suppress "$src_obj" "$dst_obj" "$symbol"; then - echo "Error: $src_obj depends on $dst_obj symbol '$(c++filt "$symbol")', can suppess with:" + echo "Error: $src_obj depends on $dst_obj symbol '$(c++filt "$symbol")', can suppress with:" echo " SUPPRESS[\"$src_obj $dst_obj $symbol\"]=1" result=1 fi @@ -145,7 +145,7 @@ check_disallowed() { # Declare array to track errors which were suppressed. declare -A SUPPRESSED -# Return whether error should be suppressed and record suppresssion in +# Return whether error should be suppressed and record suppression in # SUPPRESSED array. check_suppress() { local src_obj="$1" @@ -161,7 +161,7 @@ check_suppress() { return 1 } -# Warn about error which were supposed to be suppress, but were not encountered. +# Warn about error which were supposed to be suppressed, but were not encountered. check_not_suppressed() { for suppress in "${!SUPPRESS[@]}"; do if [[ ! -v SUPPRESSED[$suppress] ]]; then diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py index 1d92542542c2d..6cab3b521ccd4 100755 --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -235,7 +235,7 @@ def check_MACHO_libraries(binary) -> bool: return ok def check_MACHO_min_os(binary) -> bool: - if binary.build_version.minos == [11,0,0]: + if binary.build_version.minos == [13,0,0]: return True return False diff --git a/contrib/devtools/test-symbol-check.py b/contrib/devtools/test-symbol-check.py index 454dbc6bd206f..c75a5e1546b9e 100755 --- a/contrib/devtools/test-symbol-check.py +++ b/contrib/devtools/test-symbol-check.py @@ -116,7 +116,7 @@ def test_MACHO(self): } ''') - self.assertEqual(call_symbol_check(cxx, source, executable, ['-Wl,-platform_version','-Wl,macos', '-Wl,11.0', '-Wl,11.4']), + self.assertEqual(call_symbol_check(cxx, source, executable, ['-Wl,-platform_version','-Wl,macos', '-Wl,13.0', '-Wl,11.4']), (1, f'{executable}: failed SDK')) def test_PE(self): diff --git a/contrib/signet/README.md b/contrib/signet/README.md index 79eb84ee4b6b4..1590fca3b4843 100644 --- a/contrib/signet/README.md +++ b/contrib/signet/README.md @@ -24,9 +24,8 @@ miner You will first need to pick a difficulty target. Since signet chains are primarily protected by a signature rather than proof of work, there is no need to spend as much energy as possible mining, however you may wish to choose to spend more time than the absolute minimum. The calibrate subcommand can be used to pick a target appropriate for your hardware, eg: pip3 install groestlcoin_hash - cd src/ - MINER="../contrib/signet/miner" - GRIND="./groestlcoin-util grind" + MINER="./contrib/signet/miner" + GRIND="./build/src/groestlcoin-util grind" $MINER calibrate --grind-cmd="$GRIND" nbits=1e0377ae for 60s average mining time @@ -34,7 +33,7 @@ It defaults to estimating an nbits value resulting in 60s average time to find a To mine the first block in your custom chain, you can run: - CLI="./groestlcoin-cli -conf=mysignet.conf" + CLI="./build/src/groestlcoin-cli -conf=mysignet.conf" ADDR=$($CLI -signet getnewaddress) NBITS=1e0377ae $MINER --cli="$CLI" generate --grind-cmd="$GRIND" --address="$ADDR" --nbits=$NBITS diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk index a27d8b323b694..4659d52912c1b 100644 --- a/depends/hosts/darwin.mk +++ b/depends/hosts/darwin.mk @@ -1,4 +1,4 @@ -OSX_MIN_VERSION=11.0 +OSX_MIN_VERSION=13.0 OSX_SDK_VERSION=14.0 XCODE_VERSION=15.0 XCODE_BUILD_ID=15A240d diff --git a/doc/build-osx.md b/doc/build-osx.md index 3445342564ab3..48f5932ecd987 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -1,15 +1,15 @@ # macOS Build Guide -**Updated for MacOS [14](https://www.apple.com/macos/sonoma/)** +**Updated for MacOS [15](https://www.apple.com/macos/macos-sequoia/)** -This guide describes how to build groestlcoind, command-line utilities, and GUI on macOS +This guide describes how to build groestlcoind, command-line utilities, and GUI on macOS. ## Preparation The commands in this guide should be executed in a Terminal application. macOS comes with a built-in Terminal located in: -``` +```bash /Applications/Utilities/Terminal.app ``` @@ -51,20 +51,6 @@ To install, run the following from your terminal: brew install cmake boost pkg-config libevent ``` -For macOS 11 (Big Sur) and 12 (Monterey) you need to install a more recent version of llvm. - -``` bash -brew install llvm -``` - -And append the following to the configure commands below: - -``` bash --DCMAKE_C_COMPILER="$(brew --prefix llvm)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm)/bin/clang++" -``` - -Try `llvm@17` if compilation fails with the default version of llvm. - ### 4. Clone Groestlcoin repository `git` should already be installed by default on your system. diff --git a/doc/dependencies.md b/doc/dependencies.md index fdeca31403fcf..92fd8064ba080 100644 --- a/doc/dependencies.md +++ b/doc/dependencies.md @@ -9,7 +9,7 @@ You can find installation instructions in the `build-*.md` file for your platfor | [Clang](https://clang.llvm.org) | [16.0](https://github.com/bitcoin/bitcoin/pull/30263) | | [CMake](https://cmake.org/) | [3.22](https://github.com/bitcoin/bitcoin/pull/30454) | | [GCC](https://gcc.gnu.org) | [11.1](https://github.com/bitcoin/bitcoin/pull/29091) | -| [Python](https://www.python.org) (scripts, tests) | [3.9](https://github.com/bitcoin/bitcoin/pull/28211) | +| [Python](https://www.python.org) (scripts, tests) | [3.10](https://github.com/bitcoin/bitcoin/pull/30527) | | [systemtap](https://sourceware.org/systemtap/) ([tracing](tracing.md))| N/A | ## Required diff --git a/doc/fuzzing.md b/doc/fuzzing.md index ac824f4cc6b35..8d89a2b562e86 100644 --- a/doc/fuzzing.md +++ b/doc/fuzzing.md @@ -227,82 +227,6 @@ $ FUZZ=process_message ./honggfuzz/honggfuzz -i inputs/ -- build_fuzz/src/test/f Read the [Honggfuzz documentation](https://github.com/google/honggfuzz/blob/master/docs/USAGE.md) for more information. -## Fuzzing the Groestlcoin Core P2P layer using Honggfuzz NetDriver - -Honggfuzz NetDriver allows for very easy fuzzing of TCP servers such as Groestlcoin -Core without having to write any custom fuzzing harness. The `groestlcoind` server -process is largely fuzzed without modification. - -This makes the fuzzing highly realistic: a bug reachable by the fuzzer is likely -also remotely triggerable by an untrusted peer. - -To quickly get started fuzzing the P2P layer using Honggfuzz NetDriver: - -```sh -$ mkdir groestlcoin-honggfuzz-p2p/ -$ cd groestlcoin-honggfuzz-p2p/ -$ git clone https://github.com/groestlcoin/groestlcoin -$ cd groestlcoin/ -$ git clone https://github.com/google/honggfuzz -$ cd honggfuzz/ -$ make -$ cd .. -$ git apply << "EOF" -diff --git a/src/compat/compat.h b/src/compat/compat.h -index 8195bceaec..cce2b31ff0 100644 ---- a/src/compat/compat.h -+++ b/src/compat/compat.h -@@ -90,8 +90,12 @@ typedef char* sockopt_arg_type; - // building with a binutils < 2.36 is subject to this ld bug. - #define MAIN_FUNCTION __declspec(dllexport) int main(int argc, char* argv[]) - #else -+#ifdef HFND_FUZZING_ENTRY_FUNCTION_CXX -+#define MAIN_FUNCTION HFND_FUZZING_ENTRY_FUNCTION_CXX(int argc, char* argv[]) -+#else - #define MAIN_FUNCTION int main(int argc, char* argv[]) - #endif -+#endif - - // Note these both should work with the current usage of poll, but best to be safe - // WIN32 poll is broken https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/ -diff --git a/src/net.cpp b/src/net.cpp -index 7601a6ea84..702d0f56ce 100644 ---- a/src/net.cpp -+++ b/src/net.cpp -@@ -727,7 +727,7 @@ int V1TransportDeserializer::readHeader(Span msg_bytes) - } - - // Check start string, network magic -- if (memcmp(hdr.pchMessageStart, m_chain_params.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) { -+ if (false && memcmp(hdr.pchMessageStart, m_chain_params.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) { // skip network magic checking - LogDebug(BCLog::NET, "Header error: Wrong MessageStart %s received, peer=%d\n", HexStr(hdr.pchMessageStart), m_node_id); - return -1; - } -@@ -788,7 +788,7 @@ CNetMessage V1TransportDeserializer::GetMessage(const std::chrono::microseconds - RandAddEvent(ReadLE32(hash.begin())); - - // Check checksum and header message type string -- if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) { -+ if (false && memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) { // skip checksum checking - LogDebug(BCLog::NET, "Header error: Wrong checksum (%s, %u bytes), expected %s was %s, peer=%d\n", - SanitizeString(msg.m_type), msg.m_message_size, - HexStr(Span{hash}.first(CMessageHeader::CHECKSUM_SIZE)), -EOF -$ cmake -B build_fuzz \ - -DCMAKE_C_COMPILER="$(pwd)/honggfuzz/hfuzz_cc/hfuzz-clang" \ - -DCMAKE_CXX_COMPILER="$(pwd)/honggfuzz/hfuzz_cc/hfuzz-clang++" \ - -DENABLE_WALLET=OFF \ - -DBUILD_GUI=OFF \ - -DSANITIZERS=address,undefined -$ cmake --build build_fuzz --target groestlcoind -$ mkdir -p inputs/ -$ ./honggfuzz/honggfuzz --exit_upon_crash --quiet --timeout 4 -n 1 -Q \ - -E HFND_TCP_PORT=18444 -f inputs/ -- \ - build_fuzz/src/groestlcoind -regtest -discover=0 -dns=0 -dnsseed=0 -listenonion=0 \ - -nodebuglogfile -bind=127.0.0.1:18444 -logthreadnames \ - -debug -``` - # OSS-Fuzz Groestlcoin Core participates in Google's [OSS-Fuzz](https://github.com/google/oss-fuzz/tree/master/projects/bitcoin-core) diff --git a/doc/release-notes-empty-template.md b/doc/release-notes-empty-template.md index 9904a39e68e27..679e98b8afc28 100644 --- a/doc/release-notes-empty-template.md +++ b/doc/release-notes-empty-template.md @@ -39,7 +39,7 @@ Compatibility ============== Groestlcoin Core is supported and extensively tested on operating systems -using the Linux Kernel 3.17+, macOS 11.0+, and Windows 7 and newer. Groestlcoin +using the Linux Kernel 3.17+, macOS 13.0+, and Windows 7 and newer. Groestlcoin Core should also work on most other Unix-like systems but is not as frequently tested on them. It is not recommended to use Groestlcoin Core on unsupported systems. diff --git a/share/qt/Info.plist.in b/share/qt/Info.plist.in index e98f4009f6533..db25307c62240 100644 --- a/share/qt/Info.plist.in +++ b/share/qt/Info.plist.in @@ -3,7 +3,7 @@ LSMinimumSystemVersion - 11 + 13 LSArchitecturePriority diff --git a/src/kernel/CMakeLists.txt b/src/kernel/CMakeLists.txt index e68e85b4a3a34..ae5b28c481d8f 100644 --- a/src/kernel/CMakeLists.txt +++ b/src/kernel/CMakeLists.txt @@ -87,6 +87,7 @@ target_link_libraries(groestlcoinkernel bitcoin_crypto leveldb secp256k1 + $ PUBLIC Boost::headers ) diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h index f5a3c0dcee17c..f9cf5d91577ac 100644 --- a/src/test/util/setup_common.h +++ b/src/test/util/setup_common.h @@ -75,6 +75,23 @@ struct BasicTestingSetup { fs::path m_path_root; fs::path m_path_lock; bool m_has_custom_datadir{false}; + /** @brief Test-specific arguments and settings. + * + * This member is intended to be the primary source of settings for code + * being tested by unit tests. It exists to make tests more self-contained + * and reduce reliance on global state. + * + * Usage guidelines: + * 1. Prefer using m_args where possible in test code. + * 2. If m_args is not accessible, use m_node.args as a fallback. + * 3. Avoid direct references to gArgs in test code. + * + * Note: Currently, m_node.args points to gArgs for backwards + * compatibility. In the future, it will point to m_args to further isolate + * test environments. + * + * @see https://github.com/bitcoin/bitcoin/issues/25055 for additional context. + */ ArgsManager m_args; }; diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index 7abf7f59c08fa..aceed24a86c3d 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -1167,6 +1167,7 @@ static util::Result CreateTransactionInternal( result.GetSelectedValue()); // vouts to the payees + txNew.vout.reserve(vecSend.size() + 1); // + 1 because of possible later insert for (const auto& recipient : vecSend) { txNew.vout.emplace_back(recipient.nAmount, GetScriptForDestination(recipient.dest)); @@ -1217,6 +1218,7 @@ static util::Result CreateTransactionInternal( // behavior." bool use_anti_fee_sniping = true; const uint32_t default_sequence{coin_control.m_signal_bip125_rbf.value_or(wallet.m_signal_rbf) ? MAX_BIP125_RBF_SEQUENCE : CTxIn::MAX_SEQUENCE_NONFINAL}; + txNew.vin.reserve(selected_coins.size()); for (const auto& coin : selected_coins) { std::optional sequence = coin_control.GetSequence(coin->outpoint); if (sequence) { diff --git a/test/functional/README.md b/test/functional/README.md index a4994f2e7c975..a34bf1827cbcf 100644 --- a/test/functional/README.md +++ b/test/functional/README.md @@ -10,7 +10,8 @@ that file and modify to fit your needs. #### Coverage -Running `test/functional/test_runner.py` with the `--coverage` argument tracks which RPCs are +Assuming the build directory is `build`, +running `build/test/functional/test_runner.py` with the `--coverage` argument tracks which RPCs are called by the tests and prints a report of uncovered RPCs in the summary. This can be used (along with the `--extended` argument) to find out which RPCs we don't have test cases for. diff --git a/test/util/test_runner.py b/test/util/test_runner.py index e4a77d53d6eed..cac184ca302f3 100644 --- a/test/util/test_runner.py +++ b/test/util/test_runner.py @@ -83,13 +83,11 @@ def bctest(testDir, testObj, buildenv): execrun = [execprog] + execargs # Read the input data (if there is any) - stdinCfg = None inputData = None if "input" in testObj: filename = os.path.join(testDir, testObj["input"]) with open(filename, encoding="utf8") as f: inputData = f.read() - stdinCfg = subprocess.PIPE # Read the expected output data (if there is any) outputFn = None @@ -112,9 +110,8 @@ def bctest(testDir, testObj, buildenv): raise Exception # Run the test - proc = subprocess.Popen(execrun, stdin=stdinCfg, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) try: - outs = proc.communicate(input=inputData) + res = subprocess.run(execrun, capture_output=True, text=True, input=inputData) except OSError: logging.error("OSError, Failed to execute " + execprog) raise @@ -123,9 +120,9 @@ def bctest(testDir, testObj, buildenv): data_mismatch, formatting_mismatch = False, False # Parse command output and expected output try: - a_parsed = parse_output(outs[0], outputType) + a_parsed = parse_output(res.stdout, outputType) except Exception as e: - logging.error('Error parsing command output as %s: %s' % (outputType, e)) + logging.error(f"Error parsing command output as {outputType}: '{str(e)}'; res: {str(res)}") raise try: b_parsed = parse_output(outputData, outputType) @@ -134,13 +131,13 @@ def bctest(testDir, testObj, buildenv): raise # Compare data if a_parsed != b_parsed: - logging.error("Output data mismatch for " + outputFn + " (format " + outputType + ")") + logging.error(f"Output data mismatch for {outputFn} (format {outputType}); res: {str(res)}") data_mismatch = True # Compare formatting - if outs[0] != outputData: - error_message = "Output formatting mismatch for " + outputFn + ":\n" + if res.stdout != outputData: + error_message = f"Output formatting mismatch for {outputFn}:\nres: {str(res)}\n" error_message += "".join(difflib.context_diff(outputData.splitlines(True), - outs[0].splitlines(True), + res.stdout.splitlines(True), fromfile=outputFn, tofile="returned")) logging.error(error_message) @@ -152,8 +149,8 @@ def bctest(testDir, testObj, buildenv): wantRC = 0 if "return_code" in testObj: wantRC = testObj['return_code'] - if proc.returncode != wantRC: - logging.error("Return code mismatch for " + outputFn) + if res.returncode != wantRC: + logging.error(f"Return code mismatch for {outputFn}; res: {str(res)}") raise Exception if "error_txt" in testObj: @@ -164,8 +161,8 @@ def bctest(testDir, testObj, buildenv): # emits DISPLAY errors when running as a windows application on # linux through wine. Just assert that the expected error text appears # somewhere in stderr. - if want_error not in outs[1]: - logging.error("Error mismatch:\n" + "Expected: " + want_error + "\nReceived: " + outs[1].rstrip()) + if want_error not in res.stderr: + logging.error(f"Error mismatch:\nExpected: {want_error}\nReceived: {res.stderr.rstrip()}\nres: {str(res)}") raise Exception def parse_output(a, fmt):