diff --git a/.cirrus.yml b/.cirrus.yml deleted file mode 100644 index 3170c4cccc9..00000000000 --- a/.cirrus.yml +++ /dev/null @@ -1,339 +0,0 @@ -env: # Global defaults - SECP256K1_TEST_ITERS: 16 # ELEMENTS: avoid test timeouts on arm - PACKAGE_MANAGER_INSTALL: "apt-get update && apt-get install -y" - MAKEJOBS: "-j3" # ELEMENTS: reduced from j4 - TEST_RUNNER_PORT_MIN: "14000" # Must be larger than 12321, which is used for the http cache. See https://cirrus-ci.org/guide/writing-tasks/#http-cache - CCACHE_SIZE: "200M" - CCACHE_DIR: "/tmp/ccache_dir" - CCACHE_NOHASHDIR: "1" # Debug info might contain a stale path if the build dir changes, but this is fine - -cirrus_ephemeral_worker_template_env: &CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV - DANGER_RUN_CI_ON_HOST: "1" # Containers will be discarded after the run, so there is no risk that the ci scripts modify the system - -persistent_worker_template_env: &PERSISTENT_WORKER_TEMPLATE_ENV - RESTART_CI_DOCKER_BEFORE_RUN: "1" - -persistent_worker_template: &PERSISTENT_WORKER_TEMPLATE - persistent_worker: {} # https://cirrus-ci.org/guide/persistent-workers/ - -# https://cirrus-ci.org/guide/tips-and-tricks/#sharing-configuration-between-tasks -filter_template: &FILTER_TEMPLATE - skip: $CIRRUS_REPO_FULL_NAME == "bitcoin-core/gui" && $CIRRUS_PR == "" # No need to run on the read-only mirror, unless it is a PR. https://cirrus-ci.org/guide/writing-tasks/#conditional-task-execution - stateful: false # https://cirrus-ci.org/guide/writing-tasks/#stateful-tasks - -base_template: &BASE_TEMPLATE - << : *FILTER_TEMPLATE - merge_base_script: - # Unconditionally install git (used in fingerprint_script) and set the - # default git author name (used in verify-commits.py) - - bash -c "$PACKAGE_MANAGER_INSTALL git" - - git config --global user.email "ci@ci.ci" - - git config --global user.name "ci" - - if [ "$CIRRUS_PR" = "" ]; then exit 0; fi - - git fetch $CIRRUS_REPO_CLONE_URL $CIRRUS_BASE_BRANCH - - git merge FETCH_HEAD # Merge base to detect silent merge conflicts - -main_template: &MAIN_TEMPLATE - timeout_in: 120m # https://cirrus-ci.org/faq/#instance-timed-out - ccache_cache: - folder: "/tmp/ccache_dir" - ci_script: - - ./ci/test_run_all.sh - -global_task_template: &GLOBAL_TASK_TEMPLATE - << : *BASE_TEMPLATE - container: - # https://cirrus-ci.org/faq/#are-there-any-limits - # Each project has 16 CPU in total, assign 2 to each container, so that 8 tasks run in parallel - cpu: 2 - greedy: true - memory: 8G # Set to 8GB to avoid OOM. https://cirrus-ci.org/guide/linux/#linux-containers - depends_built_cache: - folder: "depends/built" - fingerprint_script: echo $CIRRUS_TASK_NAME $(git rev-list -1 HEAD ./depends) - << : *MAIN_TEMPLATE - -macos_native_task_template: &MACOS_NATIVE_TASK_TEMPLATE - << : *BASE_TEMPLATE - check_clang_script: - - clang --version - brew_install_script: - - brew install boost@1.85 libevent qt@5 miniupnpc libnatpmp ccache zeromq qrencode libtool automake gnu-getopt - - brew link --force --overwrite boost@1.85 - << : *MAIN_TEMPLATE - -compute_credits_template: &CREDITS_TEMPLATE - # https://cirrus-ci.org/pricing/#compute-credits - # Only use credits for pull requests to the main repo - use_compute_credits: $CIRRUS_REPO_FULL_NAME == 'ElementsProject/elements' && $CIRRUS_PR != "" - -task: - name: 'lint [bionic]' - << : *BASE_TEMPLATE - container: - image: ubuntu:bionic # For python 3.6, oldest supported version according to doc/dependencies.md - cpu: 1 - memory: 1G - # For faster CI feedback, immediately schedule the linters - << : *CREDITS_TEMPLATE - lint_script: - - ./ci/lint_run_all.sh - env: - << : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV - -win64_native_common: &win64_native_common - << : *FILTER_TEMPLATE - windows_container: - cpu: 4 - memory: 8G - image: cirrusci/windowsservercore:visualstudio2019 - timeout_in: 120m - env: - PATH: 'C:\jom;C:\Python39;C:\Python39\Scripts;C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin;%PATH%' - PYTHONUTF8: 1 - CI_VCPKG_TAG: '2021.05.12' - VCPKG_DOWNLOADS: 'C:\Users\ContainerAdministrator\AppData\Local\vcpkg\downloads' - VCPKG_DEFAULT_BINARY_CACHE: 'C:\Users\ContainerAdministrator\AppData\Local\vcpkg\archives' - QT_DOWNLOAD_URL: 'https://download.qt.io/archive/qt/5.15/5.15.3/single/qt-everywhere-opensource-src-5.15.3.zip' - QT_LOCAL_PATH: 'C:\qt-everywhere-opensource-src-5.15.3.zip' - QT_SOURCE_DIR: 'C:\qt-everywhere-src-5.15.3' - QTBASEDIR: 'C:\Qt_static' - x64_NATIVE_TOOLS: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat"' - IgnoreWarnIntDirInTempDetected: 'true' - merge_script: - - git config --global user.email "ci@ci.ci" - - git config --global user.name "ci" - # Windows filesystem loses the executable bit, and all of the executable - # files are considered "modified" now. It will break the following `git merge` - # command. The next two commands make git ignore this issue. - - git config core.filemode false - - git reset --hard - - PowerShell -NoLogo -Command if ($env:CIRRUS_PR -ne $null) { git fetch $env:CIRRUS_REPO_CLONE_URL $env:CIRRUS_BASE_BRANCH; git merge FETCH_HEAD; } - msvc_qt_built_cache: - folder: "%QTBASEDIR%" - reupload_on_changes: false - fingerprint_script: - - echo %QT_DOWNLOAD_URL% - - msbuild -version - populate_script: - - curl -L -o C:\jom.zip https://download.qt.io/official_releases/jom/jom_1_1_2.zip - - mkdir C:\jom - - tar -xf C:\jom.zip -C C:\jom - - curl -L -o %QT_LOCAL_PATH% %QT_DOWNLOAD_URL% - - tar -xf %QT_LOCAL_PATH% -C C:\ - - '%x64_NATIVE_TOOLS%' - - cd %QT_SOURCE_DIR% - - mkdir build - - cd build - - ..\configure -release -silent -opensource -confirm-license -opengl desktop -static -static-runtime -mp -qt-zlib -qt-pcre -qt-libpng -nomake examples -nomake tests -nomake tools -no-angle -no-dbus -no-gif -no-gtk -no-ico -no-icu -no-libjpeg -no-libudev -no-sql-sqlite -no-sql-odbc -no-sqlite -no-vulkan -skip qt3d -skip qtactiveqt -skip qtandroidextras -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdeclarative -skip doc -skip qtdoc -skip qtgamepad -skip qtgraphicaleffects -skip qtimageformats -skip qtlocation -skip qtlottie -skip qtmacextras -skip qtmultimedia -skip qtnetworkauth -skip qtpurchasing -skip qtquick3d -skip qtquickcontrols -skip qtquickcontrols2 -skip qtquicktimeline -skip qtremoteobjects -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qtsvg -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebglplugin -skip qtwebsockets -skip qtwebview -skip qtx11extras -skip qtxmlpatterns -no-openssl -no-feature-bearermanagement -no-feature-printdialog -no-feature-printer -no-feature-printpreviewdialog -no-feature-printpreviewwidget -no-feature-sql -no-feature-sqlmodel -no-feature-textbrowser -no-feature-textmarkdownwriter -no-feature-textodfwriter -no-feature-xml -prefix %QTBASEDIR% - - jom - - jom install - vcpkg_tools_cache: - folder: '%VCPKG_DOWNLOADS%\tools' - reupload_on_changes: false - fingerprint_script: - - echo %CI_VCPKG_TAG% - - msbuild -version - vcpkg_binary_cache: - folder: '%VCPKG_DEFAULT_BINARY_CACHE%' - reupload_on_changes: true - fingerprint_script: - - echo %CI_VCPKG_TAG% - - msbuild -version - populate_script: - - mkdir %VCPKG_DEFAULT_BINARY_CACHE% - install_python_script: - - choco install --yes --no-progress python3 --version=3.9.6 - - pip install zmq - - python -VV - install_vcpkg_script: - - cd .. - - git clone --quiet https://github.com/microsoft/vcpkg.git - - cd vcpkg - - git -c advice.detachedHead=false checkout %CI_VCPKG_TAG% - - .\bootstrap-vcpkg -disableMetrics - - echo set(VCPKG_BUILD_TYPE release) >> triplets\x64-windows-static.cmake - - .\vcpkg integrate install - - .\vcpkg version - build_script: - - cd %CIRRUS_WORKING_DIR% - - python build_msvc\msvc-autogen.py - - msbuild build_msvc\bitcoin.sln -property:Configuration=Release -maxCpuCount -verbosity:minimal -noLogo - -task: - name: "Win64 native [msvc] (Short running functional tests)" - <<: *win64_native_common - functional_tests_script: - # Increase the dynamic port range to the maximum allowed value to mitigate "OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted". - # See: https://docs.microsoft.com/en-us/biztalk/technical-guides/settings-that-can-be-modified-to-improve-network-performance - - netsh int ipv4 set dynamicport tcp start=1025 num=64511 - - netsh int ipv6 set dynamicport tcp start=1025 num=64511 - # Heavier tests are moved to a secondary task - # Exclude feature_dbcrash and feature_fee_estimation, failing https://github.com/ElementsProject/elements/pull/1298 - - python test\functional\test_runner.py --nocleanup --ci --quiet --combinedlogslen=4000 --jobs=4 --timeout-factor=8 --extended --exclude wallet_avoidreuse,feature_trim_headers,feature_dbcrash,feature_fee_estimation - -task: - name: "Win64 native [msvc] (Long running functional tests + unit tests)" - <<: *win64_native_common - unit_tests_script: - - src\test_elements.exe -l test_suite - - src\bench_elements.exe > NUL - - python test\util\test_runner.py - - python test\util\rpcauth-test.py - functional_tests_script: - # Increase the dynamic port range to the maximum allowed value to mitigate "OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted". - # See: https://docs.microsoft.com/en-us/biztalk/technical-guides/settings-that-can-be-modified-to-improve-network-performance - - netsh int ipv4 set dynamicport tcp start=1025 num=64511 - - netsh int ipv6 set dynamicport tcp start=1025 num=64511 - # Execute tests excluded from the main task - # Ignore failures for now until https://github.com/ElementsProject/elements/pull/1298 is merged - - python test\functional\test_runner.py --nocleanup --ci --quiet --combinedlogslen=4000 --jobs=4 --timeout-factor=8 wallet_avoidreuse feature_trim_headers feature_dbcrash feature_fee_estimation || true - -task: - name: 'ARM [unit tests, no functional tests] [bullseye]' - << : *GLOBAL_TASK_TEMPLATE - container: - image: debian:bullseye - docker_arguments: - CI_IMAGE_NAME_TAG: debian:bullseye - << : *CREDITS_TEMPLATE - env: - << : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV - FILE_ENV: "./ci/test/00_setup_env_arm.sh" - -task: - name: 'Win64 [unit tests, no gui tests, no boost::process, no functional tests] [jammy]' - << : *GLOBAL_TASK_TEMPLATE - container: - image: ubuntu:jammy - env: - << : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV - FILE_ENV: "./ci/test/00_setup_env_win64.sh" - -task: - name: '32-bit + dash [gui] [Rocky 8]' - << : *GLOBAL_TASK_TEMPLATE - container: - image: quay.io/rockylinux/rockylinux:8 - env: - << : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV - PACKAGE_MANAGER_INSTALL: "yum install -y" - FILE_ENV: "./ci/test/00_setup_env_i686_centos.sh" - -task: - name: '[previous releases, uses qt5 dev package and some depends packages, DEBUG] [unsigned char] [bionic]' - previous_releases_cache: - folder: "releases" - << : *GLOBAL_TASK_TEMPLATE - << : *PERSISTENT_WORKER_TEMPLATE - env: - << : *PERSISTENT_WORKER_TEMPLATE_ENV - FILE_ENV: "./ci/test/00_setup_env_native_qt5.sh" - -task: - name: '[TSan, depends, gui] [2404]' - << : *GLOBAL_TASK_TEMPLATE - container: - image: ubuntu:24.04 - cpu: 6 # Increase CPU and Memory to avoid timeout - memory: 24G - env: - << : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV - FILE_ENV: "./ci/test/00_setup_env_native_tsan.sh" - MAKEJOBS: "-j2" # Avoid excessive memory use due to MSan - -task: - name: '[MSan, depends] [focal]' - << : *GLOBAL_TASK_TEMPLATE - container: - image: ubuntu:focal - env: - << : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV - FILE_ENV: "./ci/test/00_setup_env_native_msan.sh" - -task: - name: '[ASan + LSan + UBSan + integer, no depends] [jammy]' - << : *GLOBAL_TASK_TEMPLATE - container: - image: ubuntu:jammy - memory: 16G # ELEMENTS: need more memory - cpu: 4 # ELEMENTS: cirrus wants more CPUs if you want more memory - env: - << : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV - FILE_ENV: "./ci/test/00_setup_env_native_asan.sh" - -task: - name: '[fuzzer,address,undefined,integer, no depends] [jammy]' - << : *GLOBAL_TASK_TEMPLATE - container: - image: ubuntu:jammy - cpu: 8 # Increase CPU and memory to avoid timeout - memory: 16G - env: - << : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV - FILE_ENV: "./ci/test/00_setup_env_native_fuzz.sh" - -task: - name: '[multiprocess, i686, DEBUG] [focal]' - # Disable for Elements for now; Multiprocess build is not supported or tested and fails CI. - only_if: false - << : *GLOBAL_TASK_TEMPLATE - container: - image: ubuntu:focal - cpu: 4 - memory: 16G # The default memory is sometimes just a bit too small, so double everything - env: - << : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV - FILE_ENV: "./ci/test/00_setup_env_i686_multiprocess.sh" - -task: - name: '[no wallet] [bionic]' - << : *GLOBAL_TASK_TEMPLATE - container: - image: ubuntu:bionic - env: - << : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV - FILE_ENV: "./ci/test/00_setup_env_native_nowallet.sh" - -task: - name: 'macOS 10.15 [gui, no tests] [focal]' - << : *BASE_TEMPLATE - macos_sdk_cache: - folder: "depends/SDKs/$MACOS_SDK" - fingerprint_key: "$MACOS_SDK" - << : *MAIN_TEMPLATE - container: - image: ubuntu:focal - env: - MACOS_SDK: "Xcode-12.2-12B45b-extracted-SDK-with-libcxx-headers" - << : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV - FILE_ENV: "./ci/test/00_setup_env_mac.sh" - -task: - name: 'macOS 13 native arm64 [gui, sqlite only] [no depends]' - macos_instance: - # Use latest image, but hardcode version to avoid silent upgrades (and breaks) - image: ghcr.io/cirruslabs/macos-runner:sequoia # https://cirrus-ci.org/guide/macOS - << : *MACOS_NATIVE_TASK_TEMPLATE - env: - << : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV - CI_USE_APT_INSTALL: "no" - PACKAGE_MANAGER_INSTALL: "echo" # Nothing to do - FILE_ENV: "./ci/test/00_setup_env_mac_native_arm64.sh" - -task: - name: 'ARM64 Android APK [focal]' - # Disable for Elements; Android build is broken and unsupported. - only_if: false - android_sdk_cache: - folder: "depends/SDKs/android" - fingerprint_key: "ANDROID_API_LEVEL=28 ANDROID_BUILD_TOOLS_VERSION=28.0.3 ANDROID_NDK_VERSION=23.1.7779620" - depends_sources_cache: - folder: "depends/sources" - fingerprint_script: git rev-list -1 HEAD ./depends - << : *MAIN_TEMPLATE - container: - image: ubuntu:focal - env: - << : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV - FILE_ENV: "./ci/test/00_setup_env_android.sh" diff --git a/.github/actions/clear-files/action.yml b/.github/actions/clear-files/action.yml new file mode 100644 index 00000000000..0008f825ff0 --- /dev/null +++ b/.github/actions/clear-files/action.yml @@ -0,0 +1,12 @@ +name: 'Clear unnecessary files' +description: 'Clear out unnecessary files to make space on the VM' +runs: + using: 'composite' + steps: + - name: Clear unnecessary files + shell: bash + env: + DEBIAN_FRONTEND: noninteractive + run: | + set +o errexit + sudo bash -c '(ionice -c 3 nice -n 19 rm -rf /usr/share/dotnet/ /usr/local/graalvm/ /usr/local/.ghcup/ /usr/local/share/powershell /usr/local/share/chromium /usr/local/lib/android /usr/local/lib/node_modules)&' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000000..8ced796b8e5 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,719 @@ +# GitHub Actions CI workflow for ElementsProject/elements + +name: CI +on: + # See: https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request. + pull_request: + # See: https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#push. + push: + branches: + - '**' + tags-ignore: + - '**' + +# Cancel in-progress runs for the same branch/PR +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + SECP256K1_TEST_ITERS: 16 # ELEMENTS: avoid test timeouts on arm + PACKAGE_MANAGER_INSTALL: "sudo apt-get update && apt-get install -y" + MAKEJOBS: "-j3" # ELEMENTS: reduced from -j4 + TEST_RUNNER_PORT_MIN: "14000" # Must be > 12321 (used for http cache) + CCACHE_SIZE: "200M" + CCACHE_DIR: "/tmp/ccache_dir" + CCACHE_NOHASHDIR: "1" + # On forks this variable is not matched so jobs fall back to free GH runners. + REPO_USE_CIRRUS_RUNNERS: "ElementsProject/elements" + +jobs: + + # ------------------------------------------------------------------------- + # Lint + # Image: ubuntu:focal (Python 3.6, oldest supported per doc/dependencies.md) + # ------------------------------------------------------------------------- + lint: + name: 'lint [focal]' + runs-on: ubuntu-latest + timeout-minutes: 120 + env: + FILE_ENV: "./ci/test/00_setup_env_lint.sh" + DANGER_RUN_CI_ON_HOST: "" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Run CI + run: ./ci/test_run_all.sh + + # ------------------------------------------------------------------------- + # ARM unit tests (no functional tests) + # Image: debian:bullseye + # ------------------------------------------------------------------------- + arm-unit-tests: + name: 'ARM [unit tests, no functional tests] [bullseye]' + runs-on: ubuntu-latest + timeout-minutes: 120 + env: + FILE_ENV: "./ci/test/00_setup_env_arm.sh" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Restore ccache + uses: actions/cache/restore@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-arm-unit-tests-${{ github.sha }} + restore-keys: ccache-arm-unit-tests- + + - name: Restore depends/built cache + uses: actions/cache/restore@v4 + with: + path: depends/built + key: depends-built-arm-unit-tests-${{ hashFiles('depends/**') }}-${{ hashFiles('ci/test/00_setup_env_arm.sh') }} + restore-keys: depends-built-arm-unit-tests-${{ hashFiles('depends/**') }}- + + - name: Run CI + run: ./ci/test_run_all.sh + + - name: Save ccache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-arm-unit-tests-${{ github.sha }} + + - name: Save depends/built cache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: depends/built + key: depends-built-arm-unit-tests-${{ hashFiles('depends/**') }}-${{ hashFiles('ci/test/00_setup_env_arm.sh') }} + + # ------------------------------------------------------------------------- + # Win64 cross-compile (unit tests, no gui tests, no boost::process, + # no functional tests) + # Image: ubuntu:jammy + # ------------------------------------------------------------------------- + win64-cross: + name: 'Win64 [unit tests, no gui tests, no boost::process, no functional tests] [jammy]' + runs-on: ubuntu-latest + timeout-minutes: 120 + env: + FILE_ENV: "./ci/test/00_setup_env_win64.sh" + RUN_UNIT_TESTS: "false" # Wine-based unit tests unreliable on GHA + RUN_FUNCTIONAL_TESTS: "false" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Restore ccache + uses: actions/cache/restore@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-win64-cross-${{ github.sha }} + restore-keys: ccache-win64-cross- + + - name: Restore depends/built cache + uses: actions/cache/restore@v4 + with: + path: depends/built + key: depends-built-win64-cross-${{ hashFiles('depends/**', 'ci/test/00_setup_env_win64.sh') }} + restore-keys: depends-built-win64-cross- + + - name: Run CI + run: ./ci/test_run_all.sh + + - name: Save ccache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-win64-cross-${{ github.sha }} + + - name: Save depends/built cache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: depends/built + key: depends-built-win64-cross-${{ hashFiles('depends/**', 'ci/test/00_setup_env_win64.sh') }} + + # ------------------------------------------------------------------------- + # 32-bit + dash (GUI) + # Image: rockylinux:8 + # ------------------------------------------------------------------------- + i686-centos: + name: '32-bit + dash [gui] [Rocky 8]' + runs-on: ubuntu-latest + timeout-minutes: 180 + env: + PACKAGE_MANAGER_INSTALL: "yum install -y" + FILE_ENV: "./ci/test/00_setup_env_i686_centos.sh" + TEST_RUNNER_EXTRA: "--exclude feature_proxy.py,rpc_bind.py" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Restore ccache + uses: actions/cache/restore@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-i686-centos-${{ github.sha }} + restore-keys: ccache-i686-centos- + + - name: Restore depends/built cache + uses: actions/cache/restore@v4 + with: + path: depends/built + key: depends-built-i686-centos-${{ hashFiles('depends/**', 'ci/test/00_setup_env_i686_centos.sh') }} + restore-keys: depends-built-i686-centos- + + - name: Run CI + run: ./ci/test_run_all.sh + + - name: Save ccache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-i686-centos-${{ github.sha }} + + - name: Save depends/built cache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: depends/built + key: depends-built-i686-centos-${{ hashFiles('depends/**', 'ci/test/00_setup_env_i686_centos.sh') }} + + # ------------------------------------------------------------------------- + # TSan + depends + gui + # Image: ubuntu:24.04 (needs extra CPU/memory - 6 CPU, 24 GB in Cirrus) + # ------------------------------------------------------------------------- + tsan: + name: '[TSan, depends, gui] [2404]' + runs-on: ubuntu-latest + timeout-minutes: 120 + env: + FILE_ENV: "./ci/test/00_setup_env_native_tsan.sh" + MAKEJOBS: "-j2" # Avoid excessive memory use + TEST_RUNNER_EXTRA: "--exclude feature_proxy.py,rpc_bind.py" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Restore ccache + uses: actions/cache/restore@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-tsan-${{ github.sha }} + restore-keys: ccache-tsan- + + - name: Restore depends/built cache + uses: actions/cache/restore@v4 + with: + path: depends/built + key: depends-built-tsan-${{ hashFiles('depends/**', 'ci/test/00_setup_env_native_tsan.sh') }} + restore-keys: depends-built-tsan- + + - name: Run CI + run: ./ci/test_run_all.sh + + - name: Save ccache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-tsan-${{ github.sha }} + + - name: Save depends/built cache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: depends/built + key: depends-built-tsan-${{ hashFiles('depends/**', 'ci/test/00_setup_env_native_tsan.sh') }} + + # ------------------------------------------------------------------------- + # MSan + depends + # Image: ubuntu:focal + # ------------------------------------------------------------------------- + msan: + name: '[MSan, depends] [focal]' + runs-on: ubuntu-latest + timeout-minutes: 300 + env: + FILE_ENV: "./ci/test/00_setup_env_native_msan.sh" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Restore ccache + uses: actions/cache/restore@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-msan-${{ github.sha }} + restore-keys: ccache-msan- + + - name: Restore depends/built cache + uses: actions/cache/restore@v4 + with: + path: depends/built + key: depends-built-msan-${{ hashFiles('depends/**', 'ci/test/00_setup_env_native_msan.sh') }} + restore-keys: depends-built-msan- + + - name: Run CI + run: ./ci/test_run_all.sh + + - name: Save ccache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-msan-${{ github.sha }} + + - name: Save depends/built cache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: depends/built + key: depends-built-msan-${{ hashFiles('depends/**', 'ci/test/00_setup_env_native_msan.sh') }} + + # ------------------------------------------------------------------------- + # ASan + LSan + UBSan + integer (no depends) + # Image: ubuntu:jammy (needs 16 GB RAM - ELEMENTS-specific increase) + # ------------------------------------------------------------------------- + asan-lsan-ubsan-integer: + name: '[ASan + LSan + UBSan + integer, no depends] [jammy]' + runs-on: ubuntu-latest + timeout-minutes: 120 + env: + FILE_ENV: "./ci/test/00_setup_env_native_asan.sh" + TEST_RUNNER_EXTRA: "--exclude feature_proxy.py,rpc_bind.py" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Restore ccache + uses: actions/cache/restore@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-asan-${{ github.sha }} + restore-keys: ccache-asan- + + - name: Restore depends/built cache + uses: actions/cache/restore@v4 + with: + path: depends/built + key: depends-built-asan-${{ hashFiles('depends/**', 'ci/test/00_setup_env_native_asan.sh') }} + restore-keys: depends-built-asan- + + - name: Run CI + run: ./ci/test_run_all.sh + + - name: Save ccache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-asan-${{ github.sha }} + + - name: Save depends/built cache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: depends/built + key: depends-built-asan-${{ hashFiles('depends/**', 'ci/test/00_setup_env_native_asan.sh') }} + + # ------------------------------------------------------------------------- + # Fuzzer (address, undefined, integer; no depends) + # Image: ubuntu:jammy (8 CPU, 16 GB in Cirrus) + # ------------------------------------------------------------------------- + fuzzer: + name: '[fuzzer,address,undefined,integer, no depends] [jammy]' + runs-on: ubuntu-latest + timeout-minutes: 120 + env: + FILE_ENV: "./ci/test/00_setup_env_native_fuzz.sh" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Restore ccache + uses: actions/cache/restore@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-fuzzer-${{ github.sha }} + restore-keys: ccache-fuzzer- + + - name: Restore depends/built cache + uses: actions/cache/restore@v4 + with: + path: depends/built + key: depends-built-fuzzer-${{ hashFiles('depends/**', 'ci/test/00_setup_env_native_fuzz.sh') }} + restore-keys: depends-built-fuzzer- + + - name: Run CI + run: ./ci/test_run_all.sh + + - name: Save ccache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-fuzzer-${{ github.sha }} + + - name: Save depends/built cache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: depends/built + key: depends-built-fuzzer-${{ hashFiles('depends/**', 'ci/test/00_setup_env_native_fuzz.sh') }} + + # ------------------------------------------------------------------------- + # No wallet + # Image: ubuntu:bionic + # ------------------------------------------------------------------------- + no-wallet: + name: '[no wallet] [bionic]' + runs-on: ubuntu-latest + timeout-minutes: 120 + env: + FILE_ENV: "./ci/test/00_setup_env_native_nowallet.sh" + TEST_RUNNER_EXTRA: "--exclude feature_proxy.py,rpc_bind.py" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Restore ccache + uses: actions/cache/restore@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-no-wallet-${{ github.sha }} + restore-keys: ccache-no-wallet- + + - name: Restore depends/built cache + uses: actions/cache/restore@v4 + with: + path: depends/built + key: depends-built-no-wallet-${{ hashFiles('depends/**') }}-${{ hashFiles('ci/test/00_setup_env_native_nowallet.sh') }} + restore-keys: depends-built-no-wallet-${{ hashFiles('depends/**') }}- + + - name: Run CI + run: ./ci/test_run_all.sh + + - name: Save ccache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-no-wallet-${{ github.sha }} + + - name: Save depends/built cache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: depends/built + key: depends-built-no-wallet-${{ hashFiles('depends/**') }}-${{ hashFiles('ci/test/00_setup_env_native_nowallet.sh') }} + + # ------------------------------------------------------------------------- + # macOS 10.15 cross-compile (gui, no tests) + # Image: ubuntu:focal (cross-compiles targeting macOS) + # ------------------------------------------------------------------------- + macos-cross: + name: 'macOS 10.15 [gui, no tests] [focal]' + runs-on: ubuntu-latest + timeout-minutes: 120 + env: + MACOS_SDK: "Xcode-12.2-12B45b-extracted-SDK-with-libcxx-headers" + FILE_ENV: "./ci/test/00_setup_env_mac.sh" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Restore macOS SDK cache + uses: actions/cache/restore@v4 + with: + path: depends/SDKs/${{ env.MACOS_SDK }} + key: macos-sdk-${{ env.MACOS_SDK }} + + - name: Restore ccache + uses: actions/cache/restore@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-macos-cross-${{ github.sha }} + restore-keys: ccache-macos-cross- + + - name: Restore depends/built cache + uses: actions/cache/restore@v4 + with: + path: depends/built + key: depends-built-macos-cross-${{ hashFiles('depends/packages/**', 'depends/Makefile') }}-${{ hashFiles('ci/test/00_setup_env_mac.sh') }} + restore-keys: depends-built-macos-cross- + + - name: Run CI + run: ./ci/test_run_all.sh + + - name: Save macOS SDK cache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: depends/SDKs/${{ env.MACOS_SDK }} + key: macos-sdk-${{ env.MACOS_SDK }} + + - name: Save ccache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-macos-cross-${{ github.sha }} + + - name: Save depends/built cache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: depends/built + key: depends-built-macos-cross-${{ hashFiles('depends/packages/**', 'depends/Makefile') }}-${{ hashFiles('ci/test/00_setup_env_mac.sh') }} + + # ------------------------------------------------------------------------- + # macOS 13 native arm64 (gui, sqlite only, no depends) + # Runner: macos-14 (Apple Silicon, equivalent to Cirrus macos-runner:sequoia) + # ------------------------------------------------------------------------- + macos-native-arm64: + name: 'macOS 13 native arm64 [gui, sqlite only] [no depends]' + runs-on: macos-14 + timeout-minutes: 120 + env: + FILE_ENV: "./ci/test/00_setup_env_mac_native_arm64.sh" + CI_USE_APT_INSTALL: "no" + PACKAGE_MANAGER_INSTALL: "echo" # Nothing to install via apt + DANGER_RUN_CI_ON_HOST: "1" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check clang version + run: clang --version + + - name: Install brew dependencies + run: | + brew install boost@1.85 libevent qt@5 miniupnpc libnatpmp ccache \ + zeromq qrencode libtool automake gnu-getopt + brew link --force --overwrite boost@1.85 + + - name: Restore ccache + uses: actions/cache/restore@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-macos-native-arm64-${{ github.sha }} + restore-keys: ccache-macos-native-arm64- + + - name: Run CI + run: ./ci/test_run_all.sh + + - name: Save ccache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-macos-native-arm64-${{ github.sha }} + +# ------------------------------------------------------------------------- + # Win64 native MSVC - functional tests + unit tests + # Runner: windows-2022 + # ------------------------------------------------------------------------- + win64-msvc: + name: 'Win64 native [msvc] (functional tests + unit tests)' + runs-on: windows-2022 + timeout-minutes: 360 + env: + PYTHONUTF8: 1 + CI_VCPKG_TAG: '2021.05.12' + VCPKG_ROOT: 'D:\a\elements\vcpkg' + VCPKG_DEFAULT_BINARY_CACHE: 'C:\Users\runneradmin\AppData\Local\vcpkg\archives' + QT_DOWNLOAD_URL: 'https://download.qt.io/archive/qt/5.15/5.15.3/single/qt-everywhere-opensource-src-5.15.3.zip' + QT_LOCAL_PATH: 'C:\qt-everywhere-opensource-src-5.15.3.zip' + QT_SOURCE_DIR: 'C:\qt-everywhere-src-5.15.3' + QTBASEDIR: 'C:\Qt_static' + IgnoreWarnIntDirInTempDetected: 'true' + DANGER_RUN_CI_ON_HOST: "1" + defaults: + run: + shell: cmd + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Restore Qt static cache + id: qt-cache + uses: actions/cache@v5 + with: + path: ${{ env.QTBASEDIR }} + key: qt-static-${{ env.QT_DOWNLOAD_URL }}-${{ runner.os }} + + - name: Install jom + if: steps.qt-cache.outputs.cache-hit != 'true' + run: | + curl -L -o C:\jom.zip https://download.qt.io/official_releases/jom/jom_1_1_2.zip + mkdir C:\jom + tar -xf C:\jom.zip -C C:\jom + + - name: Build Qt static + if: steps.qt-cache.outputs.cache-hit != 'true' + shell: pwsh + run: | + curl -L -o $env:QT_LOCAL_PATH $env:QT_DOWNLOAD_URL + Write-Host "Extracting Qt source..." + tar -xf $env:QT_LOCAL_PATH -C C:\ + $vsPath = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" ` + -latest -property installationPath + Write-Host "Using VS at: $vsPath" + cmd /c "`"$vsPath\VC\Auxiliary\Build\vcvars64.bat`" -vcvars_ver=14.29 && cd /d $env:QT_SOURCE_DIR && mkdir build && cd build && ..\configure -release -silent -opensource -confirm-license -opengl desktop -static -static-runtime -mp -qt-zlib -qt-pcre -qt-libpng -nomake examples -nomake tests -nomake tools -no-angle -no-dbus -no-gif -no-gtk -no-ico -no-icu -no-libjpeg -no-libudev -no-sql-sqlite -no-sql-odbc -no-sqlite -no-vulkan -skip qt3d -skip qtactiveqt -skip qtandroidextras -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdeclarative -skip doc -skip qtdoc -skip qtgamepad -skip qtgraphicaleffects -skip qtimageformats -skip qtlocation -skip qtlottie -skip qtmacextras -skip qtmultimedia -skip qtnetworkauth -skip qtpurchasing -skip qtquick3d -skip qtquickcontrols -skip qtquickcontrols2 -skip qtquicktimeline -skip qtremoteobjects -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qtsvg -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebglplugin -skip qtwebsockets -skip qtwebview -skip qtx11extras -skip qtxmlpatterns -no-openssl -no-feature-bearermanagement -no-feature-printdialog -no-feature-printer -no-feature-printpreviewdialog -no-feature-printpreviewwidget -no-feature-sql -no-feature-sqlmodel -no-feature-textbrowser -no-feature-textmarkdownwriter -no-feature-textodfwriter -no-feature-xml -prefix $env:QTBASEDIR && C:\jom\jom.exe && C:\jom\jom.exe install" + + - name: Restore vcpkg tools cache + uses: actions/cache@v5 + with: + path: ${{ env.VCPKG_ROOT }}\downloads\tools + key: vcpkg-tools-${{ env.CI_VCPKG_TAG }}-${{ runner.os }} + + - name: Restore vcpkg binary cache + uses: actions/cache@v5 + with: + path: ${{ env.VCPKG_DEFAULT_BINARY_CACHE }} + key: vcpkg-binary-${{ env.CI_VCPKG_TAG }}-${{ runner.os }}-${{ github.sha }} + restore-keys: vcpkg-binary-${{ env.CI_VCPKG_TAG }}-${{ runner.os }}- + + - name: Install Python and pip packages + run: | + choco install --yes --no-progress python3 --version=3.9.6 + pip install zmq + python -VV + + - name: Install vcpkg + shell: pwsh + run: | + if (Test-Path $env:VCPKG_ROOT) { + if (-not (Test-Path "$env:VCPKG_ROOT\.git")) { + Write-Host "Removing incomplete vcpkg directory..." + Remove-Item -Recurse -Force $env:VCPKG_ROOT + } + } + if (-not (Test-Path "$env:VCPKG_ROOT\.git")) { + git clone --quiet https://github.com/microsoft/vcpkg.git $env:VCPKG_ROOT + } + Set-Location $env:VCPKG_ROOT + git -c advice.detachedHead=false checkout $env:CI_VCPKG_TAG + .\bootstrap-vcpkg.bat -disableMetrics + Add-Content triplets\x64-windows-static.cmake "set(VCPKG_BUILD_TYPE release)" + .\vcpkg integrate install + .\vcpkg version + + - name: Create vcpkg binary cache directory + shell: pwsh + run: New-Item -ItemType Directory -Force -Path $env:VCPKG_DEFAULT_BINARY_CACHE + + - name: Build (MSVC) + shell: pwsh + run: | + cd $env:GITHUB_WORKSPACE + python build_msvc\msvc-autogen.py + $vsPath = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" ` + -latest -property installationPath + $msbuild = "$vsPath\MSBuild\Current\Bin\MSBuild.exe" + & $msbuild build_msvc\bitcoin.sln /property:Configuration=Release ` + /property:PlatformToolset=v142 ` + /maxCpuCount /verbosity:minimal /noLogo + + - name: Run unit tests + shell: cmd + run: | + src\test_elements.exe -l test_suite + src\bench_elements.exe > NUL + python test\util\test_runner.py + python test\util\rpcauth-test.py + + - name: Run functional tests + shell: cmd + run: | + netsh int ipv4 set dynamicport tcp start=1025 num=64511 + netsh int ipv6 set dynamicport tcp start=1025 num=64511 + python test\functional\test_runner.py --nocleanup --ci --quiet ^ + --combinedlogslen=4000 --jobs=4 --timeout-factor=8 --extended ^ + --exclude wallet_avoidreuse,feature_trim_headers,feature_dbcrash,feature_fee_estimation + + - name: Save vcpkg binary cache (push only) + if: github.event_name == 'push' + uses: actions/cache/save@v5 + with: + path: ${{ env.VCPKG_DEFAULT_BINARY_CACHE }} + key: vcpkg-binary-${{ env.CI_VCPKG_TAG }}-${{ runner.os }}-${{ github.sha }} + + # ------------------------------------------------------------------------- + # DISABLED JOBS + # + # The following job was skipped in cirrus, as is required persistent self-hosted runners and is not currently supported in GitHub Actions. It is preserved here as a comment for future re-enabling when self-hosted runner support is available. + # + # previous-releases: + # name: '[previous releases, uses qt5 dev package and some depends packages, DEBUG] [unsigned char] [bionic]' + # runs-on: [self-hosted, persistent] + # timeout-minutes: 120 + # env: + # FILE_ENV: "./ci/test/00_setup_env_native_qt5.sh" + # RESTART_CI_DOCKER_BEFORE_RUN: "1" + # steps: + # - name: Checkout + # uses: actions/checkout@v4 + # + # - name: Restore previous releases cache + # uses: actions/cache@v4 + # with: + # path: releases + # key: previous-releases-${{ hashFiles('ci/**') }} + # restore-keys: previous-releases- + # + # - name: Restore ccache + # uses: actions/cache/restore@v4 + # with: + # path: ${{ env.CCACHE_DIR }} + # key: ccache-previous-releases-${{ github.sha }} + # restore-keys: ccache-previous-releases- + # + # - name: Restore depends/built cache + # uses: actions/cache/restore@v4 + # with: + # path: depends/built + # key: depends-built-previous-releases-${{ hashFiles('depends/**', 'ci/test/00_setup_env_native_qt5.sh') }} + # restore-keys: depends-built-previous-releases- + # + # - name: Run CI + # run: ./ci/test_run_all.sh + # + # - name: Save ccache (push only) + # if: github.event_name == 'push' + # uses: actions/cache/save@v4 + # with: + # path: ${{ env.CCACHE_DIR }} + # key: ccache-previous-releases-${{ github.sha }} + # + # - name: Save depends/built cache (push only) + # if: github.event_name == 'push' + # uses: actions/cache/save@v4 + # with: + # path: depends/built + # key: depends-built-previous-releases-${{ hashFiles('depends/**', 'ci/test/00_setup_env_native_qt5.sh') }} + # + # The following jobs were disabled in .cirrus.yml with `only_if: false` + # and are preserved here as comments for future re-enabling. + # + # multiprocess-i686-debug: + # name: '[multiprocess, i686, DEBUG] [focal]' + # # Disabled: multiprocess build is not supported or tested in Elements. + # if: false + # ... + # + # android-apk: + # name: 'ARM64 Android APK [focal]' + # # Disabled: Android build is broken and unsupported in Elements. + # if: false + # ... + # ------------------------------------------------------------------------- diff --git a/ci/test/00_setup_env_lint.sh b/ci/test/00_setup_env_lint.sh new file mode 100755 index 00000000000..b95f3a35d31 --- /dev/null +++ b/ci/test/00_setup_env_lint.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2019-2021 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +export LC_ALL=C.UTF-8 + +export HOST="x86_64-pc-linux-gnu" +export CONTAINER_NAME=ci_lint +export DOCKER_NAME_TAG=ubuntu:focal +export RUN_LINT=true +export RUN_UNIT_TESTS=false +export RUN_FUNCTIONAL_TESTS=false +export GOAL="" +export BITCOIN_CONFIG="" diff --git a/ci/test/00_setup_env_mac_native_arm64.sh b/ci/test/00_setup_env_mac_native_arm64.sh index 1a7be56d5bd..ade2d2787c1 100755 --- a/ci/test/00_setup_env_mac_native_arm64.sh +++ b/ci/test/00_setup_env_mac_native_arm64.sh @@ -7,7 +7,9 @@ export LC_ALL=C.UTF-8 export HOST=arm64-apple-darwin -export PIP_PACKAGES="zmq" +# Homebrew's python@3.12 is marked as externally managed (PEP 668). +# Therefore, `--break-system-packages` is needed. +export PIP_PACKAGES="--break-system-packages zmq" export GOAL="install" # ELEMENTS: add -fno-stack-check to work around clang bug on macos export BITCOIN_CONFIG="--with-gui --with-miniupnpc --with-natpmp --enable-reduce-exports CXXFLAGS=-fno-stack-check" diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh index 6244a74f7bd..5e778f10e3b 100755 --- a/ci/test/04_install.sh +++ b/ci/test/04_install.sh @@ -11,7 +11,7 @@ if [[ $QEMU_USER_CMD == qemu-s390* ]]; then fi if [ "$CI_OS_NAME" == "macos" ]; then - sudo -H pip3 install --upgrade --ignore-installed pip + sudo -H pip3 install --upgrade --break-system-packages --ignore-installed pip # shellcheck disable=SC2086 IN_GETOPT_BIN="$(brew --prefix gnu-getopt)/bin/getopt" ${CI_RETRY_EXE} pip3 install --user $PIP_PACKAGES fi diff --git a/configure.ac b/configure.ac index ff410adddda..8e0af752247 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 23) define(_CLIENT_VERSION_MINOR, 3) -define(_CLIENT_VERSION_BUILD, 3) -define(_CLIENT_VERSION_RC, 0) +define(_CLIENT_VERSION_BUILD, 4) +define(_CLIENT_VERSION_RC, 1) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2026) define(_COPYRIGHT_HOLDERS,[The %s developers]) diff --git a/doc/man/elements-cli.1 b/doc/man/elements-cli.1 index dfb21700b09..111ee9e7223 100644 --- a/doc/man/elements-cli.1 +++ b/doc/man/elements-cli.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH ELEMENTS-CLI "1" "April 2026" "elements-cli v23.3.3" "User Commands" +.TH ELEMENTS-CLI "1" "June 2026" "elements-cli v23.3.4" "User Commands" .SH NAME -elements-cli \- manual page for elements-cli v23.3.3 +elements-cli \- manual page for elements-cli v23.3.4 .SH SYNOPSIS .B elements-cli [\fI\,options\/\fR] \fI\, \/\fR[\fI\,params\/\fR] \fI\,Send command to Elements Core\/\fR @@ -15,7 +15,7 @@ elements-cli \- manual page for elements-cli v23.3.3 .B elements-cli [\fI\,options\/\fR] \fI\,help Get help for a command\/\fR .SH DESCRIPTION -Elements Core RPC client version v23.3.3 +Elements Core RPC client version v23.3.4 .SH OPTIONS .HP \-? diff --git a/doc/man/elements-qt.1 b/doc/man/elements-qt.1 index 4f850c9d87b..97a47e1b5c9 100644 --- a/doc/man/elements-qt.1 +++ b/doc/man/elements-qt.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH ELEMENTS-QT "1" "April 2026" "elements-qt v23.3.3" "User Commands" +.TH ELEMENTS-QT "1" "June 2026" "elements-qt v23.3.4" "User Commands" .SH NAME -elements-qt \- manual page for elements-qt v23.3.3 +elements-qt \- manual page for elements-qt v23.3.4 .SH SYNOPSIS .B elements-qt [\fI\,command-line options\/\fR] .SH DESCRIPTION -Elements Core version v23.3.3 +Elements Core version v23.3.4 .SH OPTIONS .HP \-? @@ -815,8 +815,9 @@ Relay and mine data carrier transactions (default: 1) .HP \fB\-datacarriersize\fR .IP -Maximum size of data in data carrier transactions we relay and mine -(default: 83) +Relay and mine transactions whose data\-carrying raw scriptPubKeys in +aggregate are of this size or less, allowing multiple outputs +(default: 100000) .HP \fB\-minrelaytxfee=\fR .IP diff --git a/doc/man/elements-tx.1 b/doc/man/elements-tx.1 index 8410f50088b..04f0cbf7d5d 100644 --- a/doc/man/elements-tx.1 +++ b/doc/man/elements-tx.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH ELEMENTS-TX "1" "April 2026" "elements-tx v23.3.3" "User Commands" +.TH ELEMENTS-TX "1" "June 2026" "elements-tx v23.3.4" "User Commands" .SH NAME -elements-tx \- manual page for elements-tx v23.3.3 +elements-tx \- manual page for elements-tx v23.3.4 .SH SYNOPSIS .B elements-tx [\fI\,options\/\fR] \fI\, \/\fR[\fI\,commands\/\fR] \fI\,Update hex-encoded Elements transaction\/\fR @@ -9,7 +9,7 @@ elements-tx \- manual page for elements-tx v23.3.3 .B elements-tx [\fI\,options\/\fR] \fI\,-create \/\fR[\fI\,commands\/\fR] \fI\,Create hex-encoded Elements transaction\/\fR .SH DESCRIPTION -Elements Core elements\-tx utility version v23.3.3 +Elements Core elements\-tx utility version v23.3.4 .SH OPTIONS .HP \-? diff --git a/doc/man/elements-util.1 b/doc/man/elements-util.1 index 4b858969409..e73f293f6de 100644 --- a/doc/man/elements-util.1 +++ b/doc/man/elements-util.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH ELEMENTS-UTIL "1" "April 2026" "elements-util v23.3.3" "User Commands" +.TH ELEMENTS-UTIL "1" "June 2026" "elements-util v23.3.4" "User Commands" .SH NAME -elements-util \- manual page for elements-util v23.3.3 +elements-util \- manual page for elements-util v23.3.4 .SH SYNOPSIS .B bitcoin-util [\fI\,options\/\fR] [\fI\,commands\/\fR] \fI\,Do stuff\/\fR .SH DESCRIPTION -Elements Core bitcoin\-util utility version v23.3.3 +Elements Core bitcoin\-util utility version v23.3.4 .SH OPTIONS .HP \-? diff --git a/doc/man/elements-wallet.1 b/doc/man/elements-wallet.1 index 37443f9c21e..33a03286327 100644 --- a/doc/man/elements-wallet.1 +++ b/doc/man/elements-wallet.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH ELEMENTS-WALLET "1" "April 2026" "elements-wallet v23.3.3" "User Commands" +.TH ELEMENTS-WALLET "1" "June 2026" "elements-wallet v23.3.4" "User Commands" .SH NAME -elements-wallet \- manual page for elements-wallet v23.3.3 +elements-wallet \- manual page for elements-wallet v23.3.4 .SH DESCRIPTION -Elements Core elements\-wallet version v23.3.3 +Elements Core elements\-wallet version v23.3.4 .PP elements\-wallet is an offline tool for creating and interacting with Elements Core wallet files. By default elements\-wallet will act on wallets in the default mainnet wallet directory in the datadir. diff --git a/doc/man/elementsd.1 b/doc/man/elementsd.1 index 201bf3332db..075185be0bf 100644 --- a/doc/man/elementsd.1 +++ b/doc/man/elementsd.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH ELEMENTSD "1" "April 2026" "elementsd v23.3.3" "User Commands" +.TH ELEMENTSD "1" "June 2026" "elementsd v23.3.4" "User Commands" .SH NAME -elementsd \- manual page for elementsd v23.3.3 +elementsd \- manual page for elementsd v23.3.4 .SH SYNOPSIS .B elementsd [\fI\,options\/\fR] \fI\,Start Elements Core\/\fR .SH DESCRIPTION -Elements Core version v23.3.3 +Elements Core version v23.3.4 .SH OPTIONS .HP \-? @@ -815,8 +815,9 @@ Relay and mine data carrier transactions (default: 1) .HP \fB\-datacarriersize\fR .IP -Maximum size of data in data carrier transactions we relay and mine -(default: 83) +Relay and mine transactions whose data\-carrying raw scriptPubKeys in +aggregate are of this size or less, allowing multiple outputs +(default: 100000) .HP \fB\-minrelaytxfee=\fR .IP diff --git a/src/block_proof.cpp b/src/block_proof.cpp index 272d9c0569c..0ef130b517c 100644 --- a/src/block_proof.cpp +++ b/src/block_proof.cpp @@ -26,10 +26,8 @@ static bool CheckProofGeneric(const CBlockHeader& block, const uint32_t max_bloc // Check signature limits for blocks if (scriptSig.size() > max_block_signature_size) { - assert(!is_dyna); return false; } else if (witness.GetSerializedSize() > max_block_signature_size) { - assert(is_dyna); return false; } diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 0ffb5867244..c6065b0f884 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -229,7 +229,7 @@ class CMainParams : public CChainParams { anyonecanspend_aremine = false; accept_unlimited_issuances = false; enforce_pak = false; - multi_data_permitted = false; + multi_data_permitted = true; accept_discount_ct = false; create_discount_ct = false; consensus.has_parent_chain = false; @@ -376,7 +376,7 @@ class CTestNetParams : public CChainParams { anyonecanspend_aremine = false; enforce_pak = false; accept_unlimited_issuances = false; - multi_data_permitted = false; + multi_data_permitted = true; accept_discount_ct = false; create_discount_ct = false; consensus.has_parent_chain = false; @@ -541,7 +541,7 @@ class SigNetParams : public CChainParams { anyonecanspend_aremine = false; enforce_pak = false; accept_unlimited_issuances = false; - multi_data_permitted = false; + multi_data_permitted = true; accept_discount_ct = false; create_discount_ct = false; consensus.has_parent_chain = false; @@ -645,7 +645,7 @@ class CRegTestParams : public CChainParams { anyonecanspend_aremine = false; enforce_pak = false; accept_unlimited_issuances = false; - multi_data_permitted = false; + multi_data_permitted = true; accept_discount_ct = false; create_discount_ct = false; consensus.has_parent_chain = false; @@ -1061,6 +1061,7 @@ class CLiquidTestNetParams : public CCustomParams { default_signblockscript = "51210217e403ddb181872c32a0cd468c710040b2f53d8cac69f18dad07985ee37e9a7151ae"; create_discount_ct = false; accept_discount_ct = true; + accept_unlimited_issuances = true; UpdateFromArgs(args); multi_data_permitted = true; SetGenesisBlock(); @@ -1173,7 +1174,7 @@ class CLiquidV1Params : public CChainParams { enforce_pak = true; - accept_unlimited_issuances = args.GetBoolArg("-acceptunlimitedissuances", false); + accept_unlimited_issuances = args.GetBoolArg("-acceptunlimitedissuances", true); multi_data_permitted = true; create_discount_ct = args.GetBoolArg("-creatediscountct", false); diff --git a/src/init.cpp b/src/init.cpp index 32473973451..38112fbeeef 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -567,7 +567,11 @@ void SetupServerArgs(ArgsManager& argsman) argsman.AddArg("-dustrelayfee=", strprintf("Fee rate (in %s/kvB) used to define dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY); argsman.AddArg("-bytespersigop", strprintf("Equivalent bytes per sigop in transactions for relay and mining (default: %u)", DEFAULT_BYTES_PER_SIGOP), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); argsman.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); - argsman.AddArg("-datacarriersize", strprintf("Maximum size of data in data carrier transactions we relay and mine (default: %u)", MAX_OP_RETURN_RELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); + argsman.AddArg("-datacarriersize", + strprintf("Relay and mine transactions whose data-carrying raw scriptPubKeys in aggregate " + "are of this size or less, allowing multiple outputs (default: %u)", + MAX_OP_RETURN_RELAY), + ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); argsman.AddArg("-minrelaytxfee=", strprintf("Fees (in %s/kvB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); argsman.AddArg("-whitelistforcerelay", strprintf("Add 'forcerelay' permission to whitelisted inbound peers with default permissions. This will relay transactions even if the transactions were already in the mempool. (default: %d)", DEFAULT_WHITELISTFORCERELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); diff --git a/src/pegins.cpp b/src/pegins.cpp index 72551d2c3b5..2af4fb2a3e7 100644 --- a/src/pegins.cpp +++ b/src/pegins.cpp @@ -552,7 +552,7 @@ bool DecomposePeginWitness(const CScriptWitness& witness, CAmount& value, CAsset { const auto& stack = witness.stack; - if (stack.size() < 5) return false; + if (stack.size() != 6) return false; CDataStream stream(stack[0], SER_NETWORK, PROTOCOL_VERSION); stream >> value; diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 2dc3296214b..254d648a15f 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -87,9 +87,7 @@ bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType) scriptPubKey.IsPegoutScript(Params().ParentGenesisBlockHash()) ) { // If we're enforcing pak let through larger peg-out scripts return true; - } else if (whichType == TxoutType::NULL_DATA && - (!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes)) { - return false; + } return true; @@ -134,6 +132,7 @@ bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeR CChainParams params = Params(); unsigned int nDataOut = 0; + unsigned int datacarrier_bytes_left = fAcceptDatacarrier ? nMaxDatacarrierBytes : 0; TxoutType whichType; for (const CTxOut& txout : tx.vout) { if (!::IsStandard(txout.scriptPubKey, whichType)) { @@ -143,6 +142,12 @@ bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeR if (whichType == TxoutType::NULL_DATA) { nDataOut++; + unsigned int size = txout.scriptPubKey.size(); + if (size > datacarrier_bytes_left) { + reason = "datacarrier"; + return false; + } + datacarrier_bytes_left -= size; } else if ((whichType == TxoutType::MULTISIG) && (!permit_bare_multisig)) { reason = "bare-multisig"; return false; @@ -152,7 +157,7 @@ bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeR } } - // only one OP_RETURN txout is permitted + // only one OP_RETURN txout is permitted (per-chain control) if (!params.GetMultiDataPermitted() && nDataOut > 1) { reason = "multi-op-return"; return false; diff --git a/src/script/standard.h b/src/script/standard.h index 7e351c835cd..c79db95adbb 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -47,10 +47,10 @@ class CScriptID : public BaseHash }; /** - * Default setting for nMaxDatacarrierBytes. 80 bytes of data, +1 for OP_RETURN, - * +2 for the pushdata opcodes. + * Default setting for nMaxDatacarrierBytes. 100000 bytes + * (MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR = 400000 / 4). */ -static const unsigned int MAX_OP_RETURN_RELAY = 83; +static const unsigned int MAX_OP_RETURN_RELAY = 100000; /** * A data carrying output is an unspendable output containing data. The script diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index e6e4ce0f709..ca08980a37e 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -781,15 +781,21 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) key.MakeNewKey(true); t.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey())); - constexpr auto CheckIsStandard = [](const auto& t) { + constexpr auto CheckIsStandard = [](const auto& t, const unsigned int max_op_return_relay = MAX_OP_RETURN_RELAY) { + const auto old_val = nMaxDatacarrierBytes; + nMaxDatacarrierBytes = max_op_return_relay; std::string reason; BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); BOOST_CHECK(reason.empty()); + nMaxDatacarrierBytes = old_val; }; - constexpr auto CheckIsNotStandard = [](const auto& t, const std::string& reason_in) { + constexpr auto CheckIsNotStandard = [](const auto& t, const std::string& reason_in, const unsigned int max_op_return_relay = MAX_OP_RETURN_RELAY) { + const auto old_val = nMaxDatacarrierBytes; + nMaxDatacarrierBytes = max_op_return_relay; std::string reason; BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); BOOST_CHECK_EQUAL(reason_in, reason); + nMaxDatacarrierBytes = old_val; }; CheckIsStandard(t); @@ -836,15 +842,13 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) t.vout[0].scriptPubKey = CScript() << OP_1; CheckIsNotStandard(t, "scriptpubkey"); - // MAX_OP_RETURN_RELAY-byte TxoutType::NULL_DATA (standard) + // Custom 83-byte TxoutType::NULL_DATA (standard with max_op_return_relay of 83) t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); - BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY, t.vout[0].scriptPubKey.size()); - CheckIsStandard(t); + BOOST_CHECK_EQUAL(83, t.vout[0].scriptPubKey.size()); + CheckIsStandard(t, /*max_op_return_relay=*/83); - // MAX_OP_RETURN_RELAY+1-byte TxoutType::NULL_DATA (non-standard) - t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800"); - BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY + 1, t.vout[0].scriptPubKey.size()); - CheckIsNotStandard(t, "scriptpubkey"); + // Non-standard if max_op_return_relay datacarrier arg is one less + CheckIsNotStandard(t, "datacarrier", /*max_op_return_relay=*/82); // Data payload can be encoded in any way... t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex(""); @@ -866,21 +870,28 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) t.vout[0].scriptPubKey = CScript() << OP_RETURN; CheckIsStandard(t); - // Only one TxoutType::NULL_DATA permitted in all cases + // Multiple TxoutType::NULL_DATA are permitted t.vout.resize(2); t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); t.vout[0].nValue = 0; t.vout[1].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); t.vout[1].nValue = 0; - CheckIsNotStandard(t, "multi-op-return"); + CheckIsStandard(t); t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); t.vout[1].scriptPubKey = CScript() << OP_RETURN; - CheckIsNotStandard(t, "multi-op-return"); + CheckIsStandard(t); t.vout[0].scriptPubKey = CScript() << OP_RETURN; t.vout[1].scriptPubKey = CScript() << OP_RETURN; - CheckIsNotStandard(t, "multi-op-return"); + CheckIsStandard(t); + + t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); + t.vout[1].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); + const auto datacarrier_size = t.vout[0].scriptPubKey.size() + t.vout[1].scriptPubKey.size(); + CheckIsStandard(t); // Default max relay should never trigger + CheckIsStandard(t, /*max_op_return_relay=*/datacarrier_size); + CheckIsNotStandard(t, "datacarrier", /*max_op_return_relay=*/datacarrier_size-1); // Check large scriptSig (non-standard if size is >1650 bytes) t.vout.resize(1); diff --git a/src/wallet/rpc/elements.cpp b/src/wallet/rpc/elements.cpp index 798c218249b..6b2ba269f80 100644 --- a/src/wallet/rpc/elements.cpp +++ b/src/wallet/rpc/elements.cpp @@ -1275,6 +1275,9 @@ RPCHelpMan blindrawtransaction() // Vacuous, just return the transaction return EncodeHexTx(CTransaction(tx)); } else if (n_blinded_ins > 0 && num_pubkeys == 0) { + if (tx.vout.empty()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Unable to blind transaction: transaction has no outputs to balance blinded inputs against."); + } // Blinded inputs need to balanced with something to be valid, make a dummy. CTxOut newTxOut(tx.vout.back().nAsset.GetAsset(), 0, CScript() << OP_RETURN); tx.vout.push_back(newTxOut); diff --git a/test/functional/feature_discount_ct.py b/test/functional/feature_discount_ct.py index ac128bddcc3..a4f4a3eebc2 100755 --- a/test/functional/feature_discount_ct.py +++ b/test/functional/feature_discount_ct.py @@ -89,26 +89,6 @@ def run_test(self): assert_approx(tx['discountweight'], 1301.5, 0.5) assert_equal(tx['discountvsize'], 326) - self.log.info("Send confidential tx to node 0") - addr = node0.getnewaddress() - info = node0.getaddressinfo(addr) - txid = node0.sendtoaddress(info['confidential'], 1.0, "", "", False, None, None, None, None, None, None, feerate) - tx = node0.gettransaction(txid, True, True) - decoded = tx['decoded'] - vin = decoded['vin'] - vout = decoded['vout'] - assert_equal(len(vin), 2) - assert_equal(len(vout), 3) - assert_equal(tx['fee']['bitcoin'], Decimal('-0.00002575')) - assert_equal(decoded['vsize'], 2575) - # tx weight can be 10299 or 10300, accept both - assert_approx(decoded['weight'], 10299.5, 0.5) - self.generate(node0, 1) - tx = node1.getrawtransaction(txid, True) - # tx discountweight can be 1301 or 1302, accept both - assert_approx(tx['discountweight'], 1301.5, 0.5) - assert_equal(tx['discountvsize'], 326) # node1 has discountvsize - self.log.info("Send explicit tx to node 1") addr = node1.getnewaddress() info = node1.getaddressinfo(addr) @@ -129,6 +109,26 @@ def run_test(self): assert_approx(tx['discountweight'], 1301.5, 0.5) assert_equal(tx['discountvsize'], 326) + self.log.info("Send confidential tx to node 0") + addr = node0.getnewaddress() + info = node0.getaddressinfo(addr) + txid = node0.sendtoaddress(info['confidential'], 1.0, "", "", False, None, None, None, None, None, None, feerate) + tx = node0.gettransaction(txid, True, True) + decoded = tx['decoded'] + vin = decoded['vin'] + vout = decoded['vout'] + assert_equal(len(vin), 2) + assert_equal(len(vout), 3) + assert_equal(tx['fee']['bitcoin'], Decimal('-0.00002575')) + assert_equal(decoded['vsize'], 2575) + # tx weight can be 10299 or 10300, accept both + assert_approx(decoded['weight'], 10299.5, 0.5) + self.generate(node0, 1) + tx = node1.getrawtransaction(txid, True) + # tx discountweight can be 1301 or 1302, accept both + assert_approx(tx['discountweight'], 1301.5, 0.5) + assert_equal(tx['discountvsize'], 326) # node1 has discountvsize + self.log.info("Send confidential (undiscounted) tx to node 1") addr = node1.getnewaddress() info = node1.getaddressinfo(addr) diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py index 560cc9f9fa3..b29a2ff851a 100755 --- a/test/functional/mempool_accept.py +++ b/test/functional/mempool_accept.py @@ -330,7 +330,6 @@ def run_test(self): result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'min relay fee not met'}], rawtxs=[tx.serialize().hex()], ) - self.log.info('A timelocked transaction') tx = tx_from_hex(raw_tx_reference) tx.vin[0].nSequence -= 1 # Should be non-max, so locktime is not ignored @@ -349,6 +348,17 @@ def run_test(self): maxfeerate=0, ) + self.log.info('Multiple OP_RETURN and large data are standard with default datacarriersize (100000)') + # Multiple OP_RETURN outputs with data far exceeding the old per-output + tx = tx_from_hex(raw_tx_reference) + tx.vout.append(CTxOut(nValue=0, scriptPubKey=CScript([OP_RETURN, b'\xff']))) + tx.vout.append(CTxOut(nValue=0, scriptPubKey=CScript([OP_RETURN, b'\xff' * 50000]))) + self.check_mempool_result( + result_expected=[{'txid': tx.rehash(), 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': Decimal('0.05')}}], + rawtxs=[tx.serialize().hex()], + maxfeerate=0, + ) + if __name__ == '__main__': MempoolAcceptanceTest().main()