diff --git a/depend/bitcoin/.github/workflows/ci.yml b/depend/bitcoin/.github/workflows/ci.yml index 2563c2e0..5e5b0c48 100644 --- a/depend/bitcoin/.github/workflows/ci.yml +++ b/depend/bitcoin/.github/workflows/ci.yml @@ -30,7 +30,7 @@ defaults: jobs: runners: - name: 'determine runners' + name: '[meta] determine runners' runs-on: ubuntu-latest outputs: provider: ${{ steps.runners.outputs.provider }} @@ -66,7 +66,7 @@ jobs: - name: Determine fetch depth run: echo "FETCH_DEPTH=$((${{ github.event.pull_request.commits }} + 2))" >> "$GITHUB_ENV" - *ANNOTATION_PR_NUMBER - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: ${{ env.FETCH_DEPTH }} @@ -148,7 +148,7 @@ jobs: - &CHECKOUT name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: # Ensure the latest merged pull request state is used, even on re-runs. ref: &CHECKOUT_REF_TMPL ${{ github.event_name == 'pull_request' && github.ref || '' }} @@ -343,9 +343,23 @@ jobs: run: | py -3 test/fuzz/test_runner.py --par $NUMBER_OF_PROCESSORS --loglevel DEBUG "${RUNNER_TEMP}/qa-assets/fuzz_corpora" + record-frozen-commit: + # Record frozen commit, so that the native tests on cross-builds can run on + # the exact same commit id of the build. + name: '[meta] record frozen commit' + runs-on: ubuntu-latest + outputs: + commit: ${{ steps.record-commit.outputs.commit }} + steps: + - *ANNOTATION_PR_NUMBER + - *CHECKOUT + - name: Record commit + id: record-commit + run: echo "commit=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + windows-cross: name: 'Windows-cross to x86_64, ${{ matrix.crt }}' - needs: runners + needs: [runners, record-frozen-commit] runs-on: ${{ needs.runners.outputs.provider == 'cirrus' && 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-sm' || 'ubuntu-24.04' }} if: ${{ vars.SKIP_BRANCH_PUSH != 'true' || github.event_name == 'pull_request' }} @@ -368,7 +382,10 @@ jobs: steps: - *ANNOTATION_PR_NUMBER - - *CHECKOUT + - name: Checkout + uses: actions/checkout@v6 + with: + ref: ${{ needs.record-frozen-commit.outputs.commit }} - name: Configure environment uses: ./.github/actions/configure-environment @@ -402,7 +419,7 @@ jobs: windows-native-test: name: 'Windows, ${{ matrix.crt }}, test cross-built' runs-on: windows-2022 - needs: windows-cross + needs: [windows-cross, record-frozen-commit] strategy: fail-fast: false @@ -421,7 +438,10 @@ jobs: steps: - *ANNOTATION_PR_NUMBER - - *CHECKOUT + - name: Checkout + uses: actions/checkout@v6 + with: + ref: ${{ needs.record-frozen-commit.outputs.commit }} - name: Download built executables uses: actions/download-artifact@v5 @@ -502,6 +522,12 @@ jobs: fail-fast: false matrix: include: + - name: 'iwyu' + cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md' + fallback-runner: 'ubuntu-24.04' + timeout-minutes: 120 + file-env: './ci/test/00_setup_env_native_iwyu.sh' + - name: '32 bit ARM' cirrus-runner: 'ubuntu-24.04-arm' # Cirrus' Arm runners are Apple (with virtual Linux aarch64), which doesn't support 32-bit mode fallback-runner: 'ubuntu-24.04-arm' @@ -637,7 +663,7 @@ jobs: - *ANNOTATION_PR_NUMBER - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: *CHECKOUT_REF_TMPL fetch-depth: 0 diff --git a/depend/bitcoin/.gitignore b/depend/bitcoin/.gitignore index 3b22e358..b92988f6 100644 --- a/depend/bitcoin/.gitignore +++ b/depend/bitcoin/.gitignore @@ -12,6 +12,7 @@ # Only ignore unexpected patches *.patch +!ci/test/*.patch !contrib/guix/patches/*.patch !depends/patches/**/*.patch diff --git a/depend/bitcoin/ci/lint/01_install.sh b/depend/bitcoin/ci/lint/01_install.sh index fc422675..0cf9fbb4 100755 --- a/depend/bitcoin/ci/lint/01_install.sh +++ b/depend/bitcoin/ci/lint/01_install.sh @@ -40,7 +40,6 @@ command -v python3 python3 --version ${CI_RETRY_EXE} pip3 install \ - codespell==2.4.1 \ lief==0.16.6 \ mypy==1.18.2 \ pyzmq==27.1.0 \ diff --git a/depend/bitcoin/ci/test/00_setup_env_native_iwyu.sh b/depend/bitcoin/ci/test/00_setup_env_native_iwyu.sh new file mode 100755 index 00000000..3868510d --- /dev/null +++ b/depend/bitcoin/ci/test/00_setup_env_native_iwyu.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2023-present 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 CI_IMAGE_NAME_TAG="mirror.gcr.io/debian:trixie" # To build codegen, CMake must be 3.31 or newer. +export CONTAINER_NAME=ci_native_iwyu +export TIDY_LLVM_V="21" +export APT_LLVM_V="${TIDY_LLVM_V}" +export PACKAGES="clang-${TIDY_LLVM_V} clang-format-${TIDY_LLVM_V} libclang-${TIDY_LLVM_V}-dev llvm-${TIDY_LLVM_V}-dev jq libevent-dev libboost-dev libzmq3-dev systemtap-sdt-dev qt6-base-dev qt6-tools-dev qt6-l10n-tools libqrencode-dev libsqlite3-dev libcapnp-dev capnproto" +export NO_DEPENDS=1 +export RUN_UNIT_TESTS=false +export RUN_FUNCTIONAL_TESTS=false +export RUN_FUZZ_TESTS=false +export RUN_CHECK_DEPS=false +export RUN_IWYU=true +export GOAL="codegen" +export BITCOIN_CONFIG="\ + --preset dev-mode -DBUILD_GUI=OFF \ + -DCMAKE_C_COMPILER=clang-${TIDY_LLVM_V} \ + -DCMAKE_CXX_COMPILER=clang++-${TIDY_LLVM_V} \ +" diff --git a/depend/bitcoin/ci/test/01_base_install.sh b/depend/bitcoin/ci/test/01_base_install.sh index a0f4164b..0ac56208 100755 --- a/depend/bitcoin/ci/test/01_base_install.sh +++ b/depend/bitcoin/ci/test/01_base_install.sh @@ -79,8 +79,9 @@ if [[ -n "${USE_INSTRUMENTED_LIBCPP}" ]]; then rm -rf /llvm-project fi -if [[ "${RUN_TIDY}" == "true" ]]; then +if [[ "${RUN_IWYU}" == true ]]; then ${CI_RETRY_EXE} git clone --depth=1 https://github.com/include-what-you-use/include-what-you-use -b clang_"${TIDY_LLVM_V}" /include-what-you-use + (cd /include-what-you-use && patch -p1 < /ci_container_base/ci/test/01_iwyu.patch) cmake -B /iwyu-build/ -G 'Unix Makefiles' -DCMAKE_PREFIX_PATH=/usr/lib/llvm-"${TIDY_LLVM_V}" -S /include-what-you-use make -C /iwyu-build/ install "$MAKEJOBS" fi diff --git a/depend/bitcoin/ci/test/01_iwyu.patch b/depend/bitcoin/ci/test/01_iwyu.patch new file mode 100644 index 00000000..e14316bf --- /dev/null +++ b/depend/bitcoin/ci/test/01_iwyu.patch @@ -0,0 +1,598 @@ +Prefer angled brackets over quotes for include directives. +See: https://en.cppreference.com/w/cpp/preprocessor/include.html. + +--- a/iwyu_path_util.cc ++++ b/iwyu_path_util.cc +@@ -211,7 +211,7 @@ bool IsQuotedInclude(const string& s) { + } + + string AddQuotes(string include_name, bool angled) { +- if (angled) { ++ if (true) { + return "<" + include_name + ">"; + } + return "\"" + include_name + "\""; + + +Prefer C++ headers over C counterparts. +See: https://github.com/include-what-you-use/include-what-you-use/blob/clang_21/iwyu_include_picker.cc#L587-L629. + +--- a/iwyu_include_picker.cc ++++ b/iwyu_include_picker.cc +@@ -100,20 +100,20 @@ const IncludeMapEntry libc_symbol_map[] = { + // equal. The visibility on the symbol-name is ignored; by convention + // we always set it to kPrivate. + { "_POSIX_VDISABLE", kPrivate, "", kPublic }, +- { "abort", kPrivate, "", kPublic }, ++ { "abort", kPrivate, "", kPrivate }, + { "aiocb", kPrivate, "", kPublic }, + { "blkcnt_t", kPrivate, "", kPublic }, + { "blksize_t", kPrivate, "", kPublic }, + { "cc_t", kPrivate, "", kPublic }, +- { "clock_t", kPrivate, "", kPublic }, ++ { "clock_t", kPrivate, "", kPrivate }, + { "clock_t", kPrivate, "", kPublic }, + { "clockid_t", kPrivate, "", kPublic }, +- { "ctermid", kPrivate, "", kPublic }, ++ { "ctermid", kPrivate, "", kPrivate }, + { "daddr_t", kPrivate, "", kPublic }, + { "dev_t", kPrivate, "", kPublic }, +- { "div_t", kPrivate, "", kPublic }, +- { "double_t", kPrivate, "", kPublic }, +- { "error_t", kPrivate, "", kPublic }, ++ { "div_t", kPrivate, "", kPrivate }, ++ { "double_t", kPrivate, "", kPrivate }, ++ { "error_t", kPrivate, "", kPrivate }, + { "error_t", kPrivate, "", kPublic }, + { "error_t", kPrivate, "", kPublic }, + { "FD_CLR", kPrivate, "", kPublic }, +@@ -122,10 +122,10 @@ const IncludeMapEntry libc_symbol_map[] = { + { "fd_set", kPrivate, "", kPublic }, + { "FD_SETSIZE", kPrivate, "", kPublic }, + { "FD_ZERO", kPrivate, "", kPublic }, +- { "fenv_t", kPrivate, "", kPublic }, +- { "fexcept_t", kPrivate, "", kPublic }, +- { "FILE", kPrivate, "", kPublic }, +- { "float_t", kPrivate, "", kPublic }, ++ { "fenv_t", kPrivate, "", kPrivate }, ++ { "fexcept_t", kPrivate, "", kPrivate }, ++ { "FILE", kPrivate, "", kPrivate }, ++ { "float_t", kPrivate, "", kPrivate }, + { "fsblkcnt_t", kPrivate, "", kPublic }, + { "fsfilcnt_t", kPrivate, "", kPublic }, + { "getopt", kPrivate, "", kPublic }, +@@ -135,31 +135,31 @@ const IncludeMapEntry libc_symbol_map[] = { + { "in_addr_t", kPrivate, "", kPublic }, + { "in_port_t", kPrivate, "", kPublic }, + { "id_t", kPrivate, "", kPublic }, +- { "imaxdiv_t", kPrivate, "", kPublic }, +- { "intmax_t", kPrivate, "", kPublic }, +- { "uintmax_t", kPrivate, "", kPublic }, ++ { "imaxdiv_t", kPrivate, "", kPrivate }, ++ { "intmax_t", kPrivate, "", kPrivate }, ++ { "uintmax_t", kPrivate, "", kPrivate }, + { "ino64_t", kPrivate, "", kPublic }, + { "ino_t", kPrivate, "", kPublic }, +- { "int8_t", kPrivate, "", kPublic }, +- { "int16_t", kPrivate, "", kPublic }, +- { "int32_t", kPrivate, "", kPublic }, +- { "int64_t", kPrivate, "", kPublic }, +- { "uint8_t", kPrivate, "", kPublic }, +- { "uint16_t", kPrivate, "", kPublic }, +- { "uint32_t", kPrivate, "", kPublic }, +- { "uint64_t", kPrivate, "", kPublic }, +- { "intptr_t", kPrivate, "", kPublic }, +- { "uintptr_t", kPrivate, "", kPublic }, ++ { "int8_t", kPrivate, "", kPrivate }, ++ { "int16_t", kPrivate, "", kPrivate }, ++ { "int32_t", kPrivate, "", kPrivate }, ++ { "int64_t", kPrivate, "", kPrivate }, ++ { "uint8_t", kPrivate, "", kPrivate }, ++ { "uint16_t", kPrivate, "", kPrivate }, ++ { "uint32_t", kPrivate, "", kPrivate }, ++ { "uint64_t", kPrivate, "", kPrivate }, ++ { "intptr_t", kPrivate, "", kPrivate }, ++ { "uintptr_t", kPrivate, "", kPrivate }, + { "iovec", kPrivate, "", kPublic }, +- { "itimerspec", kPrivate, "", kPublic }, ++ { "itimerspec", kPrivate, "", kPrivate }, + { "key_t", kPrivate, "", kPublic }, +- { "L_ctermid", kPrivate, "", kPublic }, +- { "lconv", kPrivate, "", kPublic }, +- { "ldiv_t", kPrivate, "", kPublic }, +- { "lldiv_t", kPrivate, "", kPublic }, +- { "locale_t", kPrivate, "", kPublic }, +- { "max_align_t", kPrivate, "", kPublic }, +- { "mbstate_t", kPrivate, "", kPublic }, ++ { "L_ctermid", kPrivate, "", kPrivate }, ++ { "lconv", kPrivate, "", kPrivate }, ++ { "ldiv_t", kPrivate, "", kPrivate }, ++ { "lldiv_t", kPrivate, "", kPrivate }, ++ { "locale_t", kPrivate, "", kPrivate }, ++ { "max_align_t", kPrivate, "", kPrivate }, ++ { "mbstate_t", kPrivate, "", kPrivate }, + { "mcontext_t", kPrivate, "", kPublic }, + { "mode_t", kPrivate, "", kPublic }, + { "nl_item", kPrivate, "", kPublic }, +@@ -175,8 +175,8 @@ const IncludeMapEntry libc_symbol_map[] = { + { "optind", kPrivate, "", kPublic }, + { "optopt", kPrivate, "", kPublic }, + { "pid_t", kPrivate, "", kPublic }, +- { "posix_memalign", kPrivate, "", kPublic }, +- { "printf", kPrivate, "", kPublic }, ++ { "posix_memalign", kPrivate, "", kPrivate }, ++ { "printf", kPrivate, "", kPrivate }, + { "pthread_attr_t", kPrivate, "", kPublic }, + { "pthread_cond_t", kPrivate, "", kPublic }, + { "pthread_condattr_t", kPrivate, "", kPublic }, +@@ -187,7 +187,7 @@ const IncludeMapEntry libc_symbol_map[] = { + { "pthread_rwlock_t", kPrivate, "", kPublic }, + { "pthread_rwlockattr_t", kPrivate, "", kPublic }, + { "pthread_t", kPrivate, "", kPublic }, +- { "ptrdiff_t", kPrivate, "", kPublic }, ++ { "ptrdiff_t", kPrivate, "", kPrivate }, + { "regex_t", kPrivate, "", kPublic }, + { "regmatch_t", kPrivate, "", kPublic }, + { "regoff_t", kPrivate, "", kPublic }, +@@ -218,51 +218,51 @@ const IncludeMapEntry libc_symbol_map[] = { + { "SCHED_FIFO", kPrivate, "", kPublic }, + { "SCHED_OTHER", kPrivate, "", kPublic }, + { "SCHED_RR", kPrivate, "", kPublic }, +- { "SEEK_CUR", kPrivate, "", kPublic }, +- { "SEEK_END", kPrivate, "", kPublic }, +- { "SEEK_SET", kPrivate, "", kPublic }, +- { "sig_atomic_t", kPrivate, "", kPublic }, +- { "sigevent", kPrivate, "", kPublic }, +- { "siginfo_t", kPrivate, "", kPublic }, +- { "sigset_t", kPrivate, "", kPublic }, +- { "sigval", kPrivate, "", kPublic }, ++ { "SEEK_CUR", kPrivate, "", kPrivate }, ++ { "SEEK_END", kPrivate, "", kPrivate }, ++ { "SEEK_SET", kPrivate, "", kPrivate }, ++ { "sig_atomic_t", kPrivate, "", kPrivate }, ++ { "sigevent", kPrivate, "", kPrivate }, ++ { "siginfo_t", kPrivate, "", kPrivate }, ++ { "sigset_t", kPrivate, "", kPrivate }, ++ { "sigval", kPrivate, "", kPrivate }, + { "sockaddr", kPrivate, "", kPublic }, + { "socklen_t", kPrivate, "", kPublic }, + { "ssize_t", kPrivate, "", kPublic }, +- { "stack_t", kPrivate, "", kPublic }, ++ { "stack_t", kPrivate, "", kPrivate }, + { "stat", kPrivate, "", kPublic }, + { "suseconds_t", kPrivate, "", kPublic }, +- { "time_t", kPrivate, "", kPublic }, ++ { "time_t", kPrivate, "", kPrivate }, + { "time_t", kPrivate, "", kPublic }, + { "timer_t", kPrivate, "", kPublic }, +- { "timespec", kPrivate, "", kPublic }, ++ { "timespec", kPrivate, "", kPrivate }, + { "timeval", kPrivate, "", kPublic }, +- { "tm", kPrivate, "", kPublic }, ++ { "tm", kPrivate, "", kPrivate }, + { "u_char", kPrivate, "", kPublic }, + { "ucontext_t", kPrivate, "", kPublic }, + { "uid_t", kPrivate, "", kPublic }, + { "useconds_t", kPrivate, "", kPublic }, +- { "wchar_t", kPrivate, "", kPublic }, +- { "wctrans_t", kPrivate, "", kPublic }, +- { "wctype_t", kPrivate, "", kPublic }, ++ { "wchar_t", kPrivate, "", kPrivate }, ++ { "wctrans_t", kPrivate, "", kPrivate }, ++ { "wctype_t", kPrivate, "", kPrivate }, + { "winsize", kPrivate, "", kPublic }, +- { "wint_t", kPrivate, "", kPublic }, ++ { "wint_t", kPrivate, "", kPrivate }, + // It is unspecified if the cname headers provide ::size_t. + // is the one header which defines NULL but not size_t. +- { "size_t", kPrivate, "", kPublic }, // 'canonical' location for size_t +- { "size_t", kPrivate, "", kPublic }, +- { "size_t", kPrivate, "", kPublic }, +- { "size_t", kPrivate, "", kPublic }, +- { "size_t", kPrivate, "", kPublic }, +- { "size_t", kPrivate, "", kPublic }, +- { "size_t", kPrivate, "", kPublic }, +- { "size_t", kPrivate, "", kPublic }, ++ { "size_t", kPrivate, "", kPrivate }, // 'canonical' location for size_t ++ { "size_t", kPrivate, "", kPrivate }, ++ { "size_t", kPrivate, "", kPrivate }, ++ { "size_t", kPrivate, "", kPrivate }, ++ { "size_t", kPrivate, "", kPrivate }, ++ { "size_t", kPrivate, "", kPrivate }, ++ { "size_t", kPrivate, "", kPrivate }, ++ { "size_t", kPrivate, "", kPrivate }, + // Macros that can be defined in more than one file, don't have the + // same __foo_defined guard that other types do, so the grep above + // doesn't discover them. Until I figure out a better way, I just + // add them in by hand as I discover them. +- { "EOF", kPrivate, "", kPublic }, +- { "FILE", kPrivate, "", kPublic }, ++ { "EOF", kPrivate, "", kPrivate }, ++ { "FILE", kPrivate, "", kPrivate }, + { "IBSHIFT", kPrivate, "", kPublic }, + { "MAP_POPULATE", kPrivate, "", kPublic }, + { "MAP_POPULATE", kPrivate, "", kPublic }, +@@ -270,22 +270,22 @@ const IncludeMapEntry libc_symbol_map[] = { + { "MAP_STACK", kPrivate, "", kPublic }, + { "MAXHOSTNAMELEN", kPrivate, "", kPublic }, + { "MAXHOSTNAMELEN", kPrivate, "", kPublic }, +- { "SIGABRT", kPrivate, "", kPublic }, +- { "SIGCHLD", kPrivate, "", kPublic }, +- { "va_arg", kPrivate, "", kPublic }, +- { "va_copy", kPrivate, "", kPublic }, +- { "va_end", kPrivate, "", kPublic }, +- { "va_list", kPrivate, "", kPublic }, +- { "va_start", kPrivate, "", kPublic }, +- { "WEOF", kPrivate, "", kPublic }, ++ { "SIGABRT", kPrivate, "", kPrivate }, ++ { "SIGCHLD", kPrivate, "", kPrivate }, ++ { "va_arg", kPrivate, "", kPrivate }, ++ { "va_copy", kPrivate, "", kPrivate }, ++ { "va_end", kPrivate, "", kPrivate }, ++ { "va_list", kPrivate, "", kPrivate }, ++ { "va_start", kPrivate, "", kPrivate }, ++ { "WEOF", kPrivate, "", kPrivate }, + // These are symbols that could be defined in either stdlib.h or + // malloc.h, but we always want the stdlib location. +- { "malloc", kPrivate, "", kPublic }, +- { "calloc", kPrivate, "", kPublic }, +- { "realloc", kPrivate, "", kPublic }, +- { "free", kPrivate, "", kPublic }, ++ { "malloc", kPrivate, "", kPrivate }, ++ { "calloc", kPrivate, "", kPrivate }, ++ { "realloc", kPrivate, "", kPrivate }, ++ { "free", kPrivate, "", kPrivate }, + // Entries for NULL +- { "NULL", kPrivate, "", kPublic }, // 'canonical' location for NULL ++ { "NULL", kPrivate, "", kPrivate }, // 'canonical' location for NULL + { "NULL", kPrivate, "", kPublic }, + { "NULL", kPrivate, "", kPublic }, + { "NULL", kPrivate, "", kPublic }, +@@ -293,13 +293,13 @@ const IncludeMapEntry libc_symbol_map[] = { + { "NULL", kPrivate, "", kPublic }, + { "NULL", kPrivate, "", kPublic }, + { "NULL", kPrivate, "", kPublic }, +- { "NULL", kPrivate, "", kPublic }, +- { "NULL", kPrivate, "", kPublic }, +- { "NULL", kPrivate, "", kPublic }, +- { "NULL", kPrivate, "", kPublic }, +- { "NULL", kPrivate, "", kPublic }, +- { "NULL", kPrivate, "", kPublic }, +- { "offsetof", kPrivate, "", kPublic }, ++ { "NULL", kPrivate, "", kPrivate }, ++ { "NULL", kPrivate, "", kPrivate }, ++ { "NULL", kPrivate, "", kPrivate }, ++ { "NULL", kPrivate, "", kPrivate }, ++ { "NULL", kPrivate, "", kPrivate }, ++ { "NULL", kPrivate, "", kPrivate }, ++ { "offsetof", kPrivate, "", kPrivate }, + }; + + // Common kludges for C++ standard libraries +@@ -355,7 +355,7 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +@@ -363,18 +363,18 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +@@ -382,24 +382,24 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPrivate }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +@@ -409,17 +409,17 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +@@ -429,22 +429,22 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPrivate }, +@@ -459,12 +459,12 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +@@ -474,11 +474,11 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + // Sometimes libc tells you what mapping to do via an '#error': + // # error "Never use directly; include instead." +@@ -488,7 +488,7 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +@@ -498,38 +498,38 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + // Top-level #includes that just forward to another file: +@@ -541,13 +541,13 @@ const IncludeMapEntry libc_include_map[] = { + // on the POSIX.1-2024 list, I just choose the top-level one. + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +@@ -567,21 +567,21 @@ const IncludeMapEntry libc_include_map[] = { + { "", kPrivate, "", kPrivate }, + // I don't know what grep would have found these. I found them + // via user report. +- { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, // PATH_MAX ++ { "", kPrivate, "", kPrivate }, // PATH_MAX + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + // System headers available on AIX, BSD, Solaris and other Unix systems + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, +- { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + { "", kPrivate, "", kPublic }, + { "", kPrivate, "", kPublic }, + // Exports guaranteed by the C standard +- { "", kPublic, "", kPublic }, ++ { "", kPrivate, "", kPrivate }, + }; + + const IncludeMapEntry stdlib_c_include_map[] = { +@@ -601,31 +601,31 @@ const IncludeMapEntry stdlib_c_include_map[] = { + // + // $ curl -s -N https://raw.githubusercontent.com/cplusplus/draft/c%2B%2B20/source/lib-intro.tex | sed -n '/begin{multicolfloattable}.*{headers.cpp.c}/,/end{multicolfloattable}/p' | grep tcode | perl -nle 'm/tcode{}/ && print qq@ { "<$1.h>", kPublic, "", kPublic },@' | sort + { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, +- { "", kPublic, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, ++ { "", kPrivate, "", kPublic }, + }; + + const char* stdlib_cpp_public_headers[] = { diff --git a/depend/bitcoin/ci/test/02_run_container.py b/depend/bitcoin/ci/test/02_run_container.py index 311fe923..64077c4b 100755 --- a/depend/bitcoin/ci/test/02_run_container.py +++ b/depend/bitcoin/ci/test/02_run_container.py @@ -47,7 +47,26 @@ def main(): file.write(f"{k}={v}\n") run(["cat", env_file]) - if not os.getenv("DANGER_RUN_CI_ON_HOST"): + if os.getenv("DANGER_RUN_CI_ON_HOST"): + print("Running on host system without docker wrapper") + print("Create missing folders") + for create_dir in [ + os.environ["CCACHE_DIR"], + os.environ["PREVIOUS_RELEASES_DIR"], + ]: + Path(create_dir).mkdir(parents=True, exist_ok=True) + + # Modify PATH to prepend the retry script, needed for CI_RETRY_EXE + os.environ["PATH"] = f"{os.environ['BASE_ROOT_DIR']}/ci/retry:{os.environ['PATH']}" + # GNU getopt is required for the CI_RETRY_EXE script + if os.getenv("CI_OS_NAME") == "macos": + prefix = run( + ["brew", "--prefix", "gnu-getopt"], + stdout=subprocess.PIPE, + text=True, + ).stdout.strip() + os.environ["IN_GETOPT_BIN"] = f"{prefix}/bin/getopt" + else: CI_IMAGE_LABEL = "bitcoin-ci-test" # Use buildx unconditionally @@ -142,18 +161,31 @@ def main(): stdout=subprocess.PIPE, text=True, ).stdout.strip() - os.environ["CI_CONTAINER_ID"] = container_id - # GNU getopt is required for the CI_RETRY_EXE script - if os.getenv("CI_OS_NAME") == "macos": - prefix = run( - ["brew", "--prefix", "gnu-getopt"], - stdout=subprocess.PIPE, - text=True, - ).stdout.strip() - os.environ["IN_GETOPT_BIN"] = f"{prefix}/bin/getopt" + def ci_exec(cmd_inner, **kwargs): + if os.getenv("DANGER_RUN_CI_ON_HOST"): + prefix = [] + else: + prefix = ["docker", "exec", container_id] + + return run([*prefix, *cmd_inner], **kwargs) + + # Normalize all folders to BASE_ROOT_DIR + ci_exec([ + "rsync", + "--recursive", + "--perms", + "--stats", + "--human-readable", + f"{os.environ['BASE_READ_ONLY_DIR']}/", + f"{os.environ['BASE_ROOT_DIR']}", + ]) + ci_exec([f"{os.environ['BASE_ROOT_DIR']}/ci/test/01_base_install.sh"]) + ci_exec([f"{os.environ['BASE_ROOT_DIR']}/ci/test/03_test_script.sh"]) - run(["./ci/test/02_run_container.sh"]) # run the remainder + if not os.getenv("DANGER_RUN_CI_ON_HOST"): + print("Stop and remove CI container by ID") + run(["docker", "container", "kill", container_id]) if __name__ == "__main__": diff --git a/depend/bitcoin/ci/test/02_run_container.sh b/depend/bitcoin/ci/test/02_run_container.sh deleted file mode 100755 index 41128b5c..00000000 --- a/depend/bitcoin/ci/test/02_run_container.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) 2018-present 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 - -set -o errexit -o pipefail -o xtrace - -if [ -z "$DANGER_RUN_CI_ON_HOST" ]; then - export CI_EXEC_CMD_PREFIX="docker exec ${CI_CONTAINER_ID}" -else - echo "Running on host system without docker wrapper" - echo "Create missing folders" - mkdir -p "${CCACHE_DIR}" - mkdir -p "${PREVIOUS_RELEASES_DIR}" -fi - -CI_EXEC () { - $CI_EXEC_CMD_PREFIX bash -c "export PATH=\"/path_with space:${BASE_ROOT_DIR}/ci/retry:\$PATH\" && cd \"${BASE_ROOT_DIR}\" && $*" -} -export -f CI_EXEC - -# Normalize all folders to BASE_ROOT_DIR -CI_EXEC rsync --recursive --perms --stats --human-readable "${BASE_READ_ONLY_DIR}/" "${BASE_ROOT_DIR}" || echo "Nothing to copy from ${BASE_READ_ONLY_DIR}/" -CI_EXEC "${BASE_ROOT_DIR}/ci/test/01_base_install.sh" -CI_EXEC "${BASE_ROOT_DIR}/ci/test/03_test_script.sh" - -if [ -z "$DANGER_RUN_CI_ON_HOST" ]; then - echo "Stop and remove CI container by ID" - docker container kill "${CI_CONTAINER_ID}" -fi diff --git a/depend/bitcoin/ci/test/03_test_script.sh b/depend/bitcoin/ci/test/03_test_script.sh index e61dc33e..1cf9eb23 100755 --- a/depend/bitcoin/ci/test/03_test_script.sh +++ b/depend/bitcoin/ci/test/03_test_script.sh @@ -8,6 +8,9 @@ export LC_ALL=C.UTF-8 set -ex +cd "${BASE_ROOT_DIR}" + +export PATH="/path_with space:${PATH}" export ASAN_OPTIONS="detect_leaks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1" export LSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/lsan" export TSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/tsan:halt_on_error=1:second_deadlock_stack=1" @@ -41,10 +44,10 @@ echo "=== BEGIN env ===" env echo "=== END env ===" -# Don't apply patches in the tidy job, because it relies on the `git diff` -# command to detect IWYU errors. It is safe to skip this patch in the tidy job +# Don't apply patches in the iwyu job, because it relies on the `git diff` +# command to detect IWYU errors. It is safe to skip this patch in the iwyu job # because it doesn't run a UB detector. -if [ "$RUN_TIDY" != "true" ]; then +if [[ "${RUN_IWYU}" != true ]]; then # compact->outputs[i].file_size is uninitialized memory, so reading it is UB. # The statistic bytes_written is only used for logging, which is disabled in # CI, so as a temporary minimal fix to work around UB and CI failures, leave @@ -120,7 +123,7 @@ BASE_BUILD_DIR=${BASE_BUILD_DIR:-$BASE_SCRATCH_DIR/build-$HOST} BITCOIN_CONFIG_ALL="$BITCOIN_CONFIG_ALL -DCMAKE_INSTALL_PREFIX=$BASE_OUTDIR -Werror=dev" -if [[ "${RUN_TIDY}" == "true" ]]; then +if [[ "${RUN_IWYU}" == true || "${RUN_TIDY}" == true ]]; then BITCOIN_CONFIG_ALL="$BITCOIN_CONFIG_ALL -DCMAKE_EXPORT_COMPILE_COMMANDS=ON" fi @@ -132,11 +135,15 @@ cmake -S "$BASE_ROOT_DIR" -B "$BASE_BUILD_DIR" "${CMAKE_ARGS[@]}" || ( false ) +if [[ "${GOAL}" != all && "${GOAL}" != codegen ]]; then + GOAL="all ${GOAL}" +fi + # shellcheck disable=SC2086 -cmake --build "${BASE_BUILD_DIR}" "$MAKEJOBS" --target all $GOAL || ( +cmake --build "${BASE_BUILD_DIR}" "$MAKEJOBS" --target $GOAL || ( echo "Build failure. Verbose build follows." # shellcheck disable=SC2086 - cmake --build "${BASE_BUILD_DIR}" -j1 --target all $GOAL --verbose + cmake --build "${BASE_BUILD_DIR}" -j1 --target $GOAL --verbose false ) @@ -204,9 +211,11 @@ if [ "${RUN_TIDY}" = "true" ]; then echo "^^^ ⚠️ Failure generated from clang-tidy" false fi +fi +if [[ "${RUN_IWYU}" == true ]]; then # TODO: Consider enforcing IWYU across the entire codebase. - FILES_WITH_ENFORCED_IWYU="/src/(crypto|index)/.*\\.cpp" + FILES_WITH_ENFORCED_IWYU="/src/((crypto|index)/.*\\.cpp|node/blockstorage.cpp|node/utxo_snapshot.cpp|core_read.cpp|signet.cpp|kernel/chain.cpp)" jq --arg patterns "$FILES_WITH_ENFORCED_IWYU" 'map(select(.file | test($patterns)))' "${BASE_BUILD_DIR}/compile_commands.json" > "${BASE_BUILD_DIR}/compile_commands_iwyu_errors.json" jq --arg patterns "$FILES_WITH_ENFORCED_IWYU" 'map(select(.file | test($patterns) | not))' "${BASE_BUILD_DIR}/compile_commands.json" > "${BASE_BUILD_DIR}/compile_commands_iwyu_warnings.json" @@ -220,6 +229,7 @@ if [ "${RUN_TIDY}" = "true" ]; then -Xiwyu --max_line_length=160 \ 2>&1 | tee /tmp/iwyu_ci.out python3 "/include-what-you-use/fix_includes.py" --nosafe_headers < /tmp/iwyu_ci.out + git diff -U0 | ./contrib/devtools/clang-format-diff.py -binary="clang-format-${TIDY_LLVM_V}" -p1 -i -v } run_iwyu "compile_commands_iwyu_errors.json" diff --git a/depend/bitcoin/ci/test_imagefile b/depend/bitcoin/ci/test_imagefile index a0e1714e..93494cc1 100644 --- a/depend/bitcoin/ci/test_imagefile +++ b/depend/bitcoin/ci/test_imagefile @@ -14,8 +14,9 @@ ENV FILE_ENV=${FILE_ENV} ARG BASE_ROOT_DIR ENV BASE_ROOT_DIR=${BASE_ROOT_DIR} +# Make retry available in PATH, needed for CI_RETRY_EXE COPY ./ci/retry/retry /usr/bin/retry -COPY ./ci/test/00_setup_env.sh ./${FILE_ENV} ./ci/test/01_base_install.sh /ci_container_base/ci/test/ +COPY ./ci/test/00_setup_env.sh ./${FILE_ENV} ./ci/test/01_base_install.sh ./ci/test/01_iwyu.patch /ci_container_base/ci/test/ # Bash is required, so install it when missing RUN sh -c "bash -c 'true' || ( apk update && apk add --no-cache bash )" diff --git a/depend/bitcoin/cmake/libmultiprocess.cmake b/depend/bitcoin/cmake/libmultiprocess.cmake index 5db8f4e9..027109a9 100644 --- a/depend/bitcoin/cmake/libmultiprocess.cmake +++ b/depend/bitcoin/cmake/libmultiprocess.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2025 The Bitcoin Core developers +# Copyright (c) 2025-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://opensource.org/license/mit/. @@ -27,7 +27,7 @@ function(add_libmultiprocess subdir) mark_as_advanced(CapnProto_kj-tls_IMPORTED_LOCATION) if(BUILD_TESTS) # Add tests to "all" target so ctest can run them - set_target_properties(mptests PROPERTIES EXCLUDE_FROM_ALL OFF) + set_target_properties(mptest PROPERTIES EXCLUDE_FROM_ALL OFF) endif() # Exclude examples from compilation database, because the examples are not # built by default, and they contain generated c++ code. Without this diff --git a/depend/bitcoin/cmake/module/AddBoostIfNeeded.cmake b/depend/bitcoin/cmake/module/AddBoostIfNeeded.cmake index e2eaf556..b3f24800 100644 --- a/depend/bitcoin/cmake/module/AddBoostIfNeeded.cmake +++ b/depend/bitcoin/cmake/module/AddBoostIfNeeded.cmake @@ -29,7 +29,7 @@ function(add_boost_if_needed) endif() endif() - find_package(Boost 1.73.0 REQUIRED CONFIG) + find_package(Boost 1.74.0 REQUIRED CONFIG) mark_as_advanced(Boost_INCLUDE_DIR boost_headers_DIR) # Workaround for a bug in NetBSD pkgsrc. # See: https://github.com/NetBSD/pkgsrc/issues/167. diff --git a/depend/bitcoin/contrib/asmap/asmap-tool.py b/depend/bitcoin/contrib/asmap/asmap-tool.py index c679ab15..b594e479 100755 --- a/depend/bitcoin/contrib/asmap/asmap-tool.py +++ b/depend/bitcoin/contrib/asmap/asmap-tool.py @@ -131,6 +131,8 @@ def main(): if args.subcommand is None: parser.print_help() elif args.subcommand == "encode": + if args.outfile.isatty(): + sys.exit("Not much use in writing binary to a TTY. Please specify an output file or pipe output to another process.") state = load_file(args.infile) save_binary(args.outfile, state, fill=args.fill) elif args.subcommand == "decode": diff --git a/depend/bitcoin/contrib/completions/bash/bitcoin-cli.bash b/depend/bitcoin/contrib/completions/bash/bitcoin-cli.bash index 3018d076..ff34ad9f 100644 --- a/depend/bitcoin/contrib/completions/bash/bitcoin-cli.bash +++ b/depend/bitcoin/contrib/completions/bash/bitcoin-cli.bash @@ -1,5 +1,5 @@ # bash programmable completion for bitcoin-cli(1) -# Copyright (c) 2012-2022 The Bitcoin Core developers +# Copyright (c) 2012-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/contrib/completions/bash/bitcoin-tx.bash b/depend/bitcoin/contrib/completions/bash/bitcoin-tx.bash index 51a9fe31..28359bfd 100644 --- a/depend/bitcoin/contrib/completions/bash/bitcoin-tx.bash +++ b/depend/bitcoin/contrib/completions/bash/bitcoin-tx.bash @@ -1,5 +1,5 @@ # bash programmable completion for bitcoin-tx(1) -# Copyright (c) 2016-2022 The Bitcoin Core developers +# Copyright (c) 2016-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/contrib/completions/bash/bitcoind.bash b/depend/bitcoin/contrib/completions/bash/bitcoind.bash index c11d99ef..78e4d4e5 100644 --- a/depend/bitcoin/contrib/completions/bash/bitcoind.bash +++ b/depend/bitcoin/contrib/completions/bash/bitcoind.bash @@ -1,5 +1,5 @@ # bash programmable completion for bitcoind(1) and bitcoin-qt(1) -# Copyright (c) 2012-2022 The Bitcoin Core developers +# Copyright (c) 2012-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/contrib/devtools/gen-bitcoin-conf.sh b/depend/bitcoin/contrib/devtools/gen-bitcoin-conf.sh index d31f5462..05618252 100755 --- a/depend/bitcoin/contrib/devtools/gen-bitcoin-conf.sh +++ b/depend/bitcoin/contrib/devtools/gen-bitcoin-conf.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Copyright (c) 2021 The Bitcoin Core developers +# Copyright (c) 2021-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/contrib/devtools/gen-manpages.py b/depend/bitcoin/contrib/devtools/gen-manpages.py index 02e5f839..94187944 100755 --- a/depend/bitcoin/contrib/devtools/gen-manpages.py +++ b/depend/bitcoin/contrib/devtools/gen-manpages.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2022 The Bitcoin Core developers +# Copyright (c) 2022-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. import os diff --git a/depend/bitcoin/contrib/devtools/iwyu/bitcoin.core.imp b/depend/bitcoin/contrib/devtools/iwyu/bitcoin.core.imp index c3195e51..9067bc32 100644 --- a/depend/bitcoin/contrib/devtools/iwyu/bitcoin.core.imp +++ b/depend/bitcoin/contrib/devtools/iwyu/bitcoin.core.imp @@ -13,4 +13,8 @@ { "symbol": ["SEEK_CUR", "private", "", "public"] }, { "symbol": ["SEEK_END", "private", "", "public"] }, { "symbol": ["SEEK_SET", "private", "", "public"] }, + + # IWYU bug. + # See: https://github.com/include-what-you-use/include-what-you-use/issues/1863. + { "symbol": ["std::vector", "private", "", "public"] }, ] diff --git a/depend/bitcoin/contrib/devtools/utils.py b/depend/bitcoin/contrib/devtools/utils.py index 8b4c67c6..7f37c607 100755 --- a/depend/bitcoin/contrib/devtools/utils.py +++ b/depend/bitcoin/contrib/devtools/utils.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2021 The Bitcoin Core developers +# Copyright (c) 2021-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' diff --git a/depend/bitcoin/contrib/guix/libexec/build.sh b/depend/bitcoin/contrib/guix/libexec/build.sh index 48301841..f4db25f4 100755 --- a/depend/bitcoin/contrib/guix/libexec/build.sh +++ b/depend/bitcoin/contrib/guix/libexec/build.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Copyright (c) 2019-2022 The Bitcoin Core developers +# Copyright (c) 2019-present 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 diff --git a/depend/bitcoin/contrib/guix/libexec/codesign.sh b/depend/bitcoin/contrib/guix/libexec/codesign.sh index fe860653..9ea683b9 100755 --- a/depend/bitcoin/contrib/guix/libexec/codesign.sh +++ b/depend/bitcoin/contrib/guix/libexec/codesign.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Copyright (c) 2021-2022 The Bitcoin Core developers +# Copyright (c) 2021-present 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 diff --git a/depend/bitcoin/contrib/guix/security-check.py b/depend/bitcoin/contrib/guix/security-check.py index be2e0cfb..2a6e26b6 100755 --- a/depend/bitcoin/contrib/guix/security-check.py +++ b/depend/bitcoin/contrib/guix/security-check.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2022 The Bitcoin Core developers +# Copyright (c) 2015-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' diff --git a/depend/bitcoin/contrib/macdeploy/detached-sig-create.sh b/depend/bitcoin/contrib/macdeploy/detached-sig-create.sh index b558784e..efb0d247 100755 --- a/depend/bitcoin/contrib/macdeploy/detached-sig-create.sh +++ b/depend/bitcoin/contrib/macdeploy/detached-sig-create.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Copyright (c) 2014-2022 The Bitcoin Core developers +# Copyright (c) 2014-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/contrib/qos/tc.sh b/depend/bitcoin/contrib/qos/tc.sh index 7ebcbf22..2c48fc2a 100755 --- a/depend/bitcoin/contrib/qos/tc.sh +++ b/depend/bitcoin/contrib/qos/tc.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Copyright (c) 2017-2021 The Bitcoin Core developers +# Copyright (c) 2017-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/contrib/seeds/generate-seeds.py b/depend/bitcoin/contrib/seeds/generate-seeds.py index 9ad48805..2dfad0c7 100755 --- a/depend/bitcoin/contrib/seeds/generate-seeds.py +++ b/depend/bitcoin/contrib/seeds/generate-seeds.py @@ -160,6 +160,9 @@ def main(): sys.exit(1) g = sys.stdout indir = sys.argv[1] + g.write('// Copyright (c) The Bitcoin Core developers\n') + g.write('// Distributed under the MIT software license, see the accompanying\n') + g.write('// file COPYING or https://opensource.org/license/mit.\n\n') g.write('#ifndef BITCOIN_CHAINPARAMSSEEDS_H\n') g.write('#define BITCOIN_CHAINPARAMSSEEDS_H\n') g.write('/**\n') diff --git a/depend/bitcoin/contrib/signet/getcoins.py b/depend/bitcoin/contrib/signet/getcoins.py index 75430e5b..b58ed04a 100755 --- a/depend/bitcoin/contrib/signet/getcoins.py +++ b/depend/bitcoin/contrib/signet/getcoins.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2020-2022 The Bitcoin Core developers +# Copyright (c) 2020-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/contrib/signet/miner b/depend/bitcoin/contrib/signet/miner index 8c7edc56..f46d88b5 100755 --- a/depend/bitcoin/contrib/signet/miner +++ b/depend/bitcoin/contrib/signet/miner @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2020 The Bitcoin Core developers +# Copyright (c) 2020-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/contrib/testgen/gen_key_io_test_vectors.py b/depend/bitcoin/contrib/testgen/gen_key_io_test_vectors.py index 7bfb1d76..ceefd7a8 100755 --- a/depend/bitcoin/contrib/testgen/gen_key_io_test_vectors.py +++ b/depend/bitcoin/contrib/testgen/gen_key_io_test_vectors.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2012-2022 The Bitcoin Core developers +# Copyright (c) 2012-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' diff --git a/depend/bitcoin/contrib/tracing/log_raw_p2p_msgs.py b/depend/bitcoin/contrib/tracing/log_raw_p2p_msgs.py index 1c0f03e1..ff181b00 100755 --- a/depend/bitcoin/contrib/tracing/log_raw_p2p_msgs.py +++ b/depend/bitcoin/contrib/tracing/log_raw_p2p_msgs.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2021 The Bitcoin Core developers +# Copyright (c) 2021-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/contrib/tracing/log_utxocache_flush.py b/depend/bitcoin/contrib/tracing/log_utxocache_flush.py index 8ff9cd5e..230b38e9 100755 --- a/depend/bitcoin/contrib/tracing/log_utxocache_flush.py +++ b/depend/bitcoin/contrib/tracing/log_utxocache_flush.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2021-2022 The Bitcoin Core developers +# Copyright (c) 2021-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/contrib/tracing/mempool_monitor.py b/depend/bitcoin/contrib/tracing/mempool_monitor.py index c5f672fb..03c5c59f 100755 --- a/depend/bitcoin/contrib/tracing/mempool_monitor.py +++ b/depend/bitcoin/contrib/tracing/mempool_monitor.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2022 The Bitcoin Core developers +# Copyright (c) 2022-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/contrib/tracing/p2p_monitor.py b/depend/bitcoin/contrib/tracing/p2p_monitor.py index 51af6037..d486f566 100755 --- a/depend/bitcoin/contrib/tracing/p2p_monitor.py +++ b/depend/bitcoin/contrib/tracing/p2p_monitor.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2021 The Bitcoin Core developers +# Copyright (c) 2021-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/contrib/verify-commits/gpg.sh b/depend/bitcoin/contrib/verify-commits/gpg.sh index cfd68e45..3579a70a 100755 --- a/depend/bitcoin/contrib/verify-commits/gpg.sh +++ b/depend/bitcoin/contrib/verify-commits/gpg.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Copyright (c) 2014-2019 The Bitcoin Core developers +# Copyright (c) 2014-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/contrib/verify-commits/pre-push-hook.sh b/depend/bitcoin/contrib/verify-commits/pre-push-hook.sh index 99532483..a532bf74 100755 --- a/depend/bitcoin/contrib/verify-commits/pre-push-hook.sh +++ b/depend/bitcoin/contrib/verify-commits/pre-push-hook.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Copyright (c) 2014-2021 The Bitcoin Core developers +# Copyright (c) 2014-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/contrib/windeploy/detached-sig-create.sh b/depend/bitcoin/contrib/windeploy/detached-sig-create.sh index 4ec72653..f417b046 100755 --- a/depend/bitcoin/contrib/windeploy/detached-sig-create.sh +++ b/depend/bitcoin/contrib/windeploy/detached-sig-create.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Copyright (c) 2014-2021 The Bitcoin Core developers +# Copyright (c) 2014-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/contrib/zmq/zmq_sub.py b/depend/bitcoin/contrib/zmq/zmq_sub.py index b2290a6c..59639c45 100755 --- a/depend/bitcoin/contrib/zmq/zmq_sub.py +++ b/depend/bitcoin/contrib/zmq/zmq_sub.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2014-2021 The Bitcoin Core developers +# Copyright (c) 2014-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/doc/dependencies.md b/depend/bitcoin/doc/dependencies.md index 3ff306f8..0d7d8b3a 100644 --- a/depend/bitcoin/doc/dependencies.md +++ b/depend/bitcoin/doc/dependencies.md @@ -19,7 +19,7 @@ Bitcoin Core requires one of the following compilers. | Dependency | Releases | Minimum required | | --- | --- | --- | -| [Boost](../depends/packages/boost.mk) | [link](https://www.boost.org/users/download/) | [1.73.0](https://github.com/bitcoin/bitcoin/pull/29066) | +| [Boost](../depends/packages/boost.mk) | [link](https://www.boost.org/users/download/) | [1.74.0](https://github.com/bitcoin/bitcoin/pull/34107) | | CMake | [link](https://cmake.org/) | [3.22](https://github.com/bitcoin/bitcoin/pull/30454) | | [libevent](../depends/packages/libevent.mk) | [link](https://github.com/libevent/libevent/releases) | [2.1.8](https://github.com/bitcoin/bitcoin/pull/24681) | diff --git a/depend/bitcoin/doc/design/assumeutxo.md b/depend/bitcoin/doc/design/assumeutxo.md index 123c02ac..9f04a52b 100644 --- a/depend/bitcoin/doc/design/assumeutxo.md +++ b/depend/bitcoin/doc/design/assumeutxo.md @@ -63,7 +63,7 @@ chainstate and a sync to tip begins. A new chainstate directory is created in th datadir for the snapshot chainstate called `chainstate_snapshot`. When this directory is present in the datadir, the snapshot chainstate will be detected -and loaded as active on node startup (via `DetectSnapshotChainstate()`). +and loaded as active on node startup (via `LoadAssumeutxoChainstate()`). A special file is created within that directory, `base_blockhash`, which contains the serialized `uint256` of the base block of the snapshot. This is used to reinitialize @@ -97,14 +97,13 @@ sequentially. ### Background chainstate hits snapshot base block Once the tip of the background chainstate hits the base block of the snapshot -chainstate, we stop use of the background chainstate by setting `m_disabled`, in -`MaybeCompleteSnapshotValidation()`, which is checked in `ActivateBestChain()`). We hash the +chainstate, we hash the background chainstate's UTXO set contents and ensure it matches the compiled value in `CMainParams::m_assumeutxo_data`. | | | | ---------- | ----------- | -| number of chainstates | 2 (ibd has `m_disabled=true`) | +| number of chainstates | 2 | | active chainstate | snapshot | The background chainstate data lingers on disk until the program is restarted. diff --git a/depend/bitcoin/doc/fuzzing.md b/depend/bitcoin/doc/fuzzing.md index 564245b7..7564bbd7 100644 --- a/depend/bitcoin/doc/fuzzing.md +++ b/depend/bitcoin/doc/fuzzing.md @@ -82,7 +82,7 @@ of the test. Just make sure to use double-dash to distinguish them from the fuzzer's own arguments: ```sh -$ FUZZ=address_deserialize_v2 build_fuzz/bin/fuzz -runs=1 fuzz_corpora/address_deserialize_v2 --checkaddrman=5 --printtoconsole=1 +$ FUZZ=address_deserialize build_fuzz/bin/fuzz -runs=1 fuzz_corpora/address_deserialize --checkaddrman=5 --printtoconsole=1 ``` ## Fuzzing corpora diff --git a/depend/bitcoin/doc/policy/packages.md b/depend/bitcoin/doc/policy/packages.md index 4795f715..d48afed4 100644 --- a/depend/bitcoin/doc/policy/packages.md +++ b/depend/bitcoin/doc/policy/packages.md @@ -99,14 +99,6 @@ submitted as a package. transaction (i.e. in which a replacement transaction with a higher fee cannot be signed) being rejected from the mempool when transaction volume is high and the mempool minimum feerate rises. -Note: Package feerate cannot be used to meet the minimum relay feerate (`-minrelaytxfee`) -requirement. For example, if the mempool minimum feerate is 5sat/vB and the minimum relay feerate is -set to 5sat/vB, a 1sat/vB parent transaction with a high-feerate child will not be accepted, even if -submitted as a package. Note that this rule does not apply to -[TRUC transactions](https://github.com/bitcoin/bips/blob/master/bip-0431.mediawiki) as an individual -TRUC transaction is permitted to be below the mempool min relay feerate, assuming it is considered within -a package that meets the mempool's feerate requirements. - *Rationale*: Avoid situations in which the mempool contains non-bumped transactions below min relay feerate (which we consider to have pay 0 fees and thus receiving free relay). While package submission would ensure these transactions are bumped at the time of entry, it is not guaranteed diff --git a/depend/bitcoin/doc/release-notes-33657.md b/depend/bitcoin/doc/release-notes-33657.md index f9e6841b..a9821323 100644 --- a/depend/bitcoin/doc/release-notes-33657.md +++ b/depend/bitcoin/doc/release-notes-33657.md @@ -1,5 +1,5 @@ New REST API ------------ -- A new REST API endpoint (`/rest/blockpart/BLOCKHASH.bin?offset=X&size=Y`) has been introduced - for efficiently fetching a range of bytes from block `BLOCKHASH`. +- A new REST API endpoint (`/rest/blockpart/.?offset=&size=`) has been introduced + for efficiently fetching a range of bytes from block ``. diff --git a/depend/bitcoin/doc/release-notes-33892.md b/depend/bitcoin/doc/release-notes-33892.md new file mode 100644 index 00000000..e9d41b80 --- /dev/null +++ b/depend/bitcoin/doc/release-notes-33892.md @@ -0,0 +1,8 @@ +P2P and network changes +----------------------- + +- Transactions participating in one-parent-one-child package relay can now have the parent + with a feerate lower than the `-minrelaytxfee` feerate, even 0 fee. This expands the change + from 28.0 to also cover packages of non-TRUC transactions. Note that in general the + package child can have additional unconfirmed parents, but they must already be + in-mempool for the new package to be relayed. (#33892) diff --git a/depend/bitcoin/doc/release-notes-34088.md b/depend/bitcoin/doc/release-notes-34088.md new file mode 100644 index 00000000..5aa8a9d9 --- /dev/null +++ b/depend/bitcoin/doc/release-notes-34088.md @@ -0,0 +1,2 @@ +- When `-logsourcelocations` is enabled, the log output now contains just the + function name instead of the entire function signature. (#34088) diff --git a/depend/bitcoin/share/qt/translate.cmake b/depend/bitcoin/share/qt/translate.cmake index ed32c6dd..2ac8c7f0 100644 --- a/depend/bitcoin/share/qt/translate.cmake +++ b/depend/bitcoin/share/qt/translate.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2025 The Bitcoin Core developers +# Copyright (c) 2025-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/share/rpcauth/rpcauth.py b/depend/bitcoin/share/rpcauth/rpcauth.py index 506fcf9d..ba91e0bc 100755 --- a/depend/bitcoin/share/rpcauth/rpcauth.py +++ b/depend/bitcoin/share/rpcauth/rpcauth.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2021 The Bitcoin Core developers +# Copyright (c) 2015-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/.clang-format b/depend/bitcoin/src/.clang-format index c5fcd0b4..4db09138 100644 --- a/depend/bitcoin/src/.clang-format +++ b/depend/bitcoin/src/.clang-format @@ -97,7 +97,7 @@ ForEachMacros: - BOOST_FOREACH IfMacros: - KJ_IF_MAYBE -IncludeBlocks: Preserve +IncludeBlocks: Regroup IncludeCategories: - Regex: '^' Priority: -1 diff --git a/depend/bitcoin/src/.clang-tidy b/depend/bitcoin/src/.clang-tidy index da53a588..01153649 100644 --- a/depend/bitcoin/src/.clang-tidy +++ b/depend/bitcoin/src/.clang-tidy @@ -25,6 +25,7 @@ performance-*, -performance-noexcept-move-constructor, -performance-unnecessary-value-param, readability-const-return-type, +readability-container-contains, readability-redundant-declaration, readability-redundant-string-init, ' diff --git a/depend/bitcoin/src/CMakeLists.txt b/depend/bitcoin/src/CMakeLists.txt index 47aee937..43d67f40 100644 --- a/depend/bitcoin/src/CMakeLists.txt +++ b/depend/bitcoin/src/CMakeLists.txt @@ -43,7 +43,7 @@ add_custom_target(generate_build_info COMMENT "Generating bitcoin-build-info.h" VERBATIM ) -add_library(bitcoin_clientversion STATIC EXCLUDE_FROM_ALL +add_library(bitcoin_clientversion STATIC clientversion.cpp ) target_link_libraries(bitcoin_clientversion diff --git a/depend/bitcoin/src/addrdb.h b/depend/bitcoin/src/addrdb.h index cc3014dc..44e51ce8 100644 --- a/depend/bitcoin/src/addrdb.h +++ b/depend/bitcoin/src/addrdb.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2021 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/addresstype.cpp b/depend/bitcoin/src/addresstype.cpp index 67e64394..410879b4 100644 --- a/depend/bitcoin/src/addresstype.cpp +++ b/depend/bitcoin/src/addresstype.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2023 The Bitcoin Core developers +// Copyright (c) 2023-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/addresstype.h b/depend/bitcoin/src/addresstype.h index 78d3126d..862049de 100644 --- a/depend/bitcoin/src/addresstype.h +++ b/depend/bitcoin/src/addresstype.h @@ -1,4 +1,4 @@ -// Copyright (c) 2023 The Bitcoin Core developers +// Copyright (c) 2023-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/addrman.cpp b/depend/bitcoin/src/addrman.cpp index 5cd1d41f..206b5411 100644 --- a/depend/bitcoin/src/addrman.cpp +++ b/depend/bitcoin/src/addrman.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012 Pieter Wuille -// Copyright (c) 2012-2022 The Bitcoin Core developers +// Copyright (c) 2012-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -457,7 +457,7 @@ void AddrManImpl::Delete(nid_type nId) { AssertLockHeld(cs); - assert(mapInfo.count(nId) != 0); + assert(mapInfo.contains(nId)); AddrInfo& info = mapInfo[nId]; assert(!info.fInTried); assert(info.nRefCount == 0); @@ -516,7 +516,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, nid_type nId) if (vvTried[nKBucket][nKBucketPos] != -1) { // find an item to evict nid_type nIdEvict = vvTried[nKBucket][nKBucketPos]; - assert(mapInfo.count(nIdEvict) == 1); + assert(mapInfo.contains(nIdEvict)); AddrInfo& infoOld = mapInfo[nIdEvict]; // Remove the to-be-evicted item from the tried set. @@ -919,7 +919,7 @@ void AddrManImpl::ResolveCollisions_() bool erase_collision = false; // If id_new not found in mapInfo remove it from m_tried_collisions - if (mapInfo.count(id_new) != 1) { + if (!mapInfo.contains(id_new)) { erase_collision = true; } else { AddrInfo& info_new = mapInfo[id_new]; @@ -985,7 +985,7 @@ std::pair AddrManImpl::SelectTriedCollision_() nid_type id_new = *it; // If id_new not found in mapInfo remove it from m_tried_collisions - if (mapInfo.count(id_new) != 1) { + if (!mapInfo.contains(id_new)) { m_tried_collisions.erase(it); return {}; } @@ -1115,7 +1115,7 @@ int AddrManImpl::CheckAddrman() const for (int n = 0; n < ADDRMAN_TRIED_BUCKET_COUNT; n++) { for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) { if (vvTried[n][i] != -1) { - if (!setTried.count(vvTried[n][i])) + if (!setTried.contains(vvTried[n][i])) return -11; const auto it{mapInfo.find(vvTried[n][i])}; if (it == mapInfo.end() || it->second.GetTriedBucket(nKey, m_netgroupman) != n) { @@ -1132,7 +1132,7 @@ int AddrManImpl::CheckAddrman() const for (int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; n++) { for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) { if (vvNew[n][i] != -1) { - if (!mapNew.count(vvNew[n][i])) + if (!mapNew.contains(vvNew[n][i])) return -12; const auto it{mapInfo.find(vvNew[n][i])}; if (it == mapInfo.end() || it->second.GetBucketPosition(nKey, true, n) != i) { diff --git a/depend/bitcoin/src/addrman.h b/depend/bitcoin/src/addrman.h index 2ddf1468..3a323014 100644 --- a/depend/bitcoin/src/addrman.h +++ b/depend/bitcoin/src/addrman.h @@ -1,5 +1,5 @@ // Copyright (c) 2012 Pieter Wuille -// Copyright (c) 2012-2022 The Bitcoin Core developers +// Copyright (c) 2012-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/addrman_impl.h b/depend/bitcoin/src/addrman_impl.h index a0390b71..f825d20b 100644 --- a/depend/bitcoin/src/addrman_impl.h +++ b/depend/bitcoin/src/addrman_impl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2021-2022 The Bitcoin Core developers +// Copyright (c) 2021-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/arith_uint256.cpp b/depend/bitcoin/src/arith_uint256.cpp index 850fc624..392f052c 100644 --- a/depend/bitcoin/src/arith_uint256.cpp +++ b/depend/bitcoin/src/arith_uint256.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/attributes.h b/depend/bitcoin/src/attributes.h index a4603b02..275dad9f 100644 --- a/depend/bitcoin/src/attributes.h +++ b/depend/bitcoin/src/attributes.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2020 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/banman.cpp b/depend/bitcoin/src/banman.cpp index 32a3cda6..499595a4 100644 --- a/depend/bitcoin/src/banman.cpp +++ b/depend/bitcoin/src/banman.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/addrman.cpp b/depend/bitcoin/src/bench/addrman.cpp index ceef6c29..4ba02242 100644 --- a/depend/bitcoin/src/bench/addrman.cpp +++ b/depend/bitcoin/src/bench/addrman.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020-2022 The Bitcoin Core developers +// Copyright (c) 2020-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/base58.cpp b/depend/bitcoin/src/bench/base58.cpp index f078c339..bc82d739 100644 --- a/depend/bitcoin/src/bench/base58.cpp +++ b/depend/bitcoin/src/bench/base58.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2022 The Bitcoin Core developers +// Copyright (c) 2016-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/bech32.cpp b/depend/bitcoin/src/bench/bech32.cpp index 6aa73bd0..065ee9e7 100644 --- a/depend/bitcoin/src/bench/bech32.cpp +++ b/depend/bitcoin/src/bench/bech32.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2022 The Bitcoin Core developers +// Copyright (c) 2018-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/bench.cpp b/depend/bitcoin/src/bench/bench.cpp index 9cc1f30f..3eb99ab5 100644 --- a/depend/bitcoin/src/bench/bench.cpp +++ b/depend/bitcoin/src/bench/bench.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2022 The Bitcoin Core developers +// Copyright (c) 2015-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/bench.h b/depend/bitcoin/src/bench/bench.h index 2df203ce..f6c41486 100644 --- a/depend/bitcoin/src/bench/bench.h +++ b/depend/bitcoin/src/bench/bench.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2022 The Bitcoin Core developers +// Copyright (c) 2015-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/bench_bitcoin.cpp b/depend/bitcoin/src/bench/bench_bitcoin.cpp index 88afe68a..841d6258 100644 --- a/depend/bitcoin/src/bench/bench_bitcoin.cpp +++ b/depend/bitcoin/src/bench/bench_bitcoin.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2022 The Bitcoin Core developers +// Copyright (c) 2015-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/bip324_ecdh.cpp b/depend/bitcoin/src/bench/bip324_ecdh.cpp index e6a614da..b94c2bd2 100644 --- a/depend/bitcoin/src/bench/bip324_ecdh.cpp +++ b/depend/bitcoin/src/bench/bip324_ecdh.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022 The Bitcoin Core developers +// Copyright (c) 2022-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/block_assemble.cpp b/depend/bitcoin/src/bench/block_assemble.cpp index 00102aef..4214d635 100644 --- a/depend/bitcoin/src/bench/block_assemble.cpp +++ b/depend/bitcoin/src/bench/block_assemble.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2022 The Bitcoin Core developers +// Copyright (c) 2011-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/ccoins_caching.cpp b/depend/bitcoin/src/bench/ccoins_caching.cpp index 35186153..26d15fc2 100644 --- a/depend/bitcoin/src/bench/ccoins_caching.cpp +++ b/depend/bitcoin/src/bench/ccoins_caching.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2022 The Bitcoin Core developers +// Copyright (c) 2016-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/chacha20.cpp b/depend/bitcoin/src/bench/chacha20.cpp index f154d8c6..cc029b1b 100644 --- a/depend/bitcoin/src/bench/chacha20.cpp +++ b/depend/bitcoin/src/bench/chacha20.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2022 The Bitcoin Core developers +// Copyright (c) 2019-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/checkblock.cpp b/depend/bitcoin/src/bench/checkblock.cpp index 9558d64f..acf29767 100644 --- a/depend/bitcoin/src/bench/checkblock.cpp +++ b/depend/bitcoin/src/bench/checkblock.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2022 The Bitcoin Core developers +// Copyright (c) 2016-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/checkqueue.cpp b/depend/bitcoin/src/bench/checkqueue.cpp index c7aed5b7..2aa715cb 100644 --- a/depend/bitcoin/src/bench/checkqueue.cpp +++ b/depend/bitcoin/src/bench/checkqueue.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2022 The Bitcoin Core developers +// Copyright (c) 2015-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/cluster_linearize.cpp b/depend/bitcoin/src/bench/cluster_linearize.cpp index 1cd36b53..a856d247 100644 --- a/depend/bitcoin/src/bench/cluster_linearize.cpp +++ b/depend/bitcoin/src/bench/cluster_linearize.cpp @@ -18,21 +18,6 @@ using namespace util::hex_literals; namespace { -/** Construct a linear graph. These are pessimal for AncestorCandidateFinder, as they maximize - * the number of ancestor set feerate updates. The best ancestor set is always the topmost - * remaining transaction, whose removal requires updating all remaining transactions' ancestor - * set feerates. */ -template -DepGraph MakeLinearGraph(DepGraphIndex ntx) -{ - DepGraph depgraph; - for (DepGraphIndex i = 0; i < ntx; ++i) { - depgraph.AddTransaction({-int32_t(i), 1}); - if (i > 0) depgraph.AddDependencies(SetType::Singleton(i - 1), i); - } - return depgraph; -} - /** Construct a wide graph (one root, with N-1 children that are otherwise unrelated, with * increasing feerates). These graphs are pessimal for the LIMO step in Linearize, because * rechunking is needed after every candidate (the last transaction gets picked every time). @@ -48,136 +33,6 @@ DepGraph MakeWideGraph(DepGraphIndex ntx) return depgraph; } -// Construct a difficult graph. These need at least sqrt(2^(n-1)) iterations in the implemented -// algorithm (purely empirically determined). -template -DepGraph MakeHardGraph(DepGraphIndex ntx) -{ - DepGraph depgraph; - for (DepGraphIndex i = 0; i < ntx; ++i) { - if (ntx & 1) { - // Odd cluster size. - // - // Mermaid diagram code for the resulting cluster for 11 transactions: - // ```mermaid - // graph BT - // T0["T0: 1/2"];T1["T1: 14/2"];T2["T2: 6/1"];T3["T3: 5/1"];T4["T4: 7/1"]; - // T5["T5: 5/1"];T6["T6: 7/1"];T7["T7: 5/1"];T8["T8: 7/1"];T9["T9: 5/1"]; - // T10["T10: 7/1"]; - // T1-->T0;T1-->T2;T3-->T2;T4-->T3;T4-->T5;T6-->T5;T4-->T7;T8-->T7;T4-->T9;T10-->T9; - // ``` - if (i == 0) { - depgraph.AddTransaction({1, 2}); - } else if (i == 1) { - depgraph.AddTransaction({14, 2}); - depgraph.AddDependencies(SetType::Singleton(0), 1); - } else if (i == 2) { - depgraph.AddTransaction({6, 1}); - depgraph.AddDependencies(SetType::Singleton(2), 1); - } else if (i == 3) { - depgraph.AddTransaction({5, 1}); - depgraph.AddDependencies(SetType::Singleton(2), 3); - } else if ((i & 1) == 0) { - depgraph.AddTransaction({7, 1}); - depgraph.AddDependencies(SetType::Singleton(i - 1), i); - } else { - depgraph.AddTransaction({5, 1}); - depgraph.AddDependencies(SetType::Singleton(i), 4); - } - } else { - // Even cluster size. - // - // Mermaid diagram code for the resulting cluster for 10 transactions: - // ```mermaid - // graph BT - // T0["T0: 1"];T1["T1: 3"];T2["T2: 1"];T3["T3: 4"];T4["T4: 0"];T5["T5: 4"];T6["T6: 0"]; - // T7["T7: 4"];T8["T8: 0"];T9["T9: 4"]; - // T1-->T0;T2-->T0;T3-->T2;T3-->T4;T5-->T4;T3-->T6;T7-->T6;T3-->T8;T9-->T8; - // ``` - if (i == 0) { - depgraph.AddTransaction({1, 1}); - } else if (i == 1) { - depgraph.AddTransaction({3, 1}); - depgraph.AddDependencies(SetType::Singleton(0), 1); - } else if (i == 2) { - depgraph.AddTransaction({1, 1}); - depgraph.AddDependencies(SetType::Singleton(0), 2); - } else if (i & 1) { - depgraph.AddTransaction({4, 1}); - depgraph.AddDependencies(SetType::Singleton(i - 1), i); - } else { - depgraph.AddTransaction({0, 1}); - depgraph.AddDependencies(SetType::Singleton(i), 3); - } - } - } - return depgraph; -} - -/** Benchmark that does search-based candidate finding with a specified number of iterations. - * - * Its goal is measuring how much time every additional search iteration in linearization costs, - * by running with a low and a high count, subtracting the results, and divided by the number - * iterations difference. - */ -template -void BenchLinearizeWorstCase(DepGraphIndex ntx, benchmark::Bench& bench, uint64_t iter_limit) -{ - const auto depgraph = MakeHardGraph(ntx); - uint64_t rng_seed = 0; - bench.run([&] { - SearchCandidateFinder finder(depgraph, rng_seed++); - auto [candidate, iters_performed] = finder.FindCandidateSet(iter_limit, {}); - assert(iters_performed == iter_limit); - }); -} - -/** Benchmark for linearization improvement of a trivial linear graph using just ancestor sort. - * - * Its goal is measuring how much time linearization may take without any search iterations. - * - * If P is the benchmarked per-iteration count (obtained by running BenchLinearizeWorstCase for a - * high and a low iteration count, subtracting them, and dividing by the difference in count), and - * N is the resulting time of BenchLinearizeNoItersWorstCase*, then an invocation of Linearize with - * max_iterations=m should take no more than roughly N+m*P time. This may however be an - * overestimate, as the worst cases do not coincide (the ones that are worst for linearization - * without any search happen to be ones that do not need many search iterations). - * - * This benchmark exercises a worst case for AncestorCandidateFinder, but for which improvement is - * cheap. - */ -template -void BenchLinearizeNoItersWorstCaseAnc(DepGraphIndex ntx, benchmark::Bench& bench) -{ - const auto depgraph = MakeLinearGraph(ntx); - uint64_t rng_seed = 0; - std::vector old_lin(ntx); - for (DepGraphIndex i = 0; i < ntx; ++i) old_lin[i] = i; - bench.run([&] { - Linearize(depgraph, /*max_iterations=*/0, rng_seed++, old_lin); - }); -} - -/** Benchmark for linearization improvement of a trivial wide graph using just ancestor sort. - * - * Its goal is measuring how much time improving a linearization may take without any search - * iterations, similar to the previous function. - * - * This benchmark exercises a worst case for improving an existing linearization, but for which - * AncestorCandidateFinder is cheap. - */ -template -void BenchLinearizeNoItersWorstCaseLIMO(DepGraphIndex ntx, benchmark::Bench& bench) -{ - const auto depgraph = MakeWideGraph(ntx); - uint64_t rng_seed = 0; - std::vector old_lin(ntx); - for (DepGraphIndex i = 0; i < ntx; ++i) old_lin[i] = i; - bench.run([&] { - Linearize(depgraph, /*max_iterations=*/0, rng_seed++, old_lin); - }); -} - template void BenchPostLinearizeWorstCase(DepGraphIndex ntx, benchmark::Bench& bench) { @@ -189,92 +44,52 @@ void BenchPostLinearizeWorstCase(DepGraphIndex ntx, benchmark::Bench& bench) }); } -template -void BenchMergeLinearizationsWorstCase(DepGraphIndex ntx, benchmark::Bench& bench) -{ - DepGraph depgraph; - for (DepGraphIndex i = 0; i < ntx; ++i) { - depgraph.AddTransaction({i, 1}); - if (i) depgraph.AddDependencies(SetType::Singleton(0), i); - } - std::vector lin1; - std::vector lin2; - lin1.push_back(0); - lin2.push_back(0); - for (DepGraphIndex i = 1; i < ntx; ++i) { - lin1.push_back(i); - lin2.push_back(ntx - i); - } - bench.run([&] { - MergeLinearizations(depgraph, lin1, lin2); - }); -} - -template -void BenchLinearizeOptimally(benchmark::Bench& bench, const std::array& serialized) +void BenchLinearizeOptimallyTotal(benchmark::Bench& bench, const std::string& name, const std::vector>& serializeds) { - // Determine how many transactions the serialized cluster has. - DepGraphIndex num_tx{0}; - { + for (const auto& serialized : serializeds) { SpanReader reader{serialized}; - DepGraph> depgraph; + DepGraph> depgraph; reader >> Using(depgraph); - num_tx = depgraph.TxCount(); - assert(num_tx < 128); - } + auto bench_name = strprintf("%s_%utx_%udep", name, depgraph.TxCount(), depgraph.CountDependencies()); - SpanReader reader{serialized}; - auto runner_fn = [&]() noexcept { - DepGraph depgraph; - reader >> Using(depgraph); + // Benchmark the total time to optimal. uint64_t rng_seed = 0; - bench.run([&] { + bench.name(bench_name).run([&] { auto [_lin, optimal, _cost] = Linearize(depgraph, /*max_iterations=*/10000000, rng_seed++); assert(optimal); }); - }; - - if (num_tx <= 32) { - runner_fn.template operator()>(); - } else if (num_tx <= 64) { - runner_fn.template operator()>(); - } else if (num_tx <= 96) { - runner_fn.template operator()>(); - } else if (num_tx <= 128) { - runner_fn.template operator()>(); - } else { - assert(false); } } -} // namespace +void BenchLinearizeOptimallyPerCost(benchmark::Bench& bench, const std::string& name, const std::vector>& serializeds) +{ + for (const auto& serialized : serializeds) { + SpanReader reader{serialized}; + DepGraph> depgraph; + reader >> Using(depgraph); + auto bench_name = strprintf("%s_%utx_%udep", name, depgraph.TxCount(), depgraph.CountDependencies()); -static void Linearize16TxWorstCase20Iters(benchmark::Bench& bench) { BenchLinearizeWorstCase>(16, bench, 20); } -static void Linearize16TxWorstCase120Iters(benchmark::Bench& bench) { BenchLinearizeWorstCase>(16, bench, 120); } -static void Linearize32TxWorstCase5000Iters(benchmark::Bench& bench) { BenchLinearizeWorstCase>(32, bench, 5000); } -static void Linearize32TxWorstCase15000Iters(benchmark::Bench& bench) { BenchLinearizeWorstCase>(32, bench, 15000); } -static void Linearize48TxWorstCase5000Iters(benchmark::Bench& bench) { BenchLinearizeWorstCase>(48, bench, 5000); } -static void Linearize48TxWorstCase15000Iters(benchmark::Bench& bench) { BenchLinearizeWorstCase>(48, bench, 15000); } -static void Linearize64TxWorstCase5000Iters(benchmark::Bench& bench) { BenchLinearizeWorstCase>(64, bench, 5000); } -static void Linearize64TxWorstCase15000Iters(benchmark::Bench& bench) { BenchLinearizeWorstCase>(64, bench, 15000); } -static void Linearize75TxWorstCase5000Iters(benchmark::Bench& bench) { BenchLinearizeWorstCase>(75, bench, 5000); } -static void Linearize75TxWorstCase15000Iters(benchmark::Bench& bench) { BenchLinearizeWorstCase>(75, bench, 15000); } -static void Linearize99TxWorstCase5000Iters(benchmark::Bench& bench) { BenchLinearizeWorstCase>(99, bench, 5000); } -static void Linearize99TxWorstCase15000Iters(benchmark::Bench& bench) { BenchLinearizeWorstCase>(99, bench, 15000); } + // Determine the cost of 100 rng_seeds. + uint64_t total_cost = 0; + for (uint64_t iter = 0; iter < 100; ++iter) { + auto [_lin, optimal, cost] = Linearize(depgraph, /*max_iterations=*/10000000, /*rng_seed=*/iter); + total_cost += cost; + } -static void LinearizeNoIters16TxWorstCaseAnc(benchmark::Bench& bench) { BenchLinearizeNoItersWorstCaseAnc>(16, bench); } -static void LinearizeNoIters32TxWorstCaseAnc(benchmark::Bench& bench) { BenchLinearizeNoItersWorstCaseAnc>(32, bench); } -static void LinearizeNoIters48TxWorstCaseAnc(benchmark::Bench& bench) { BenchLinearizeNoItersWorstCaseAnc>(48, bench); } -static void LinearizeNoIters64TxWorstCaseAnc(benchmark::Bench& bench) { BenchLinearizeNoItersWorstCaseAnc>(64, bench); } -static void LinearizeNoIters75TxWorstCaseAnc(benchmark::Bench& bench) { BenchLinearizeNoItersWorstCaseAnc>(75, bench); } -static void LinearizeNoIters99TxWorstCaseAnc(benchmark::Bench& bench) { BenchLinearizeNoItersWorstCaseAnc>(99, bench); } + // Benchmark the time per cost. + bench.name(bench_name).unit("cost").batch(total_cost).run([&] { + uint64_t recompute_cost = 0; + for (uint64_t iter = 0; iter < 100; ++iter) { + auto [_lin, optimal, cost] = Linearize(depgraph, /*max_iterations=*/10000000, /*rng_seed=*/iter); + assert(optimal); + recompute_cost += cost; + } + assert(total_cost == recompute_cost); + }); + } +} -static void LinearizeNoIters16TxWorstCaseLIMO(benchmark::Bench& bench) { BenchLinearizeNoItersWorstCaseLIMO>(16, bench); } -static void LinearizeNoIters32TxWorstCaseLIMO(benchmark::Bench& bench) { BenchLinearizeNoItersWorstCaseLIMO>(32, bench); } -static void LinearizeNoIters48TxWorstCaseLIMO(benchmark::Bench& bench) { BenchLinearizeNoItersWorstCaseLIMO>(48, bench); } -static void LinearizeNoIters64TxWorstCaseLIMO(benchmark::Bench& bench) { BenchLinearizeNoItersWorstCaseLIMO>(64, bench); } -static void LinearizeNoIters75TxWorstCaseLIMO(benchmark::Bench& bench) { BenchLinearizeNoItersWorstCaseLIMO>(75, bench); } -static void LinearizeNoIters99TxWorstCaseLIMO(benchmark::Bench& bench) { BenchLinearizeNoItersWorstCaseLIMO>(99, bench); } +} // namespace static void PostLinearize16TxWorstCase(benchmark::Bench& bench) { BenchPostLinearizeWorstCase>(16, bench); } static void PostLinearize32TxWorstCase(benchmark::Bench& bench) { BenchPostLinearizeWorstCase>(32, bench); } @@ -283,105 +98,57 @@ static void PostLinearize64TxWorstCase(benchmark::Bench& bench) { BenchPostLinea static void PostLinearize75TxWorstCase(benchmark::Bench& bench) { BenchPostLinearizeWorstCase>(75, bench); } static void PostLinearize99TxWorstCase(benchmark::Bench& bench) { BenchPostLinearizeWorstCase>(99, bench); } -static void MergeLinearizations16TxWorstCase(benchmark::Bench& bench) { BenchMergeLinearizationsWorstCase>(16, bench); } -static void MergeLinearizations32TxWorstCase(benchmark::Bench& bench) { BenchMergeLinearizationsWorstCase>(32, bench); } -static void MergeLinearizations48TxWorstCase(benchmark::Bench& bench) { BenchMergeLinearizationsWorstCase>(48, bench); } -static void MergeLinearizations64TxWorstCase(benchmark::Bench& bench) { BenchMergeLinearizationsWorstCase>(64, bench); } -static void MergeLinearizations75TxWorstCase(benchmark::Bench& bench) { BenchMergeLinearizationsWorstCase>(75, bench); } -static void MergeLinearizations99TxWorstCase(benchmark::Bench& bench) { BenchMergeLinearizationsWorstCase>(99, bench); } - -// The following example clusters were constructed by replaying historical mempool activity, and -// selecting for ones that take many iterations (after the introduction of some but not all -// linearization algorithm optimizations). - -/* 2023-05-05T23:12:21Z 71, 521780, 543141,*/ -static constexpr auto BENCH_EXAMPLE_00 = "801081a5360092239efc6201810982ab58029b6b98c86803800eed7804800ecb7e058f2f878778068030d43407853e81902a08962a81d176098010b6620a8010b2280b8010da3a0c9f069da9580d800db11e0e9d719ad37a0f967897ed5210990e99fc0e11812c81982012804685823e0f0a893982b6040a10804682c146110a6e80db5c120a8010819806130a8079858f0c140a8054829a120c12803483a1760c116f81843c0d11718189000e11800d81ac2c0f11800d81e50e10117181c77c1111822e87f2601012815983d17211127180f2121212811584a21e1312800e80d1781412813c83e81815126f80ef5016126f80ff6c16126f80f66017126e80fd541812800d81942a1912800e80dd781a12800d81f96c1b12805282e7581b127180fd721c1271a918230b805fc11a220d8118a15a2d036f80e5002011817684d8241e346f80e1181c37805082fc04260024800d81f8621734803382b354270b12805182ca2e162f800e80d52e0d32803dc360201b850e818c400b318c49808a5a290210805181d65823142a800d81a34e0850800e81fb3c0851886994fc0a280b00082c805482d208032e28805e83ba380059801081cd4a0159811884f770002e0015e17280e49024300a0000000000000031803dcb48014200"_hex_u8; -/* 2023-12-06T09:30:01Z 81, 141675, 647053,*/ -static constexpr auto BENCH_EXAMPLE_01 = "b348f1fc4000f365818a9e2c01b44cf7ca0002b004f0b02003b33ef8ae3004b334f9e87005800d81c85e06b368fae26007b05ef2e14208be1a8093a50409b15cf5ee500a802c80a1420b802dea440c802ce50a0d802cdc320e802cd7220f802dd72210805380f74a118174f370126e96b32812127182c4701312817389d26414128035848c221512800e82bf3816126f81e4341712801082b228181280518af57418128040859a0019127182d0401a12803e858b641b127182c4421c126f82b3481d12811486b6301e12821d89e7281f126e8a8b421f127182d6642012806284c12021126e81d34822126e86a76222126e86d8102212805187b6542312800d82fc002412803d848e0e2512801082d27a26126e8589642612800e83a9602712800e83bd0028126e81ef1a29116e858d7228126f82db5e2912801083843c2a127181c93c2b126e85d0162b127181c5622c126e84f8262c12800f8392202d12800e82b66c2e126e81d0082f12803282d50430126e84f9003012805f84be6c3112846e88df0e2b12804080d44c340a8b31898808350a800ed760350b801083a1182b517182817e2a51800e82b6582951803583cb52420030806284cb6c204f7181d300204f82688ce0303e001d800e82bb200f488010808a182822a3289cd63041000a6fcd100a408a7caaa7024800002f803584e0741e27288f3386dd783b001000802683f27e004b8c44bcd0763f0000000000000000000100000e00"_hex_u8; -/* 2023-04-04T00:26:50Z 90, 99930, 529375,*/ -static constexpr auto BENCH_EXAMPLE_02 = "815b80b61e00800da63001cd378da70e028010991a03800e9d3e0480109708058010991a068010973a07da738fa72408de7491831009b35b88f0080a9d4485de180b71974e0c71974e0d80108e500eb27988a75a0f719632108061a56c11801087761280108a1413807893441480538c1415a606828806168010893e1780548c40188e4b80bb2c196eab3e1718805ed60e18188051c97a19188010cf781a1871b11e1b1871c5281c1880508080581d186e80b13c1e188035cf421f18805fe0482018804caa661f198035a9001f156e80cb701d1871a2281e1871ad281f18817380a16020186f98642118805ee04821198010b6702219800ea12623196eb67024198035808b0025196fa65c26198054ba1c2719807680bf7c28198053cd782919803d80b80429198051db5a2a198040d3742b19976584bb1c28196efc1c281971b21a29198052bc762a1971a2502b196eb73c2c19976381ab0c2a18806290543409862081c3423b00336fbc70224d80109e7c1c52805ebd5c1942800eb57016468034ba423405158118da28350416927480f4743000159f6a81c9462e00188051ec5e380e00800e9e420775800d9e26007c906c82f754251d0025870480f12c14280023800d9e26027e9e1385ed08102900001a804fac7a018001719856028001800da87e0180039b1a868b60064102246e9f42018005800da87e028005850d81d600026d862381a2200e0008230015831480a5480342000524803eeb32006e873582a4700a0100351300"_hex_u8; -/* 2023-05-08T15:51:59Z 87, 76869, 505222,*/ -static constexpr auto BENCH_EXAMPLE_03 = "c040b9e15a00b10eac842601805f85931802c104bae17403ae50aaa336049d76a9bf7005c55bbeab6606ae2aa9c72c07805e81992e08af7dab817a096e80a7e4520909803e92bd780a097185c76c0b096e98e7380b09850bb9953c0c09803389f6260d096f859d620e09803f88d3000f0971829c6e1009837690f6481109806285931811097181f56814076ea09b74120980408eb73213096f87853214096f86e2701509803f8c860016098a6fe6c3721709814f92a204180980628a8a441909803285df681a0980348498661b096e8290781c096e978e081c097187da1a1d097186c05c1e097185893c1f09805f8ad9002009800d84e74e21097183a67a22097182e23423097184b53a23096ea393062309840faddd46240980618eb732250980548bee6a2609807986883c2709718298402809815388b6582909805384ec742a097181b9142b096e97b5262b096e85e14e2c0980518abb5c2d09805489e75a2e09803187e3382f097180eb1c34046f87c34a2f098309a5c54430097186911831098054899c083209801083bc1033097081e02a3409805f848f0c35096e80d4343a057180c37040006f80a22438097180a0503f03816f8381444003803f80ef003f05800580a4283f066ef72845016efb91663e09923d808d8216470041803584837c46012f9247dc86684501268267a09610450222862184db68440712803585ea40440113835d97887805800b8723c7a40a4b00022f81529ae2143c0c1f80548b8f381b311980408e955c055e802589dc10037e801083b54602658010848130006700"_hex_u8; -/* 2023-05-01T19:32:10Z 35, 55747, 504128,*/ -static constexpr auto BENCH_EXAMPLE_04 = "801af95c00801af72801801af95c02873e85f2180202873e85f2180202873e85f21802028018fb2802068018fb2803068018fb2804068018fb2805068018fb2806068018fb2807068018fb2808068018fb2809068018fb280a068018fb280a058018fb280b058018fb280c058018fb280d058018fb280e058018fb280f058018fb2810058018fb2811058018fb2812058018fb2813058018fb2814058018fb2815058018fb2815048018fb2816048018fb2817048018fb2818048018fb2819048018fb281a048018fb281b04810d80d9481f00000100"_hex_u8; -/* 2023-02-27T17:06:38Z 60, 55680, 502749,*/ -static constexpr auto BENCH_EXAMPLE_05 = "b5108ab56600b26d89f85601b07383b01602b22683c96003b34a83d82e04b12f83b53a05b20e83c75a066e80840a06068040be0007066fb10608066fb2120906800eba320a06842b80b05a0a066eff420b067199300b068124c3140c0680618085180d066faa1c0e068010b4440f068051af541006800da1781106857881946812066eee1613068052b31014068324808d361506806180885c150671b03216066ef11017068052b63218066ef3521806803f80865419066e93441a068035a13e1b0680628085181c06806ec4481d068117e72c1e06719c721f068077c42420068159808d1821066eef0c21058010b90022056f9908230571993024058010b00a25058010b00a260580608087402705803fc10027068032b42828068051b6322906800db11e212a8324808d361933803ff400192f826381a7141a2f8032ac08152a800db54c044e8323808d3630010002018158d84000042d821cea12002807853580d462002d01891181d022002e00"_hex_u8; -/* 2023-04-20T22:25:49Z 99, 49100, 578622,*/ -static constexpr auto BENCH_EXAMPLE_06 = "bf3c87c14c008010955a01b21d85e07002800d946c036e8e3404b77f86c26605b33c85f55e06bd06879852078010970a08bd4b87cf00098123a7720ab2158687680b8054d4440b0a8062fa4c0c0a71ac400d0a80628081540e0a8010a2580f0a8054b676100a8032b85c110a6e9a40120a6e809012130a817f80c31e140a8175808674150a719d46160a8172d86415098033c1481609800da4181709800ada2e1809803dc85219098034b4041a096ef5501b098052d67c1c098051d3281d09800ebc4a1e098175808c641f098061c55020098078c85021096e8081141f0b6faf1e200b8061da68210b8062f000220b800ebc20230b8035d058240b8053de32250b8050b610250b6fad32260b803dc276270b803d80a610280b6ef812290b8052b6322a0b800eb57e2b0b8052bd062c0b719e522d0b71a3762e0b8010bb1e2f0b80109a78310a80109962320a8051a60c330a6f9f3e320b6e808b24330b719e40340b8117cc50350b803d80971a360b8051b930370b6f9e0a380b719b10390b8052a6003a0b6e808c76390a7195603a0a6f935c3b0a8054a31a3c0a803ce30c3b0b803fa3003c0b800dbe2a3d0b8f3480a84244058005851a44069d1bf824400b83098f284507719c723d4f6f9c1c3449719c722f4f6eb23c304f8061c5502e528061da682b4e8118bb724e022a8054b35028476e941c1d51815be02c4f01148557808e3a4f070e8104af464e001180329d364e010d805f9f6a421b9c3387aa744c0d4d71ac400b800881748098444710338173809b780b80008054d444292c12821dc040550403078b4682b4664517003f00"_hex_u8; -/* 2023-06-05T19:56:12Z 52, 44896, 540514,*/ -static constexpr auto BENCH_EXAMPLE_07 = "b317998a4000b40098d53e01b45b99814802b7289b940003b3699a9d1204b6619a807a05814682cb78050571d854060571d8540705800e808d7a0805803480c06a09056e8189280a056ffd060b05800d80ea7a0c05803c80b80c0c03803e80d86e0d036ed2280e03811581804a0f036fd34e1003805380eb6811036e81f60e12038010ec101204805f80e83a13048033809534140471e00a15048010f95816046e81fa301704805180a74c1705800d808f1018056fd55c1905800e8091481a056e80a76e1b05805f80e2741c0571809b021c05826382c8401d0571df201e05800e809d2c1f05850083e87c1f05811580af68200571f20a21056ff9042205803e80df1e23056e81956c24056e9f542604805180e83829000e800e8080621325803380b0402a020d6ef8100e2c8c4889a96a2c000f803580ce4c2c000b6e9f54062a803480c96406260500"_hex_u8; -/* 2023-12-05T23:48:44Z 69, 44283, 586734,*/ -static constexpr auto BENCH_EXAMPLE_08 = "83728ce80000b90befca1001806083b24002b40de6da3203b545e9c35c04b34beede3005b068e8883006d41c80b1e14c07b337e7841208b26beadb2e096e83892e090980518487380a096e82815c0a096e81ce3c0b097181db200c097181d4020d09810084ed600e096e96b0100f0971819a0210086e93da2e0f09803583ee5e1009803583c66c1109800d82bb6e1209800d81d56a1309803c82e622140971819f521509803d84a55c15057181d6161605806283ac5217056e949c5a18056e89e8641806815889e23419067181de321a066e8af2641a076e82a70a1b07803583f2081c076f81e76e1d076e81d33e1e07800d83b8761e086e82a5541f087181de302008805f84ad0021086e81c74022086e81bd3e23086e9288182408806184b3102409803283816025096e91ed662609830a88e70827096e81d14a27097181ce6028096e8cf03829097181883832016f81835c3103806181e0103203804180b8103204863584fe183304800de66434046e9e4c34056e81d6742f429213c0eb602e3d6483b06c283a6e81d73c263d6e82f9581831805485ab360e37805080c62609398b3189880838010603916db1f3583a03000110873199f8623c000000011100"_hex_u8; -/* 2023-04-14T19:36:52Z 77, 20418, 501117,*/ -static constexpr auto BENCH_EXAMPLE_09 = "bf2989d00400815bca5c01af1e86f97602800d9d6c03800d8a3404b47988866e05b36287f92e0680109f68078010991a08805ecf1208076e80933e09078062d01c0a078054b6760b078053b6760c076f9c1c0d078054b6760e0771af260f0771b17e10078032f57011078035d56812078054e1581307886b83dc301407817480d13013068005a6001406803d80821a15066ef3201606800ea2181706800da628180671ab1219068054db0c1a06719b001b06815b80a11c1c068050b9301d066fac2a1e068033ab481f06719b1020068035ab721e07803dc2761f0771ae3c20078040f60e210771ce282207800ea4322307882a81a66024078035ad4625076efe7e26078162808e1827078118bb7228076eac7428088010bf58290871a04c2a0871bc722b086fa8382c08803d80a0142d088035d6282e088051c30c2f086efc623008800d9f6231086f986432088117bb7237028010a63034068010c84e2740800ea64c2237832c80933e1f3b830880c454390208813c80955c3905068032c73611348010a03c093c837a808a101b278050ac34093a8051ac34291b8f3b8187401d28881a82cb3a3a0a37977b86d20843000028996686a7083f030f8078d3761b27106e995a08499070839b5a1131000b00"_hex_u8; -/* 2023-11-07T17:59:35Z 48, 4792, 498995,*/ -static constexpr auto BENCH_EXAMPLE_10 = "875f89aa1000b51ec09d7201c55cc7a72e02a11aa1fb3203b233a7f95204800ef56205b33ea9d13006803e80b26e07d90ec9dd4008b45eabbe6c09806080ca000a815984e8680a0a6f80925e0a0a803f80e1660c09937c94b7420d086e82f5640a086e80997e0b086f808d320c08800580a5640d086f8089100e08804080c9060f088115819a1c10086e82961a0f0a805f81bc0a100a6ff826110a6ef53e120a807584c60c110a6e818f32120a803c81c246130a805481d508140a8159838410150a7180a55c160a6f80821c170a6fe6101c066fe6101d06805080f854190a6e81b27c1a0a8155819c701e06805180ae0c21046e8b9a222501805180f53422001680f26880f8a62a220116803580da582007058153838e6e21000c800d80a712033a807681ae1c23000308834a82d36023020205815981e03a051a08001700"_hex_u8; -/* 2023-11-16T10:47:08Z 77, 473962, 486863,*/ -static constexpr auto BENCH_EXAMPLE_11 = "801980c06000801980c06001801980c06002801980c06003801980c06004801980c06005801980c06006801980c06007801980c06008801980c06009801980c0600a801980c0600b801980c0600c801980c0600d801980c0600e801980c0600f801980c060108019d12c11800f80b1601111800f80b1601111801080b1601111800f80b160100e800f80b160100f801980c060110f800f80b160140d801180b1601111801180b160100d801180b160120c801180b1600f10801180b1600f11801980c0601011800f80b160140e800f80b160110f801980c060170a801180b1601210801980c060140f800f80b1601311801980c0602005801180b1601f07800f80b1601b0c800fca7c1611812081f9601638812081f9601637812081fb001636801080b160142f801980c0600e2a801080b1600f2a801180b1600d25801980c0600e25800f80b1600d27801980c0600e27801980c0600d27801180b1600e26812080b1500c27812081f960201025812081f960200f27812081fc201d101c812081fc201d101d812081fc201d0f1f812081fc201d0f20812081f9601b1016800f80b1600a35800f80b1600a36800f80b1600e32801080b160122f812081f960280040812081fc20121d1b812081f960112713812081f960160d37812081fc20140d2b812081f960130d2d812081fc20130c2c812081fb001b0157812081fb001a0245812081fc20140030812081fc20092747812081fb000b152500"_hex_u8; -/* 2023-10-06T20:44:09Z 40, 341438, 341438,*/ -static constexpr auto BENCH_EXAMPLE_12 = "80318f4c0080318f4c0180318f4c0280318f4c0380318f4c0480318f4c0580318f4c0680318f4c078033a57807078033a57807078033a57807078033a57807078033a57807078033a57807078033a57807078033a578070780318f4c0e0180318f4c0d0380318f4c0c0580318f4c0b078033a57803128033a57803128033a57803128033a578031280318f4c0412810b9c28140300810c9c281303028033a57802188033a57802188033a5780218810c9c280b01108033a578001c810c9c2807050f8033a578001b810c98040700158033a578001c810c98040301158033a5780019806ca1240101118033a578001300"_hex_u8; -/* 2023-11-15T21:40:46Z 96, 23608, 138286,*/ -static constexpr auto BENCH_EXAMPLE_13 = "8060829f4000b157bab07a01b27cc2b16802b22fbce54603826480a95804803da81a05bc7bcac93806800de55207800daf0608805bc71809805bc7180a800d9d4a0b805bbc700c8152d7180d805bb9380e850a8886260f800d80d33410bf38d3d55011b41dc4eb6012bd70d2ce2e138d3596af7812137180cd501313805e81f7281413718092001513803d81f90016136e8b916c1713801081861a17106e80cd2a18106f80cc3c19106e80cf161911800d80fe781b107180d87c1c106e80fb081d10803e8286701d11800d81c4781f10804082a6002010801081912e21107180ff0021116e81da4a2310850b8b864023116e89db3224116e84ff7e2610897c95993427106f80bb1a240b803581c272250b8032828c10260b6e80d42a270b804082b35a280b800d80fe3e290b805cc0282312821d8697022b0b6e8add562c0b805281c8063007811883f1082313800d80fe3e24137180c9142513800d8380102613803382c00e2713805eb32228136e8494542913800e8186742913806082b74c2a1380528285782b13800d818f7a2c136e84a5562d1380508286702e136f80a46e3e04803f8191364102805481ad4c3d076e809a5a3e077180fe4032136e838b7233138c4790cf384106853584ab624206805b80932a4801806280966c48028168ef04400b7181bd524903806282db5c375b9316acbf703a599c68c5a454385c6e81d63e364a6f80ff64334e817485a6784f023171819536234e800d81826e1e498053829a12420018834c87cb14291d2e840e8bc94c1d2825800d81b7220368811783fe0e271f1f811783e758380f001ecd55809edf6e56000000003a815984ba76008010d54d80aebb4e2c22000000000000002c807682f150007a00"_hex_u8; -/* 2023-12-06T09:18:20Z 93, 68130, 122830,*/ -static constexpr auto BENCH_EXAMPLE_14 = "b26beadb2e00800d80ca0a01d41c80b1e14c02b068e8883003800d81af1604b34beede30056e80b14006b151f5d46c07b93e8085b02608b30cf98b1009b14ef6b3040ab176f6ab480bb7078082b8640c800d81c6460d802c80a8080e802c80a8080f802c80a14210802ce50a11802cd722127181ce6012126e81d14a13126e9b8b00141282428dd42c15128051828408150e6e81bd3e150f805f84ad00160f7181de30170f6e81c740180f800d83b876190f6e82a5541a0f6e81d33e1a106e82a70a1b106f81e76e1c10803583f2081d106e82d9401e106e96e4441f107181de321e12815889e2341f127182d60c20126e979d4e21126e8282262410800d82972c25106f838a5822126f82842a23127182d24a2412803e84bc2a2512800d83c81a26126e84f8142712805085a22c27126e889e6a2812801083aa50281280348598102912801082d5522a126e85865c2b127182c7602b1282468c82042c126e84972c2d12805485d93a2d12801083c7322e12815386e1582f126e84fb0c30126f82eb6c3011813a85b47a3111803f869f5c3211805181ed30370d6e84bf0a3411804180e1383809815883aa183a08815a8392203e05807681f140380c6e9e4c4005805485ab363255805183856030406e82f9582c45805185c1001b4f82418df1001a4e803283c50e430026800d83a6201a4b836886be3044010b8b318988084c0101803183a6120776800d828a1e087682338ae050301c33873199f8624d010032813986bc663c1034800d83a5220a6f800d82be52048000805183e364084907800d83cc4a018005815987b41e1832000017884b9dce72035035803284c11e00800885769d9538192f0000000002001000"_hex_u8; -/* 2023-12-14T02:02:29Z 55, 247754, 247754,*/ -static constexpr auto BENCH_EXAMPLE_15 = "801980c06000801980c06001801980c06002801980c06003801980c06004801980c06005801980c06006801980c06007801980c06008801980c06009801980c0600a801980c0600b801980c0600c801980c0600d801980c0600e801180b1600e0e801180b1600e0e801180b1600e0e801180b1600e0e801180b1600e0e801180b1600e0e801180b1600d07801180b1600f06801180b1600c0a801180b1600f08801180b1600c0c801180b1600c0d801180b1600c0e801180b160100b801180b1601309812081fc200e2a812081fc200e29812081fc200e28812081fc200e0e18812081fc200e0e17801980c060042e812081fc200e0d07812081fc200e0d08812081fc200e0c0a812081fc200e0d0a801980c060081e812081fc200f0c0c812081fc200f0c0d812081fc200f0c0e801180b160083a801180b1600426801980c0600b20801980c0600a22812081fc200f0b30801180b160022b801180b160022b812081fc20062422812081fc2006220b812081fc200c0a1e812081fc2012041a00"_hex_u8; -/* 2023-12-14T15:17:20Z 76, 102600, 103935,*/ -static constexpr auto BENCH_EXAMPLE_16 = "801980c06000801980c06001801980c06002801980c06003801980c06004801180b1600404801180b1600404801180b1600404801980c0600504801980c0600802801980c0600803801180b1600704801980c0600804801280b1600804812081fc200810812081fc20080f812081fc20080e801180b160080c800f80b160080d801980c060090d801180b160090e801980c0600a0e812181fc200a0c801180b1600a0d812181fd400a0c801980c0600a1c801980c0600916801180b1600719801180b160061b801980c0600d15801980c0600717812081fc200718801980c0600716801180b160072d801180b1600722801180b1600525801980c060091b801980c060071e801080b160071f801280b160061d812081fc20063a812181f960160815801280b1600525801980c0600625801180b1600626801980c0600726801980c0600536801180b160032b801980c060042b801280b160032d801980c060033e801180b160043e812181fc20100c27801080b160042f801980c0600342801180b1600442812081fc20150d25800f80b1600245812081fd40120619812081fc20040243812081fc20120c2c812081fd40120a1d812181fb00100623812081fc20030347812081fc20072126801980c0600236812081fc20040d2b812081fc20120328801980c0600237801180b1600337812081fc20052230801180b1600239812081fc2008242c812081fd4005112d812081fb00070b32812081f96011034700"_hex_u8; -/* 2023-12-15T07:12:29Z 98, 112693, 112730,*/ -static constexpr auto BENCH_EXAMPLE_17 = "801980c06000801980c06001801980c06002801980c06003801980c06004801980c06005801980c06006801180b1600606801180b1600606801180b1600606801180b1600606801280b1600606801180b1600606801180b1600606801980c0600d00801980c0600b03801980c0600b04801980c0600f01812081fc200a16812081fc200a15812081fc200a14812081fc200a13812081fd400a12812181fc200a11812181fc200a0f801180b1600a10801180b1600a10801980c0600a10801180b1600b10801180b1600b10801980c0600621801980c0600915801980c060041b801180b160051b801980c0600f12801980c0600f13801980c0600d15801980c0600c17801980c060072e800f80b160082e812181fc200d150e801980c0600922801180b1600923801980c0600823801180b1600623801180b1600a20801180b1600e1c801180b1600b20801180b1600b21801980c0600a3e800f80b1600b3e801980c0600931801180b1600a31812181fc20140325801180b1600a30801180b160054c801180b160043b801980c0600336812181fc200253812081f960090944812081fc2007003c801980c0600339801180b1600433801980c0600453801980c0600340801980c060033d801080b160043d812081f960070854801980c060045a801180b160055a801180b1600545801980c0600643801980c0600641801280b1600739801180b1600562812081fc20121f27812181fc20210137812181fc2016112f801980c0600259801980c0600156812181fc20053a31801180b160025c801180b1600257801980c0600357812081fc200d2d1e812181fc20102444812181fc20035a801180b160035b801980c0600751812181fc2007392a812181fc20025f801980c060045e801180b1600350812081fc20070f6f801180b1600263812181fc201b1322812181fc2011283b812081fc2002442100"_hex_u8; -/* 2023-12-16T02:25:33Z 99, 112399, 112399,*/ -static constexpr auto BENCH_EXAMPLE_18 = "801980c06000801980c06001801980c06002801980c06003801980c06004801980c06005801980c06006801980c06007801180b16008801180b16009801180b1600a801180b1600a0a801180b1600a0a801180b1600a0a801180b1600a0a801980c0600d06801180b1600b09801980c0601005801180b1600c0a801980c0600d0a801980c0601106801180b1600e0a801980c0601207801980c0601207801180b160100a812081e668100a812081e668100a812081e668100a801980c0601407801980c0601606812081fc201226812081fc201225812081fc201224812081fc201223801180b1600e21801980c0600b1e801180b1600c1e801180b1601316801980c060091b801980c0601312801980c0600a1c801180b160190e801180b1601315801180b1600e1b801180b1601713801180b1600f1c801980c0600d34801980c0600d30801980c060102e801980c060122d801980c0600b2a801980c0600b2a801980c0600b2b801180b1601122801180b1600e26801180b1601025801180b1600f26812081fc20280032812081fc20270034812081fc20250034801180b1600d4b801980c0600d457a809a000d46801980c0601044801980c0600e46801180b1600f43801180b160123f801180b160123e801180b1601130801180b1601131801180b1601131812081fc20230a36801980c0600a5a801180b1600a5b801980c0600a5b801180b1600b5b801980c0600b5a801180b1600f57801180b1600d3f801980c0600669801980c0600568801980c0600466801180b1600945801180b1600649801180b1600945812081fc2018234b812081fc20142534812081fc20142532812081fc20142530801180b160074d801180b1600a4b801180b1600a4a812081fc20221662812081fc200c0472812081fc20072e42812081fc20062c23812081fc20100572812081fc200f036c812081fc2001345100"_hex_u8; -/* 2023-03-31T19:24:02Z 78, 90393, 152832,*/ -static constexpr auto BENCH_EXAMPLE_19 = "800dd042008028b13c018028b13c028028b13c038029b13c048029b13c058029b13c0680299948078029b13c088029b13c09802899480a802899480b8028b13c0c80299e700d802899480e802999480f8029b13c10802999481180299948128028b13c138029b13c1480289e701580289948168028b13c1780289948188028994819802899481a802999481b802999481c802899481d802999481e8028b13c1f8029b13c20802999482180299948228028b13c2380298c242480289948258029b13c2680288c242780298c242880299e70298f5a80ea762a824780aa00292a82038090402429813fcf00152a8203809040142a813ff700112982038090402d002d813ff70028002c8203809040270024824780aa00270025820380904025002882038090401e022a82038090401d042782038090401c01298203809040190029813ff700170028813ff700140128807b9258120128841280f6402c01002e82038090402b00062b820380904027000031813ff70011192d82038090401d000129851981a9403a0000003b82038090400c182e813ff7000b0f2982038090401314141b807b925805192b84568190001121000334807bdd400149824780aa00001f2a813ff700003d0b8203809040050d1915807bdd4001498728828f400b010004050501000a050c851981a9400104050b061a0400"_hex_u8; - -static void LinearizeOptimallyExample00(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_00); } -static void LinearizeOptimallyExample01(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_01); } -static void LinearizeOptimallyExample02(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_02); } -static void LinearizeOptimallyExample03(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_03); } -static void LinearizeOptimallyExample04(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_04); } -static void LinearizeOptimallyExample05(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_05); } -static void LinearizeOptimallyExample06(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_06); } -static void LinearizeOptimallyExample07(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_07); } -static void LinearizeOptimallyExample08(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_08); } -static void LinearizeOptimallyExample09(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_09); } -static void LinearizeOptimallyExample10(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_10); } -static void LinearizeOptimallyExample11(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_11); } -static void LinearizeOptimallyExample12(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_12); } -static void LinearizeOptimallyExample13(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_13); } -static void LinearizeOptimallyExample14(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_14); } -static void LinearizeOptimallyExample15(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_15); } -static void LinearizeOptimallyExample16(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_16); } -static void LinearizeOptimallyExample17(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_17); } -static void LinearizeOptimallyExample18(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_18); } -static void LinearizeOptimallyExample19(benchmark::Bench& bench) { BenchLinearizeOptimally(bench, BENCH_EXAMPLE_19); } - -BENCHMARK(Linearize16TxWorstCase20Iters, benchmark::PriorityLevel::HIGH); -BENCHMARK(Linearize16TxWorstCase120Iters, benchmark::PriorityLevel::HIGH); -BENCHMARK(Linearize32TxWorstCase5000Iters, benchmark::PriorityLevel::HIGH); -BENCHMARK(Linearize32TxWorstCase15000Iters, benchmark::PriorityLevel::HIGH); -BENCHMARK(Linearize48TxWorstCase5000Iters, benchmark::PriorityLevel::HIGH); -BENCHMARK(Linearize48TxWorstCase15000Iters, benchmark::PriorityLevel::HIGH); -BENCHMARK(Linearize64TxWorstCase5000Iters, benchmark::PriorityLevel::HIGH); -BENCHMARK(Linearize64TxWorstCase15000Iters, benchmark::PriorityLevel::HIGH); -BENCHMARK(Linearize75TxWorstCase5000Iters, benchmark::PriorityLevel::HIGH); -BENCHMARK(Linearize75TxWorstCase15000Iters, benchmark::PriorityLevel::HIGH); -BENCHMARK(Linearize99TxWorstCase5000Iters, benchmark::PriorityLevel::HIGH); -BENCHMARK(Linearize99TxWorstCase15000Iters, benchmark::PriorityLevel::HIGH); - -BENCHMARK(LinearizeNoIters16TxWorstCaseAnc, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeNoIters32TxWorstCaseAnc, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeNoIters48TxWorstCaseAnc, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeNoIters64TxWorstCaseAnc, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeNoIters75TxWorstCaseAnc, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeNoIters99TxWorstCaseAnc, benchmark::PriorityLevel::HIGH); +// Constructed from replayed historical mempool activity, selecting for clusters that are slow +// to linearize from scratch, with increasing number of transactions (9 to 63). +static const std::vector> CLUSTERS_HISTORICAL = { + "8540e93a008331c66a018331c66a028331c66a038331c66a048331c66a058331c66a068f1b84a1060000000000000007995e888c04010000000000000000"_hex_v_u8, + "8e4886a46000835c819a100000835d819c000100835f819c000200837581a7200300835f819c000400835c819a1005008360819c000600836e81a3400700835f819c0008009c728d813000000000000000000000854e88df0600008e48a9c5700100835f8bfd40000183608bfd40010100"_hex_v_u8, + "836880bf4000834c80b6600000836880bf400100834c80b6600001836880bf400101834c80b6600002836880bf400102834c80b6600003836880bf400103834c80b6600004836880bf400104834c80b6600005836880bf400105836880bf400006834c80b6600106836880bf400106834c80b6600206836880bf400107834c80b6600207823c80bf400108834c80b660020800"_hex_v_u8, + "81b0708db03800ef7a84a6700180c57b87c87802f24f83fc7e0381a3688ce20a04cb0d82a27205b40481887e068331965207d84384a07a0880850887b31609d57a83b62a09098865c82e0707c84083a736060009932d8098240a00058c1edf48070503f55a85fc560803058b6ddf660e0002e67d858d68090107921a81a1560d0302857cb32206148235986406149a5680e67c0b000106854cc12001118578e228001281cf6499b350120000000000108578e22801128578e228001300"_hex_v_u8, + "80df2a87e05c00f62883d34801f23983c02c02808e0784ca280380c35b86d64c0480956584f1080580a91b85d20c06808c4b84c27c0780b473868c4408f54983cf7c0980aa5385d9380a80b00285f4140b80804f8487100c8099308582700d80b3138683640efe1183fa640fa734849e28000000000000000000000000000000000fc82788ce48010000000000000000000000000000000fa92b84be300200000000000000000000000000000000ab3b84e1460300000000000000000000000000000000833dc93c0102833dc93c02028331c14402038540e12603038431cc3405028335c50e030a8331c7760506930880af020307833dc07605068331be0205068335be3a05078d09fb76030d842dcb6e030d00"_hex_v_u8, + "8368903600836890360183689036028368903603836890360483689036058368903606836890360783689036088368903609836890360a836890360b836890360c836890361b836890360e836890360f83689036228368903611836890361283689036138359900a13158359900a13158359900a13158359900a13158359900a13158359900a13158359900a13158359900a13158359900a13158359900a13158359900a13158359900a13158359900a12148359900a12148359900a11138359900a11138359900a11138359900a1113a42281a91012000000000000000000000000000000000000002600"_hex_v_u8, + "83689220008734a05001836892200283689220038368922004854e99400583689220068368922007836892200406836892200306836892200207854e994009000983689220030c854e9940080107836892200309854e99400b0101836892200416854e9940070209854e994005060c854e9940020c0e854e9940030804854e9940030706891aa770070207854e9940040413854e994006020d854e99400311836892200310836892200217836892200113854e994003070d854e9940020410854e994002020d8734a05006010b854e9940050612854e994002128734a0500014854e9940050015836892200114854e994001090e854e99400507148734a050020b058734a0500210836892200222854e994004090e854e9940041200"_hex_v_u8, + "db3284df6200e45386c550018235a906028235a906038236a906048235a906058600da0005058578d94c06058236a104070582429e10080582429b040905831d982e0a05854181e1040b058f1880f2240c058235a5040d058236a9060e05823581c3080f058235a90610058235a9061105857c80804012058235ab0613058235a90613058236a90614058236990215058474ca6e16058470ca6e17058a5480df0418058470ca6e19058316a43e1b04847c8088701b0586088086481d048236af061d058235a9061e058235a9061f058235b10620058236b10621058236b10622058236b1062305847080870224058546b34425058234b30626058235838f3227058242a504212a8241a9061b2d824181be76192d875282ad702b00168242ab061929845085af4c2d000f824181e448102b860480885c25168d0884c76e1b100000000100"_hex_v_u8, + "8514fd1a00851480d02801903183803e028368e154038368e154048368e63c058368e63c068368e154078e4b82da4e08903181ec440983688187580a83688185240b83688185240c903181db100d8e4b8391180c0d8e4b84b4760c078361e566090b8361e5660b0a8363e1020d098363e1020f088363e1020c0c8e4b81be5614058e4b81dd6e0c0d835f8184200c0d835f8181700c0d835f8181700c0d8c6686a8100b24d63b93ea661205128e4b8391180d1d937d82d740071d8e4b81dd6e071c90318dce1604338e4b848d78042c8e4b82e234042c8d1e83f106052b8e4b81dd6e05258e4b85a9700333921785880c03328e4482e03c04308e4b8687380237920f85ab68020317178e4b86dd1a001c16d77ed4c56c020e0700000000068e4b8687380100318e4b868f1e00328e4b86ae3600328f2385f62a01181a836880fe100132845a81ab1e0033836881a93001338e438ffd30031c836881a9300135835f81a5400235835f81a5400137921790ba2c023697498dfd280800180019903189f81a003900"_hex_v_u8, + "836280c06000836180c06001836280c06002836180c06003834280b1600303836180c0600403834280b1600403836180c0600503834280b1600503836280c0600603834280b1600603877e81fc20060c833a80b160060c836280c060070c877f81fc20070b834180b160070b877e81fc20070a836280c060070a834180b160080a880381fc200809836180c060081a834280b1600719836280c0600716836180c0600614834380b1600612836180c0600511834180b1600527834380b160041f834280b160041c836180c0600617836280c0600618834080b1600516877f81fc200531880281f960140414836280c060041e836280c060041f834280b160051f834580b160071e836280c060053b834280b1600422834880b1600423836180c0600622834280b1600343836180c0600443880281fc200f091d833e80b1600328834280b1600249836280c0600345877f81fc20140b23833b80b1600149877e81fc20020345877f81fc2011081f877e81fd400e0a12880281fb00110316877e81fc2003024a877f81fc20061b1c877f81fc200e0420877f81fc20040c1d877e81fc20021e20877f81fc20041d1f877e81fd40030e1c877f81fb00030a20877e81f9600c033200"_hex_v_u8 +}; + +// Randomly generated clusters, selected for slow linearization, from 28 to 64 transactions. +// The first 10 are selected for long total runtime, the last 10 for high runtime per cost. +static const std::vector> CLUSTERS_SYNTHETIC = { + "85058a7c008473b22d018706c70102873bd55303805e857b048732973005811487690686739032078260950508866b52098603a056000000000000000000000a8305986b0100000000000000000008852fa1260200000000000000000005855d8a0c03000000000000000000048468a9260400000000000000000004811f8449050000000000000000000483529f3e06000000000000000000048645962d07000000000000000000048333802a0800000000000000000001807187380900000000000000000001832f98220a000000000000000000018635a6380b00000000000000000001827c812c0c00000000000000000001844382700d00000000000000000000837d80410e00000000000000000000834ca16d0f00000000000000000000872d932c10000000000000000000008619b159110000000000000000000000"_hex_v_u8, + "8040810400864384650184599d6902806c802903853fa502048332a25b058627cb6b068024897307861080790883469c7a098458b10f0a846bab240b8406a1770c8526b2290d870c710e840d8c630f8608926f108646af49118426a123128747c74213813b837d0000000000000000000000000000000000000000148629c81b010000000000000000000000000000000000000012865a857b020000000000000000000000000000000000000011866c8d3d03000000000000000000000000000000000000000f71871404000000000000000000000000000000000000000a86509a1805000000000000000000000000000000000000000a863e8c4b060000000000000000000000000000000000000009871db86a070000000000000000000000000000000000000006807b930a08000000000000000000000000000000000000000585779a2a090000000000000000000000000000000000000002831584430a00000000000000000000000000000000000000018156804a0b000000000000000000000000000000000000000100"_hex_v_u8, + "8630852c008029804601864fb81d028602ae03038633af710481358b7a058559ad75068461a43b07865dd10a088516a42809810c8a250a821fa3150b812093470c805a85450d8708c27d0e8477aa770f8152850210806b892711810e805112821a904b13820582160000000000000000000000000000000000000000128114935f0100000000000000000000000000000000000000128179863902000000000000000000000000000000000000000e8064861103000000000000000000000000000000000000000d856a816c04000000000000000000000000000000000000000d8671b17405000000000000000000000000000000000000000d80368b0806000000000000000000000000000000000000000c847e881507000000000000000000000000000000000000000c8713811808000000000000000000000000000000000000000c801b89620900000000000000000000000000000000000000098139802b0a0000000000000000000000000000000000000009801d85440b00000000000000000000000000000000000000098161994d0c000000000000000000000000000000000000000882448c4b0d0000000000000000000000000000000000000008862b9c040e00000000000000000000000000000000000000068738e1580f000000000000000000000000000000000000000100"_hex_v_u8, + "8345803600823fa12101862acf45028611882c038115953e0482748b51058606af0f068619a55f078436b76f086482440983358a380a846abb680b8164991f0c8142931b0d8535b1590e846d8d6d0f8400977b10811f8d6211857bc24f12857daf3300000000000000000000000000000000000000138262a8700100000000000000000000000000000000000011821d91240200000000000000000000000000000000000010870aa538030000000000000000000000000000000000001080788d68040000000000000000000000000000000000000b8240940e0500000000000000000000000000000000000009872f863c060000000000000000000000000000000000000781568460070000000000000000000000000000000000000282138e350800000000000000000000000000000000000002871c991609000000000000000000000000000000000000028072942a0a00000000000000000000000000000000000002835d0a0b00000000000000000000000000000000000002830b824f0c0000000000000000000000000000000000000282608e110d000000000000000000000000000000000000028071842f0e00000000000000000000000000000000000002837287410f00000000000000000000000000000000000001810e88671000000000000000000000000000000000000001867c977f11000000000000000000000000000000000000018704932612000000000000000000000000000000000000018724b61b13000000000000000000000000000000000000018339a072140000000000000000000000000000000000000100"_hex_v_u8, + "8240952700865eb9710184219a7202863d8b2503833c9855048748b66705817ea16106814f8b1b07841f9349088717c90c09800d8d2d0a815190220b860bb4680c866d93250d81109a490e8075813e0f83388b3b1083268a7d118640c00f128727ae2813807b87781480428d5315833aaf6d168213a71d178623cc63188542a9531981796e1a855db8390000000000000000000000000000000000000000000000000000001b64883e0100000000000000000000000000000000000000000000000000001686638627020000000000000000000000000000000000000000000000000000168370871a03000000000000000000000000000000000000000000000000000015871b990104000000000000000000000000000000000000000000000000000014810e99080500000000000000000000000000000000000000000000000000000f80668e720600000000000000000000000000000000000000000000000000000f85738c240700000000000000000000000000000000000000000000000000000e803c8f660800000000000000000000000000000000000000000000000000000e873cb8200900000000000000000000000000000000000000000000000000000d8606cc3c0a00000000000000000000000000000000000000000000000000000b826f99050b000000000000000000000000000000000000000000000000000006815597400c000000000000000000000000000000000000000000000000000005860b955a0d00000000000000000000000000000000000000000000000000000581018f6b0e0000000000000000000000000000000000000000000000000000028644882e0f00000000000000000000000000000000000000000000000000000282048e0b1000000000000000000000000000000000000000000000000000000200"_hex_v_u8, + "8041853f008115953c01866ea90e02816ba407038101870b04854eda0505841d995a06854ad1690783528b5e0886208a3709873de6580a8454af370b8732d21e0c846ecd410d822d9b190e8335b0440f80348137108278866d11874bd81d1284788d741385389e20148501cf0c15813b81251681108971000000000000000000000000000000000000000000000017813a9d7201000000000000000000000000000000000000000000001782448a6b020000000000000000000000000000000000000000000017855cb361030000000000000000000000000000000000000000000013833da46c04000000000000000000000000000000000000000000001281349c230500000000000000000000000000000000000000000000108367a120060000000000000000000000000000000000000000000010803b8b7c07000000000000000000000000000000000000000000000e8375864508000000000000000000000000000000000000000000000e874b901609000000000000000000000000000000000000000000000e8209942e0a000000000000000000000000000000000000000000000d83248e700b000000000000000000000000000000000000000000000d840d8b040c000000000000000000000000000000000000000000000d8619c2360d000000000000000000000000000000000000000000000d8027824f0e000000000000000000000000000000000000000000000d8135841e0f000000000000000000000000000000000000000000000d85349f0510000000000000000000000000000000000000000000000c8476a00611000000000000000000000000000000000000000000000b831caa4f12000000000000000000000000000000000000000000000b84318b7e13000000000000000000000000000000000000000000000b83319f3b1400000000000000000000000000000000000000000000048701b76515000000000000000000000000000000000000000000000481558c461600000000000000000000000000000000000000000000038529be4e170000000000000000000000000000000000000000000003835da02018000000000000000000000000000000000000000000000200"_hex_v_u8, + "8639bf23008029863b0180539159028614c6330387408e22046782250582129117068365ad3a078075912708866e8a090982799c050a8474bf220b8548ba060c840eac020d850186460e815c85170f81628a301082369942118250a13b128644b74d13832da43314835c874f15800a8d5a00000000000000000000000000000000000000000000148707af630100000000000000000000000000000000000000000014806c993f020000000000000000000000000000000000000000001480288572030000000000000000000000000000000000000000001281449d7b04000000000000000000000000000000000000000000108505c536050000000000000000000000000000000000000000000f813e924b060000000000000000000000000000000000000000000f8510a24a070000000000000000000000000000000000000000000f8533875a080000000000000000000000000000000000000000000b8056800f090000000000000000000000000000000000000000000b870f8b0b0a0000000000000000000000000000000000000000000a87188b7a0b000000000000000000000000000000000000000000098417a87c0c00000000000000000000000000000000000000000009803d832c0d000000000000000000000000000000000000000000078663dd330e000000000000000000000000000000000000000000078511b21d0f000000000000000000000000000000000000000000058168992610000000000000000000000000000000000000000000058473bc4c110000000000000000000000000000000000000000000580428925120000000000000000000000000000000000000000000580408b61130000000000000000000000000000000000000000000581138d2814000000000000000000000000000000000000000000048647de091500000000000000000000000000000000000000000004817a85161600000000000000000000000000000000000000000004832d9d431700000000000000000000000000000000000000000003830b9512180000000000000000000000000000000000000000000382499e001900000000000000000000000000000000000000000003852d865e1a0000000000000000000000000000000000000000000380708f341b000000000000000000000000000000000000000000018555c1001c00000000000000000000000000000000000000000001822c886f1d0000000000000000000000000000000000000000000100"_hex_v_u8, + "82689142008207a3430182548a5902846f99510382049942048226976105833884760685499138078241a81b08801608098100854b0a820c85360b87319d4e0c821e89430d8565867d0e815a8e6c0f80478c3e108571894011836fb6291283148756138650dc4f14826ca204158726b01116833d8c4117855d9f4018866f934d19856b8e1a000000000000000000000000000000000000000000000000000019857ede10010000000000000000000000000000000000000000000000000019815881400200000000000000000000000000000000000000000000000000188277a914030000000000000000000000000000000000000000000000000017861ee9650400000000000000000000000000000000000000000000000000158656e824050000000000000000000000000000000000000000000000000015874ac43206000000000000000000000000000000000000000000000000001580449118070000000000000000000000000000000000000000000000000014812c873d08000000000000000000000000000000000000000000000000001083069a7109000000000000000000000000000000000000000000000000000e800482710a000000000000000000000000000000000000000000000000000e821a80590b0000000000000000000000000000000000000000000000000009854f8e640c0000000000000000000000000000000000000000000000000009833f9a040d00000000000000000000000000000000000000000000000000088002836f0e0000000000000000000000000000000000000000000000000008843d8d6e0f0000000000000000000000000000000000000000000000000007850ba7601000000000000000000000000000000000000000000000000000078172a62211000000000000000000000000000000000000000000000000000680008879120000000000000000000000000000000000000000000000000005861f83531300000000000000000000000000000000000000000000000000048155a44c140000000000000000000000000000000000000000000000000003810199501500000000000000000000000000000000000000000000000000038571d0061600000000000000000000000000000000000000000000000000038578e624170000000000000000000000000000000000000000000000000003872d8327180000000000000000000000000000000000000000000000000002871cae031900000000000000000000000000000000000000000000000000028733844e1a00000000000000000000000000000000000000000000000000028268a4681b0000000000000000000000000000000000000000000000000001806b95541c00000000000000000000000000000000000000000000000000008457af231d000000000000000000000000000000000000000000000000000000"_hex_v_u8, + "83159265008420be1c018635ba4702851ac26b0383559347048472943f058666ae7f068725d472078077901b08851fb31b098352bc560a84689c740b867ff24a0c807390100d80588f6f0e8670dc4a0f820aa604108747f803118340b41812841e9f5213830f9f27148557c3461583618b6916803a844d17811d9a5218863eac0e198465d8471a8578bf371b851bc6051c813e9d6e00000000000000000000000000000000000000000000000000000000001d810a9c7a01000000000000000000000000000000000000000000000000000000001d8532930402000000000000000000000000000000000000000000000000000000001c860dd80903000000000000000000000000000000000000000000000000000000001c84595c04000000000000000000000000000000000000000000000000000000001c8567930205000000000000000000000000000000000000000000000000000000001b8634ef3506000000000000000000000000000000000000000000000000000000001a873dc47007000000000000000000000000000000000000000000000000000000001a871b9543080000000000000000000000000000000000000000000000000000000019825d917f090000000000000000000000000000000000000000000000000000000019815c926f0a0000000000000000000000000000000000000000000000000000000018823c840b0b00000000000000000000000000000000000000000000000000000000178647952a0c00000000000000000000000000000000000000000000000000000000177b8d4c0d0000000000000000000000000000000000000000000000000000000014821e99240e000000000000000000000000000000000000000000000000000000001281628d230f0000000000000000000000000000000000000000000000000000000010835d8e2710000000000000000000000000000000000000000000000000000000000e84629c3611000000000000000000000000000000000000000000000000000000000d8264af3c12000000000000000000000000000000000000000000000000000000000a8300a36a13000000000000000000000000000000000000000000000000000000000a8567bf1f14000000000000000000000000000000000000000000000000000000000a8372b21815000000000000000000000000000000000000000000000000000000000a805b876e160000000000000000000000000000000000000000000000000000000008866eaa1f1700000000000000000000000000000000000000000000000000000000068018771800000000000000000000000000000000000000000000000000000000058357a23a190000000000000000000000000000000000000000000000000000000005841aa37b1a00000000000000000000000000000000000000000000000000000000048536981a1b0000000000000000000000000000000000000000000000000000000004811a8a2a1c0000000000000000000000000000000000000000000000000000000000805986361d00000000000000000000000000000000000000000000000000000000008626c9491e000000000000000000000000000000000000000000000000000000000000"_hex_v_u8, + "802d8a6400827caa630184598938028515c01903768805048416b02d058520b716068607ee1b078668ef6a08851c897109822182100a7f8a7e0b8514df270c8608b3070d843ab13a0e8512bb210f852dab13108152996d1180518a29128662d841138121971514812a9a48158574d25b168075864a17845cbf6e188261b54119822c8a711a824a9d4b1b8505a7251c8303b3551d833dc47d1e8130a0611f8352820920870cc005218463cf0222802b9102238176884600000000000000000000000000000000000000000000000000000000000000000000000023827b65010000000000000000000000000000000000000000000000000000000000000000000000237e8313020000000000000000000000000000000000000000000000000000000000000000000000228548dc5303000000000000000000000000000000000000000000000000000000000000000000000022810f8e1f040000000000000000000000000000000000000000000000000000000000000000000000228710f61a0500000000000000000000000000000000000000000000000000000000000000000000002182518f22060000000000000000000000000000000000000000000000000000000000000000000000218636f0490700000000000000000000000000000000000000000000000000000000000000000000001f8442cc610800000000000000000000000000000000000000000000000000000000000000000000001d805b921f0900000000000000000000000000000000000000000000000000000000000000000000001d861d820d0a00000000000000000000000000000000000000000000000000000000000000000000001d827d88580b00000000000000000000000000000000000000000000000000000000000000000000001d8254952b0c00000000000000000000000000000000000000000000000000000000000000000000001d822088610d00000000000000000000000000000000000000000000000000000000000000000000001d846a060e00000000000000000000000000000000000000000000000000000000000000000000001d873c935a0f0000000000000000000000000000000000000000000000000000000000000000000000198450bc44100000000000000000000000000000000000000000000000000000000000000000000000178250b646110000000000000000000000000000000000000000000000000000000000000000000000178350c1081200000000000000000000000000000000000000000000000000000000000000000000000f8414bb381300000000000000000000000000000000000000000000000000000000000000000000000e811c84181400000000000000000000000000000000000000000000000000000000000000000000000d8246aa101500000000000000000000000000000000000000000000000000000000000000000000000b81149b15160000000000000000000000000000000000000000000000000000000000000000000000078247af1f17000000000000000000000000000000000000000000000000000000000000000000000007816e863818000000000000000000000000000000000000000000000000000000000000000000000006853b8e02190000000000000000000000000000000000000000000000000000000000000000000000068161a32e1a000000000000000000000000000000000000000000000000000000000000000000000006811d87041b00000000000000000000000000000000000000000000000000000000000000000000000200"_hex_v_u8, + "80578c04008734c974018654a51d02856aae0d038719973c0106807f904f04018430913d000a871a985d0500018374965f030109867466000e86479a690203038735c80d0109836997010700000003840ea121080000000082699354030310803a520702000483019f2709000000108159881f0703000e847d8f10060400128128901604070e851e8f1109020100801c820f01090009803d884a040101000000010f850e8f610202000106800b880606000200000100832e826f040100000000000009856fba6002020100000008865f9a0e06000000000000000100"_hex_v_u8, + "81088137008624a1750180398f1602807a892b0102866bd12302028049450301803282010300076e880205000280068133050002810880170401088306997c05000002852e9e020401000282239424060001000166863504010000000d8135804d0601000000098227952105000100000a851a855e06000100000a8628a34b07000100000180038015070000010008801c8a7307000000010585168d210702000000000a821a6c03000202058329981f000200098507a21a000d8723bd13000417845cab5804020000000000000f83028f260201030380106e02010315842dac580501010012873bc37e040101001a8214973b060001000a80368d7902010100001900"_hex_v_u8, + "820ea20c0083308407018237a67a02821fa37900048320ab4a0202844db6210401811b98490008830b931701068676ba5d030100058317997504000386259140020402857cc2410402000a8001832d010c81078d35060200068149960708010004863ea83505040d83498656070200038320a77503050111830b822f070200010681018041060302008232863b090200000085619c03030502088524a00c030002078545a04602050002028100921a0405000200008473c1530900000101000e845a8d080500020100000017867087460502010000000f7489310401010102018216a16a0104000001078427af750501000000010585458b43040202000002872cda4f0304010000068209851d010200000000138321827a01000000000f8356a908010000002200"_hex_v_u8, + "833a8843008449995c01810a873000038066934d02018616c04d0202843a87600401826a864d0402855f8779050007863d936903038572d02d040204867cc61604030180098b69020509832792510601010581798e06040504833b9439070101000d851f946f01128147927d02030014866baa5d070201000c805f854f070300010b81579177090201000483209f7a0404020283678e420400050d8340981e080101000100048070816d07000101020c85578f010b01000000000004821a972605010204000010831c94280a01000000010001812d906c0303060882599e120505000200000a80638c5707020103844d9f04080004000000000e802b8c3107010300001b83189062020703000d872cb306080202000000098370a61e0600040000010d800a870f01010401000982369a1e030204000000058747c40c0102000317854e9e1c010300000000001a873eb04001020000002500"_hex_v_u8, + "83778b4c00834c932901853ed03202834a844c00048716a22d02038529c429020103843ebe7f0300048135944b040002810f9704040005850b9463010980628e700501000a80238d380502078739843b080000008405896304000f80094c04010d807d9739070000000c8218a32304030109853a9d460500020f817b9412030600000987498636010014850e8104060400000b80378b5407030001000b8659d87f05040001000b831e8f740a000100000009844c9f7d040501188203964806040101038201946806050000188406bd48060600000014860e9c4f0b010000000f8549c114040500030f813b82510406000218842da63e0800030115811d9b5a0501010003001c84208029070004000d832a95220500010101010022852b9b24030401010000001a857f8107050104000000000f853e9525080100000000000109821f9507050101000104827aa04602030220834f803405000201001c8268aa1603030000000001008475b43202000300000005827b93560202000100002900"_hex_v_u8, + "812d9c7200852fd301018170943702824a9e630387272402048353b33102038556b159020481599b00010883528735030381718370030107842cbf77050103816c8a1c0600048422c55d04078321a409090000000982688622050508806f8c090017873c5b08010004817fa04a050201048567c15f0505011082219f00080201118135892e07060000078360af6d0309138031824c0608001185739b080a020101000582018d0a0a000311813d860109010f8452bc6400060411825a8e2b050702098246a769012484049d3c07070100138313853a06080000158553b84b0b0203000000000010817da176030d1883388476040314852381580405050020830e966a0100042585128a3e08000001000121836f870403000700010000000025862cad000207020001128742d7180701010200010001088606da7c06000400010001000b84699b2d06030101000000010000138418b6250602030000001f84155c0401050013846a81610101030106873fd029020101000001000e82508521010300010d862ec12700000000001500"_hex_v_u8, + "7d836f008521bb6b018061934b0285118b7903802285670203850f8b5201058221a327030287369342060080188c340601802d8f68060003840fb2400700028227a713070100028747c93d06010007874b99630503010281779f3103060380228e000602000f802f831a09000106857781300803000000108707a45d080001010011830a9132030811821aa471080301000010864aca7c0602021185758d640702000110843c8a2306000214850ec3040a01020100000082568231030a00000d810e927503000a0d8001803e070001021980209041010c0005822f9c6205070005835cbf50030b000011852bb20f0a0400000000001d83179f210c010101000000001a806a967c05030403208212980d0404030302832ca5660902020000001f852e9e39080303020000028572ca5208010203020013816192320e010000010000228672ef1d06060100011082419e6a050701021f8424b26e05040104010c8420bf780406030000000000855ac63c0b00010100000000000c8426ae25030501030016874a9330030104030019871be924060200010000000000118644cd2103010302010f8345ad03000401010d81379c2102000100010030837f810901010000000e832bb24f0100000600"_hex_v_u8, + "816ba22900836f867101873c8056028511815803815497480205804283330105807e1d020383028a6100058533cc7b0100086a893d040003822493090302000b86108056020a854cbe4b05010483128c2d090000000182359815010c7281540800010002810889440602000e8518d60f09000000108563e05b0602020e8544ba220b000001018655da2105041382438a0c080202000381138a2b0702031085508f2904080004867ecb6709020002048375b142080103011a867bcc450508011983368a0b0c0200000a8420a84a0b03020000098312af7d0606020000088443c4550502050200068524b179090300000002001981188579030a00000217806d8f0a0c000005000d8076851a0800020003021581359369060101060103846eae34070203000200010022832a86670d0100000000000102830891620a00010100030000000001810592140900020001000003278712eb5d090500000100011f813f921a05020402128212ac1607010000090a870fc33001041981708e7a000903010a835ba272020900010001001884618f680207000101010118850bb168070301020000000680779a6f0406000002001f8670843605010500011e842e904709010003010000000d8222ae010205020128866086120702020000000000001082029c35010101030b82639c7802010300000100328138801001020102002000"_hex_v_u8, + "815e9a23008324a10d01825bb246028470af1301048737ba3202048264aa000304843383590403857ba37c05028351be6805028123965a0700098567c53f0307854fde3e04000e825aa8790305098259b529020f8365985d0505068246ac510800010e83448c410215801b8464011c85548a540705010f840c9d10050800118472bb480211821aa7510d010000000010823b9d50010c108533a8030607020007804e90030d0000000a80799051060701078717900106070000168511962d0209000209806c801c060603001a8347a86607060102000f8245924309030001031a8177a513070504001b81348064080a0000000002856ce16106010902000f850088600701090200048044847b09040301010020842189140d04010000010000168210a91b02000609208618ae420609020000000b8257951b0b00070100000009855d8b7b0902030520810190300a0701000000000000028254ae7b0700060001031f8748bf21040902108264af760f0004000001000a813587660c0005000100000000002d8256a04a080a00000000246a8526030a06001780068011050a000403866ecf5a080a03000000008603c30509020000050f8250916201070306000025825385380e00000200000000348210836504090200010100048334b97a060502000201012c84088e520705020002010105814a8c65050507011a8178a15e05010101000000003680448c190200020300010100003280388f2c03000000010000000000002600"_hex_v_u8, + "824da926008527804e01871bca36028604b04f038558d62c04804a960f02048513d87301068229897103058675a07e03000b843c8311050201814e5d02030c87029e020109841dc65a0601038227a325070101088334801c06030102853ee538070005688b0d080200010d8406a94d0b000000000b852bbf050a020000000a811380750d0000000005825c935d0b000200000a871bcb700902020109824187140f00000000098614ec7f0d000003078621942b080800058454bb1c0e030000000a847e630d030001000b8601e07e0c0002030c8655bf0b030f00018306bb5705010c1487038e071200000000001b856f816f1000000100020018820a9a530a0208000a81398a74001321853a944a060a03000117835aaf1c09030701118529b8690709020201248621bd330e010001010202148022800104100981428234090800030100188517cd2007060100020305836dc031020209022782449b69040c0100000001108651ac0a0607010101000000022a8337c0610505040202000001228547cd7c0d02000102020000000d843eba2a0b0501000000020025810f94010b0002030101000000010e803c921006000008041b8453bb3a0a0600030000000000000017841bae620708030100000016813f9924110100000200000000000000000c8637f36205060200050006857eb53f08020900000000002d810b9e580c0005000201000000000786459b700207060101188536b7790a0601000000010000000006854d905f08070201000000001680578f6a09030200030031837c8419080006000000022e8518a8500500040501000028861dd07e0801010300003b8743b97202000002000105003b8545b730010200010000000000001f00"_hex_v_u8 +}; + +static void LinearizeOptimallyTotal(benchmark::Bench& bench) +{ + BenchLinearizeOptimallyTotal(bench, "LinearizeOptimallyHistoricalTotal", CLUSTERS_HISTORICAL); + BenchLinearizeOptimallyTotal(bench, "LinearizeOptimallySyntheticTotal", CLUSTERS_SYNTHETIC); +} -BENCHMARK(LinearizeNoIters16TxWorstCaseLIMO, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeNoIters32TxWorstCaseLIMO, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeNoIters48TxWorstCaseLIMO, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeNoIters64TxWorstCaseLIMO, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeNoIters75TxWorstCaseLIMO, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeNoIters99TxWorstCaseLIMO, benchmark::PriorityLevel::HIGH); +static void LinearizeOptimallyPerCost(benchmark::Bench& bench) +{ + BenchLinearizeOptimallyPerCost(bench, "LinearizeOptimallyHistoricalPerCost", CLUSTERS_HISTORICAL); + BenchLinearizeOptimallyPerCost(bench, "LinearizeOptimallySyntheticPerCost", CLUSTERS_SYNTHETIC); +} BENCHMARK(PostLinearize16TxWorstCase, benchmark::PriorityLevel::HIGH); BENCHMARK(PostLinearize32TxWorstCase, benchmark::PriorityLevel::HIGH); @@ -390,30 +157,5 @@ BENCHMARK(PostLinearize64TxWorstCase, benchmark::PriorityLevel::HIGH); BENCHMARK(PostLinearize75TxWorstCase, benchmark::PriorityLevel::HIGH); BENCHMARK(PostLinearize99TxWorstCase, benchmark::PriorityLevel::HIGH); -BENCHMARK(MergeLinearizations16TxWorstCase, benchmark::PriorityLevel::HIGH); -BENCHMARK(MergeLinearizations32TxWorstCase, benchmark::PriorityLevel::HIGH); -BENCHMARK(MergeLinearizations48TxWorstCase, benchmark::PriorityLevel::HIGH); -BENCHMARK(MergeLinearizations64TxWorstCase, benchmark::PriorityLevel::HIGH); -BENCHMARK(MergeLinearizations75TxWorstCase, benchmark::PriorityLevel::HIGH); -BENCHMARK(MergeLinearizations99TxWorstCase, benchmark::PriorityLevel::HIGH); - -BENCHMARK(LinearizeOptimallyExample00, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample01, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample02, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample03, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample04, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample05, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample06, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample07, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample08, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample09, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample10, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample11, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample12, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample13, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample14, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample15, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample16, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample17, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample18, benchmark::PriorityLevel::HIGH); -BENCHMARK(LinearizeOptimallyExample19, benchmark::PriorityLevel::HIGH); +BENCHMARK(LinearizeOptimallyTotal, benchmark::PriorityLevel::HIGH); +BENCHMARK(LinearizeOptimallyPerCost, benchmark::PriorityLevel::HIGH); diff --git a/depend/bitcoin/src/bench/coin_selection.cpp b/depend/bitcoin/src/bench/coin_selection.cpp index 2150d800..41d01dfc 100644 --- a/depend/bitcoin/src/bench/coin_selection.cpp +++ b/depend/bitcoin/src/bench/coin_selection.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2022 The Bitcoin Core developers +// Copyright (c) 2012-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/connectblock.cpp b/depend/bitcoin/src/bench/connectblock.cpp index 3746ea29..cc972966 100644 --- a/depend/bitcoin/src/bench/connectblock.cpp +++ b/depend/bitcoin/src/bench/connectblock.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2025 The Bitcoin Core developers +// Copyright (c) 2025-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/crypto_hash.cpp b/depend/bitcoin/src/bench/crypto_hash.cpp index 05c7788d..0fd7245b 100644 --- a/depend/bitcoin/src/bench/crypto_hash.cpp +++ b/depend/bitcoin/src/bench/crypto_hash.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2022 The Bitcoin Core developers +// Copyright (c) 2016-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/descriptors.cpp b/depend/bitcoin/src/bench/descriptors.cpp index ac5580a4..719e69e3 100644 --- a/depend/bitcoin/src/bench/descriptors.cpp +++ b/depend/bitcoin/src/bench/descriptors.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2022 The Bitcoin Core developers +// Copyright (c) 2019-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/disconnected_transactions.cpp b/depend/bitcoin/src/bench/disconnected_transactions.cpp index 7c3c34bb..e4c72aa5 100644 --- a/depend/bitcoin/src/bench/disconnected_transactions.cpp +++ b/depend/bitcoin/src/bench/disconnected_transactions.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2023 The Bitcoin Core developers +// Copyright (c) 2023-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/duplicate_inputs.cpp b/depend/bitcoin/src/bench/duplicate_inputs.cpp index 9f22fa36..9bd7551d 100644 --- a/depend/bitcoin/src/bench/duplicate_inputs.cpp +++ b/depend/bitcoin/src/bench/duplicate_inputs.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2022 The Bitcoin Core developers +// Copyright (c) 2011-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/ellswift.cpp b/depend/bitcoin/src/bench/ellswift.cpp index 4dfef0e9..21868fb8 100644 --- a/depend/bitcoin/src/bench/ellswift.cpp +++ b/depend/bitcoin/src/bench/ellswift.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022-2023 The Bitcoin Core developers +// Copyright (c) 2022-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/gcs_filter.cpp b/depend/bitcoin/src/bench/gcs_filter.cpp index e6cc3d4d..d66402da 100644 --- a/depend/bitcoin/src/bench/gcs_filter.cpp +++ b/depend/bitcoin/src/bench/gcs_filter.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2022 The Bitcoin Core developers +// Copyright (c) 2018-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/hashpadding.cpp b/depend/bitcoin/src/bench/hashpadding.cpp index cca5c075..74047a0c 100644 --- a/depend/bitcoin/src/bench/hashpadding.cpp +++ b/depend/bitcoin/src/bench/hashpadding.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2022 The Bitcoin Core developers +// Copyright (c) 2015-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/lockedpool.cpp b/depend/bitcoin/src/bench/lockedpool.cpp index 5f39ddc4..5f8834f5 100644 --- a/depend/bitcoin/src/bench/lockedpool.cpp +++ b/depend/bitcoin/src/bench/lockedpool.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2022 The Bitcoin Core developers +// Copyright (c) 2016-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/logging.cpp b/depend/bitcoin/src/bench/logging.cpp index 3bf2b7ed..487ddcf3 100644 --- a/depend/bitcoin/src/bench/logging.cpp +++ b/depend/bitcoin/src/bench/logging.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020-2022 The Bitcoin Core developers +// Copyright (c) 2020-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/mempool_ephemeral_spends.cpp b/depend/bitcoin/src/bench/mempool_ephemeral_spends.cpp index c973c783..a572d945 100644 --- a/depend/bitcoin/src/bench/mempool_ephemeral_spends.cpp +++ b/depend/bitcoin/src/bench/mempool_ephemeral_spends.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2022 The Bitcoin Core developers +// Copyright (c) 2011-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/mempool_eviction.cpp b/depend/bitcoin/src/bench/mempool_eviction.cpp index dcbe1245..7e64592d 100644 --- a/depend/bitcoin/src/bench/mempool_eviction.cpp +++ b/depend/bitcoin/src/bench/mempool_eviction.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2022 The Bitcoin Core developers +// Copyright (c) 2011-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/mempool_stress.cpp b/depend/bitcoin/src/bench/mempool_stress.cpp index 8bdeb75c..3e83b2c2 100644 --- a/depend/bitcoin/src/bench/mempool_stress.cpp +++ b/depend/bitcoin/src/bench/mempool_stress.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2022 The Bitcoin Core developers +// Copyright (c) 2011-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/merkle_root.cpp b/depend/bitcoin/src/bench/merkle_root.cpp index 98ce197e..f9c933ec 100644 --- a/depend/bitcoin/src/bench/merkle_root.cpp +++ b/depend/bitcoin/src/bench/merkle_root.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2022 The Bitcoin Core developers +// Copyright (c) 2016-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/nanobench.cpp b/depend/bitcoin/src/bench/nanobench.cpp index fcdd8649..aa5b5527 100644 --- a/depend/bitcoin/src/bench/nanobench.cpp +++ b/depend/bitcoin/src/bench/nanobench.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020 The Bitcoin Core developers +// Copyright (c) 2019-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/peer_eviction.cpp b/depend/bitcoin/src/bench/peer_eviction.cpp index 5b08cc75..43d819cc 100644 --- a/depend/bitcoin/src/bench/peer_eviction.cpp +++ b/depend/bitcoin/src/bench/peer_eviction.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2021-2022 The Bitcoin Core developers +// Copyright (c) 2021-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/poly1305.cpp b/depend/bitcoin/src/bench/poly1305.cpp index f58afe98..eaa7857f 100644 --- a/depend/bitcoin/src/bench/poly1305.cpp +++ b/depend/bitcoin/src/bench/poly1305.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2022 The Bitcoin Core developers +// Copyright (c) 2019-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/pool.cpp b/depend/bitcoin/src/bench/pool.cpp index 40b098f5..b31046cf 100644 --- a/depend/bitcoin/src/bench/pool.cpp +++ b/depend/bitcoin/src/bench/pool.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022 The Bitcoin Core developers +// Copyright (c) 2022-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/prevector.cpp b/depend/bitcoin/src/bench/prevector.cpp index 2d4e19cf..85ef196e 100644 --- a/depend/bitcoin/src/bench/prevector.cpp +++ b/depend/bitcoin/src/bench/prevector.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2022 The Bitcoin Core developers +// Copyright (c) 2015-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/readwriteblock.cpp b/depend/bitcoin/src/bench/readwriteblock.cpp index a742a1e8..d756789b 100644 --- a/depend/bitcoin/src/bench/readwriteblock.cpp +++ b/depend/bitcoin/src/bench/readwriteblock.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2023 The Bitcoin Core developers +// Copyright (c) 2023-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/rollingbloom.cpp b/depend/bitcoin/src/bench/rollingbloom.cpp index 6b3e1c43..a9b7806e 100644 --- a/depend/bitcoin/src/bench/rollingbloom.cpp +++ b/depend/bitcoin/src/bench/rollingbloom.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2022 The Bitcoin Core developers +// Copyright (c) 2016-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/rpc_blockchain.cpp b/depend/bitcoin/src/bench/rpc_blockchain.cpp index 52916242..0dc217ea 100644 --- a/depend/bitcoin/src/bench/rpc_blockchain.cpp +++ b/depend/bitcoin/src/bench/rpc_blockchain.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2022 The Bitcoin Core developers +// Copyright (c) 2016-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/rpc_mempool.cpp b/depend/bitcoin/src/bench/rpc_mempool.cpp index 069230f0..c710c2c8 100644 --- a/depend/bitcoin/src/bench/rpc_mempool.cpp +++ b/depend/bitcoin/src/bench/rpc_mempool.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2022 The Bitcoin Core developers +// Copyright (c) 2011-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/sign_transaction.cpp b/depend/bitcoin/src/bench/sign_transaction.cpp index 40219458..f4294389 100644 --- a/depend/bitcoin/src/bench/sign_transaction.cpp +++ b/depend/bitcoin/src/bench/sign_transaction.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2023 The Bitcoin Core developers +// Copyright (c) 2023-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/streams_findbyte.cpp b/depend/bitcoin/src/bench/streams_findbyte.cpp index 1f6f4d44..9c52a72a 100644 --- a/depend/bitcoin/src/bench/streams_findbyte.cpp +++ b/depend/bitcoin/src/bench/streams_findbyte.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2023 The Bitcoin Core developers +// Copyright (c) 2023-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/strencodings.cpp b/depend/bitcoin/src/bench/strencodings.cpp index dd5829ca..38af7ad7 100644 --- a/depend/bitcoin/src/bench/strencodings.cpp +++ b/depend/bitcoin/src/bench/strencodings.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022 The Bitcoin Core developers +// Copyright (c) 2022-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/util_time.cpp b/depend/bitcoin/src/bench/util_time.cpp index 4cbc0dfb..a4f30516 100644 --- a/depend/bitcoin/src/bench/util_time.cpp +++ b/depend/bitcoin/src/bench/util_time.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2022 The Bitcoin Core developers +// Copyright (c) 2019-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/verify_script.cpp b/depend/bitcoin/src/bench/verify_script.cpp index 062f9a01..1266f6dd 100644 --- a/depend/bitcoin/src/bench/verify_script.cpp +++ b/depend/bitcoin/src/bench/verify_script.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2022 The Bitcoin Core developers +// Copyright (c) 2016-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/wallet_balance.cpp b/depend/bitcoin/src/bench/wallet_balance.cpp index 8d3f7f96..5f3711ad 100644 --- a/depend/bitcoin/src/bench/wallet_balance.cpp +++ b/depend/bitcoin/src/bench/wallet_balance.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2022 The Bitcoin Core developers +// Copyright (c) 2012-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/wallet_create_tx.cpp b/depend/bitcoin/src/bench/wallet_create_tx.cpp index 7fb535f4..cd9ffd10 100644 --- a/depend/bitcoin/src/bench/wallet_create_tx.cpp +++ b/depend/bitcoin/src/bench/wallet_create_tx.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022 The Bitcoin Core developers +// Copyright (c) 2022-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php. @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #include #include +using kernel::ChainstateRole; using wallet::CWallet; using wallet::CreateMockableWalletDatabase; using wallet::WALLET_FLAG_DESCRIPTORS; @@ -101,7 +103,7 @@ void generateFakeBlock(const CChainParams& params, // notify wallet const auto& pindex = WITH_LOCK(::cs_main, return context.chainman->ActiveChain().Tip()); - wallet.blockConnected(ChainstateRole::NORMAL, kernel::MakeBlockInfo(pindex, &block)); + wallet.blockConnected(ChainstateRole{}, kernel::MakeBlockInfo(pindex, &block)); } struct PreSelectInputs { diff --git a/depend/bitcoin/src/bench/wallet_ismine.cpp b/depend/bitcoin/src/bench/wallet_ismine.cpp index 6eef1efd..aa0fd276 100644 --- a/depend/bitcoin/src/bench/wallet_ismine.cpp +++ b/depend/bitcoin/src/bench/wallet_ismine.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022 The Bitcoin Core developers +// Copyright (c) 2022-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/wallet_loading.cpp b/depend/bitcoin/src/bench/wallet_loading.cpp index 3397fb00..dffc76e1 100644 --- a/depend/bitcoin/src/bench/wallet_loading.cpp +++ b/depend/bitcoin/src/bench/wallet_loading.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022 The Bitcoin Core developers +// Copyright (c) 2022-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bench/wallet_migration.cpp b/depend/bitcoin/src/bench/wallet_migration.cpp index 0ce23a49..f38f2165 100644 --- a/depend/bitcoin/src/bench/wallet_migration.cpp +++ b/depend/bitcoin/src/bench/wallet_migration.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2024 The Bitcoin Core developers +// Copyright (c) 2024-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php. @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include diff --git a/depend/bitcoin/src/bitcoin-chainstate.cpp b/depend/bitcoin/src/bitcoin-chainstate.cpp index 310ca95c..91c5639e 100644 --- a/depend/bitcoin/src/bitcoin-chainstate.cpp +++ b/depend/bitcoin/src/bitcoin-chainstate.cpp @@ -1,3 +1,16 @@ +// Copyright (c) 2022-present The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// +// The bitcoin-chainstate executable serves to surface the dependencies required +// by a program wishing to use Bitcoin Core's consensus engine as it is right +// now. +// +// DEVELOPER NOTE: Since this is a "demo-only", experimental, etc. executable, +// it may diverge from Bitcoin Core's coding style. +// +// It is part of the libbitcoinkernel project. + #include #include diff --git a/depend/bitcoin/src/bitcoin-cli.cpp b/depend/bitcoin/src/bitcoin-cli.cpp index d6fcaa84..88d0665e 100644 --- a/depend/bitcoin/src/bitcoin-cli.cpp +++ b/depend/bitcoin/src/bitcoin-cli.cpp @@ -1128,7 +1128,7 @@ static void ParseGetInfoResult(UniValue& result) const std::string proxy = network["proxy"].getValStr(); if (proxy.empty()) continue; // Add proxy to ordered_proxy if has not been processed - if (proxy_networks.find(proxy) == proxy_networks.end()) ordered_proxies.push_back(proxy); + if (!proxy_networks.contains(proxy)) ordered_proxies.push_back(proxy); proxy_networks[proxy].push_back(network["name"].getValStr()); } diff --git a/depend/bitcoin/src/bitcoin-tx.cpp b/depend/bitcoin/src/bitcoin-tx.cpp index 937db68e..fdff656f 100644 --- a/depend/bitcoin/src/bitcoin-tx.cpp +++ b/depend/bitcoin/src/bitcoin-tx.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -588,7 +588,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr) CCoinsView viewDummy; CCoinsViewCache view(&viewDummy); - if (!registers.count("privatekeys")) + if (!registers.contains("privatekeys")) throw std::runtime_error("privatekeys register variable must be set."); FillableSigningProvider tempKeystore; UniValue keysObj = registers["privatekeys"]; @@ -604,7 +604,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr) } // Add previous txouts given in the RPC call: - if (!registers.count("prevtxs")) + if (!registers.contains("prevtxs")) throw std::runtime_error("prevtxs register variable must be set."); UniValue prevtxsObj = registers["prevtxs"]; { diff --git a/depend/bitcoin/src/bitcoin-util.cpp b/depend/bitcoin/src/bitcoin-util.cpp index 10967bd5..a6fd026b 100644 --- a/depend/bitcoin/src/bitcoin-util.cpp +++ b/depend/bitcoin/src/bitcoin-util.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bitcoin.cpp b/depend/bitcoin/src/bitcoin.cpp index 37b6fdca..5d42bb04 100644 --- a/depend/bitcoin/src/bitcoin.cpp +++ b/depend/bitcoin/src/bitcoin.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2025 The Bitcoin Core developers +// Copyright (c) 2025-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/bitcoind.cpp b/depend/bitcoin/src/bitcoind.cpp index 37cacb2a..323e7577 100644 --- a/depend/bitcoin/src/bitcoind.cpp +++ b/depend/bitcoin/src/bitcoind.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/blockencodings.cpp b/depend/bitcoin/src/blockencodings.cpp index d48ba400..49900482 100644 --- a/depend/bitcoin/src/blockencodings.cpp +++ b/depend/bitcoin/src/blockencodings.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2022 The Bitcoin Core developers +// Copyright (c) 2016-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/blockencodings.h b/depend/bitcoin/src/blockencodings.h index 124df50a..603cbea6 100644 --- a/depend/bitcoin/src/blockencodings.h +++ b/depend/bitcoin/src/blockencodings.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2022 The Bitcoin Core developers +// Copyright (c) 2016-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/blockfilter.cpp b/depend/bitcoin/src/blockfilter.cpp index 94bcc497..44d08440 100644 --- a/depend/bitcoin/src/blockfilter.cpp +++ b/depend/bitcoin/src/blockfilter.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2022 The Bitcoin Core developers +// Copyright (c) 2018-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/blockfilter.h b/depend/bitcoin/src/blockfilter.h index b70afb90..225d3b16 100644 --- a/depend/bitcoin/src/blockfilter.h +++ b/depend/bitcoin/src/blockfilter.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2022 The Bitcoin Core developers +// Copyright (c) 2018-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/chain.cpp b/depend/bitcoin/src/chain.cpp index 94be7180..64ea44bb 100644 --- a/depend/bitcoin/src/chain.cpp +++ b/depend/bitcoin/src/chain.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/chain.h b/depend/bitcoin/src/chain.h index 64c86357..466276c0 100644 --- a/depend/bitcoin/src/chain.h +++ b/depend/bitcoin/src/chain.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -39,14 +39,6 @@ static constexpr int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME; static constexpr int32_t SEQ_ID_BEST_CHAIN_FROM_DISK = 0; static constexpr int32_t SEQ_ID_INIT_FROM_DISK = 1; -/** - * Maximum gap between node time and block time used - * for the "Catching up..." mode in GUI. - * - * Ref: https://github.com/bitcoin/bitcoin/pull/1026 - */ -static constexpr int64_t MAX_BLOCK_TIME_GAP = 90 * 60; - enum BlockStatus : uint32_t { //! Unused. BLOCK_VALID_UNKNOWN = 0, diff --git a/depend/bitcoin/src/chainparams.cpp b/depend/bitcoin/src/chainparams.cpp index eb915b0b..32c3bff7 100644 --- a/depend/bitcoin/src/chainparams.cpp +++ b/depend/bitcoin/src/chainparams.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/chainparams.h b/depend/bitcoin/src/chainparams.h index 4743e022..571e9e17 100644 --- a/depend/bitcoin/src/chainparams.h +++ b/depend/bitcoin/src/chainparams.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2021 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/chainparamsbase.h b/depend/bitcoin/src/chainparamsbase.h index adbd6a51..37e69b32 100644 --- a/depend/bitcoin/src/chainparamsbase.h +++ b/depend/bitcoin/src/chainparamsbase.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020 The Bitcoin Core developers +// Copyright (c) 2014-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/checkqueue.h b/depend/bitcoin/src/checkqueue.h index 5920d293..037023ee 100644 --- a/depend/bitcoin/src/checkqueue.h +++ b/depend/bitcoin/src/checkqueue.h @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2022 The Bitcoin Core developers +// Copyright (c) 2012-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/clientversion.h b/depend/bitcoin/src/clientversion.h index a8eabb85..9d09e502 100644 --- a/depend/bitcoin/src/clientversion.h +++ b/depend/bitcoin/src/clientversion.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/cluster_linearize.h b/depend/bitcoin/src/cluster_linearize.h index 73c8a037..d65e61d4 100644 --- a/depend/bitcoin/src/cluster_linearize.h +++ b/depend/bitcoin/src/cluster_linearize.h @@ -334,6 +334,15 @@ class DepGraph return true; } + unsigned CountDependencies() const noexcept + { + unsigned ret = 0; + for (auto i : Positions()) { + ret += GetReducedParents(i).Count(); + } + return ret; + } + /** Reduce memory usage if possible. No observable effect. */ void Compact() noexcept { @@ -386,11 +395,20 @@ struct SetInfo return *this; } - /** Construct a new SetInfo equal to this, with more transactions added (which may overlap - * with the existing transactions in the SetInfo). */ - [[nodiscard]] SetInfo Add(const DepGraph& depgraph, const SetType& txn) const noexcept + /** Remove the transactions of other from this SetInfo (which must be a subset). */ + SetInfo& operator-=(const SetInfo& other) noexcept + { + Assume(other.transactions.IsSubsetOf(transactions)); + transactions -= other.transactions; + feerate -= other.feerate; + return *this; + } + + /** Compute the difference between this and other SetInfo (which must be a subset). */ + SetInfo operator-(const SetInfo& other) const noexcept { - return {transactions | txn, feerate + depgraph.FeeRate(txn - transactions)}; + Assume(other.transactions.IsSubsetOf(transactions)); + return {transactions - other.transactions, feerate - other.feerate}; } /** Swap two SetInfo objects. */ @@ -404,7 +422,27 @@ struct SetInfo friend bool operator==(const SetInfo&, const SetInfo&) noexcept = default; }; -/** Compute the feerates of the chunks of linearization. */ +/** Compute the chunks of linearization as SetInfos. */ +template +std::vector> ChunkLinearizationInfo(const DepGraph& depgraph, std::span linearization) noexcept +{ + std::vector> ret; + for (DepGraphIndex i : linearization) { + /** The new chunk to be added, initially a singleton. */ + SetInfo new_chunk(depgraph, i); + // As long as the new chunk has a higher feerate than the last chunk so far, absorb it. + while (!ret.empty() && new_chunk.feerate >> ret.back().feerate) { + new_chunk |= ret.back(); + ret.pop_back(); + } + // Actually move that new chunk into the chunking. + ret.emplace_back(std::move(new_chunk)); + } + return ret; +} + +/** Compute the feerates of the chunks of linearization. Identical to ChunkLinearizationInfo, but + * only returns the chunk feerates, not the corresponding transaction sets. */ template std::vector ChunkLinearization(const DepGraph& depgraph, std::span linearization) noexcept { @@ -423,620 +461,880 @@ std::vector ChunkLinearization(const DepGraph& depgraph, std:: return ret; } -/** Data structure encapsulating the chunking of a linearization, permitting removal of subsets. */ +/** Class to represent the internal state of the spanning-forest linearization (SFL) algorithm. + * + * At all times, each dependency is marked as either "active" or "inactive". The subset of active + * dependencies is the state of the SFL algorithm. The implementation maintains several other + * values to speed up operations, but everything is ultimately a function of what that subset of + * active dependencies is. + * + * Given such a subset, define a chunk as the set of transactions that are connected through active + * dependencies (ignoring their parent/child direction). Thus, every state implies a particular + * partitioning of the graph into chunks (including potential singletons). In the extreme, each + * transaction may be in its own chunk, or in the other extreme all transactions may form a single + * chunk. A chunk's feerate is its total fee divided by its total size. + * + * The algorithm consists of switching dependencies between active and inactive. The final + * linearization that is produced at the end consists of these chunks, sorted from high to low + * feerate, each individually sorted in an arbitrary but topological (= no child before parent) + * way. + * + * We define three quality properties the state can have, each being stronger than the previous: + * + * - acyclic: The state is acyclic whenever no cycle of active dependencies exists within the + * graph, ignoring the parent/child direction. This is equivalent to saying that within + * each chunk the set of active dependencies form a tree, and thus the overall set of + * active dependencies in the graph form a spanning forest, giving the algorithm its + * name. Being acyclic is also equivalent to every chunk of N transactions having + * exactly N-1 active dependencies. + * + * For example in a diamond graph, D->{B,C}->A, the 4 dependencies cannot be + * simultaneously active. If at least one is inactive, the state is acyclic. + * + * The algorithm maintains an acyclic state at *all* times as an invariant. This implies + * that activating a dependency always corresponds to merging two chunks, and that + * deactivating one always corresponds to splitting two chunks. + * + * - topological: We say the state is topological whenever it is acyclic and no inactive dependency + * exists between two distinct chunks such that the child chunk has higher or equal + * feerate than the parent chunk. + * + * The relevance is that whenever the state is topological, the produced output + * linearization will be topological too (i.e., not have children before parents). + * Note that the "or equal" part of the definition matters: if not, one can end up + * in a situation with mutually-dependent equal-feerate chunks that cannot be + * linearized. For example C->{A,B} and D->{A,B}, with C->A and D->B active. The AC + * chunk depends on DB through C->B, and the BD chunk depends on AC through D->A. + * Merging them into a single ABCD chunk fixes this. + * + * The algorithm attempts to keep the state topological as much as possible, so it + * can be interrupted to produce an output whenever, but will sometimes need to + * temporarily deviate from it when improving the state. + * + * - optimal: For every active dependency, define its top and bottom set as the set of transactions + * in the chunks that would result if the dependency were deactivated; the top being the + * one with the dependency's parent, and the bottom being the one with the child. Note + * that due to acyclicity, every deactivation splits a chunk exactly in two. + * + * We say the state is optimal whenever it is topological and it has no active + * dependency whose top feerate is strictly higher than its bottom feerate. The + * relevance is that it can be proven that whenever the state is optimal, the produced + * linearization will also be optimal (in the convexified feerate diagram sense). It can + * also be proven that for every graph at least one optimal state exists. + * + * Note that it is possible for the SFL state to not be optimal, but the produced + * linearization to still be optimal. This happens when the chunks of a state are + * identical to those of an optimal state, but the exact set of active dependencies + * within a chunk differ in such a way that the state optimality condition is not + * satisfied. Thus, the state being optimal is more a "the eventual output is *known* + * to be optimal". + * + * The algorithm terminates whenever an optimal state is reached. + * + * + * This leads to the following high-level algorithm: + * - Start with all dependencies inactive, and thus all transactions in their own chunk. This is + * definitely acyclic. + * - Activate dependencies (merging chunks) until the state is topological. + * - Loop until optimal (no dependencies with higher-feerate top than bottom), or time runs out: + * - Deactivate a violating dependency, potentially making the state non-topological. + * - Activate other dependencies to make the state topological again. + * - Output the chunks from high to low feerate, each internally sorted topologically. + * + * When merging, we always either: + * - Merge upwards: merge a chunk with the lowest-feerate other chunk it depends on, among those + * with lower or equal feerate than itself. + * - Merge downwards: merge a chunk with the highest-feerate other chunk that depends on it, among + * those with higher or equal feerate than itself. + * + * Using these strategies in the improvement loop above guarantees that the output linearization + * after a deactivate + merge step is never worse or incomparable (in the convexified feerate + * diagram sense) than the output linearization that would be produced before the step. With that, + * we can refine the high-level algorithm to: + * - Start with all dependencies inactive. + * - Perform merges as described until none are possible anymore, making the state topological. + * - Loop until optimal or time runs out: + * - Pick a dependency D to deactivate among those with higher feerate top than bottom. + * - Deactivate D, causing the chunk it is in to split into top T and bottom B. + * - Do an upwards merge of T, if possible. If so, repeat the same with the merged result. + * - Do a downwards merge of B, if possible. If so, repeat the same with the merged result. + * - Output the chunks from high to low feerate, each internally sorted topologically. + * + * Instead of performing merges arbitrarily to make the initial state topological, it is possible + * to do so guided by an existing linearization. This has the advantage that the state's would-be + * output linearization is immediately as good as the existing linearization it was based on: + * - Start with all dependencies inactive. + * - For each transaction t in the existing linearization: + * - Find the chunk C that transaction is in (which will be singleton). + * - Do an upwards merge of C, if possible. If so, repeat the same with the merged result. + * No downwards merges are needed in this case. + * + * What remains to be specified are a number of heuristics: + * + * - How to decide which chunks to merge: + * - The merge upwards and downward rules specify that the lowest-feerate respectively + * highest-feerate candidate chunk is merged with, but if there are multiple equal-feerate + * candidates, a uniformly random one among them is picked. + * + * - How to decide what dependency to activate (when merging chunks): + * - After picking two chunks to be merged (see above), a uniformly random dependency between the + * two chunks is activated. + * + * - How to decide which chunk to find a dependency to split in: + * - A round-robin queue of chunks to improve is maintained. The initial ordering of this queue + * is uniformly randomly permuted. + * + * - How to decide what dependency to deactivate (when splitting chunks): + * - Inside the selected chunk (see above), among the dependencies whose top feerate is strictly + * higher than its bottom feerate in the selected chunk, if any, a uniformly random dependency + * is deactivated. + * + * - How to decide the exact output linearization: + * - When there are multiple equal-feerate chunks with no dependencies between them, output a + * uniformly random one among the ones with no missing dependent chunks first. + * - Within chunks, repeatedly pick a uniformly random transaction among those with no missing + * dependencies. + */ template -class LinearizationChunking +class SpanningForestState { - /** The depgraph this linearization is for. */ - const DepGraph& m_depgraph; - - /** The linearization we started from, possibly with removed prefix stripped. */ - std::span m_linearization; - - /** Chunk sets and their feerates, of what remains of the linearization. */ - std::vector> m_chunks; +private: + /** Internal RNG. */ + InsecureRandomContext m_rng; - /** How large a prefix of m_chunks corresponds to removed transactions. */ - DepGraphIndex m_chunks_skip{0}; + /** Data type to represent indexing into m_tx_data. */ + using TxIdx = uint32_t; + /** Data type to represent indexing into m_dep_data. */ + using DepIdx = uint32_t; + + /** Structure with information about a single transaction. For transactions that are the + * representative for the chunk they are in, this also stores chunk information. */ + struct TxData { + /** The dependencies to children of this transaction. Immutable after construction. */ + std::vector child_deps; + /** The set of parent transactions of this transaction. Immutable after construction. */ + SetType parents; + /** The set of child transactions of this transaction. Immutable after construction. */ + SetType children; + /** Which transaction holds the chunk_setinfo for the chunk this transaction is in + * (the representative for the chunk). */ + TxIdx chunk_rep; + /** (Only if this transaction is the representative for the chunk it is in) the total + * chunk set and feerate. */ + SetInfo chunk_setinfo; + }; - /** Which transactions remain in the linearization. */ - SetType m_todo; + /** Structure with information about a single dependency. */ + struct DepData { + /** Whether this dependency is active. */ + bool active; + /** What the parent and child transactions are. Immutable after construction. */ + TxIdx parent, child; + /** (Only if this dependency is active) the would-be top chunk and its feerate that would + * be formed if this dependency were to be deactivated. */ + SetInfo top_setinfo; + }; - /** Fill the m_chunks variable, and remove the done prefix of m_linearization. */ - void BuildChunks() noexcept + /** The set of all TxIdx's of transactions in the cluster indexing into m_tx_data. */ + SetType m_transaction_idxs; + /** Information about each transaction (and chunks). Keeps the "holes" from DepGraph during + * construction. Indexed by TxIdx. */ + std::vector m_tx_data; + /** Information about each dependency. Indexed by DepIdx. */ + std::vector m_dep_data; + /** A FIFO of chunk representatives of chunks that may be improved still. */ + VecDeque m_suboptimal_chunks; + + /** The number of updated transactions in activations/deactivations. */ + uint64_t m_cost{0}; + + /** Update a chunk: + * - All transactions have their chunk representative set to `chunk_rep`. + * - All dependencies which have `query` in their top_setinfo get `dep_change` added to it + * (if `!Subtract`) or removed from it (if `Subtract`). + */ + template + void UpdateChunk(const SetType& chunk, TxIdx query, TxIdx chunk_rep, const SetInfo& dep_change) noexcept { - // Caller must clear m_chunks. - Assume(m_chunks.empty()); - - // Chop off the initial part of m_linearization that is already done. - while (!m_linearization.empty() && !m_todo[m_linearization.front()]) { - m_linearization = m_linearization.subspan(1); - } - - // Iterate over the remaining entries in m_linearization. This is effectively the same - // algorithm as ChunkLinearization, but supports skipping parts of the linearization and - // keeps track of the sets themselves instead of just their feerates. - for (auto idx : m_linearization) { - if (!m_todo[idx]) continue; - // Start with an initial chunk containing just element idx. - SetInfo add(m_depgraph, idx); - // Absorb existing final chunks into add while they have lower feerate. - while (!m_chunks.empty() && add.feerate >> m_chunks.back().feerate) { - add |= m_chunks.back(); - m_chunks.pop_back(); + // Iterate over all the chunk's transactions. + for (auto tx_idx : chunk) { + auto& tx_data = m_tx_data[tx_idx]; + // Update the chunk representative. + tx_data.chunk_rep = chunk_rep; + // Iterate over all active dependencies with tx_idx as parent. Combined with the outer + // loop this iterates over all internal active dependencies of the chunk. + auto child_deps = std::span{tx_data.child_deps}; + for (auto dep_idx : child_deps) { + auto& dep_entry = m_dep_data[dep_idx]; + Assume(dep_entry.parent == tx_idx); + // Skip inactive dependencies. + if (!dep_entry.active) continue; + // If this dependency's top_setinfo contains query, update it to add/remove + // dep_change. + if (dep_entry.top_setinfo.transactions[query]) { + if constexpr (Subtract) { + dep_entry.top_setinfo -= dep_change; + } else { + dep_entry.top_setinfo |= dep_change; + } + } } - // Remember new chunk. - m_chunks.push_back(std::move(add)); } } -public: - /** Initialize a LinearizationSubset object for a given length of linearization. */ - explicit LinearizationChunking(const DepGraph& depgraph LIFETIMEBOUND, std::span lin LIFETIMEBOUND) noexcept : - m_depgraph(depgraph), m_linearization(lin) + /** Make a specified inactive dependency active. Returns the merged chunk representative. */ + TxIdx Activate(DepIdx dep_idx) noexcept { - // Mark everything in lin as todo still. - for (auto i : m_linearization) m_todo.Set(i); - // Compute the initial chunking. - m_chunks.reserve(depgraph.TxCount()); - BuildChunks(); + auto& dep_data = m_dep_data[dep_idx]; + Assume(!dep_data.active); + auto& child_tx_data = m_tx_data[dep_data.child]; + auto& parent_tx_data = m_tx_data[dep_data.parent]; + + // Gather information about the parent and child chunks. + Assume(parent_tx_data.chunk_rep != child_tx_data.chunk_rep); + auto& par_chunk_data = m_tx_data[parent_tx_data.chunk_rep]; + auto& chl_chunk_data = m_tx_data[child_tx_data.chunk_rep]; + TxIdx top_rep = parent_tx_data.chunk_rep; + auto top_part = par_chunk_data.chunk_setinfo; + auto bottom_part = chl_chunk_data.chunk_setinfo; + // Update the parent chunk to also contain the child. + par_chunk_data.chunk_setinfo |= bottom_part; + m_cost += par_chunk_data.chunk_setinfo.transactions.Count(); + + // Consider the following example: + // + // A A There are two chunks, ABC and DEF, and the inactive E->C dependency + // / \ / \ is activated, resulting in a single chunk ABCDEF. + // B C B C + // : ==> | Dependency | top set before | top set after | change + // D E D E B->A | AC | ACDEF | +DEF + // \ / \ / C->A | AB | AB | + // F F F->D | D | D | + // F->E | E | ABCE | +ABC + // + // The common pattern here is that any dependency which has the parent or child of the + // dependency being activated (E->C here) in its top set, will have the opposite part added + // to it. This is true for B->A and F->E, but not for C->A and F->D. + // + // Let UpdateChunk traverse the old parent chunk top_part (ABC in example), and add + // bottom_part (DEF) to every dependency's top_set which has the parent (C) in it. The + // representative of each of these transactions was already top_rep, so that is not being + // changed here. + UpdateChunk(/*chunk=*/top_part.transactions, /*query=*/dep_data.parent, + /*chunk_rep=*/top_rep, /*dep_change=*/bottom_part); + // Let UpdateChunk traverse the old child chunk bottom_part (DEF in example), and add + // top_part (ABC) to every dependency's top_set which has the child (E) in it. At the same + // time, change the representative of each of these transactions to be top_rep, which + // becomes the representative for the merged chunk. + UpdateChunk(/*chunk=*/bottom_part.transactions, /*query=*/dep_data.child, + /*chunk_rep=*/top_rep, /*dep_change=*/top_part); + // Make active. + dep_data.active = true; + dep_data.top_setinfo = top_part; + return top_rep; } - /** Determine how many chunks remain in the linearization. */ - DepGraphIndex NumChunksLeft() const noexcept { return m_chunks.size() - m_chunks_skip; } - - /** Access a chunk. Chunk 0 is the highest-feerate prefix of what remains. */ - const SetInfo& GetChunk(DepGraphIndex n) const noexcept + /** Make a specified active dependency inactive. */ + void Deactivate(DepIdx dep_idx) noexcept { - Assume(n + m_chunks_skip < m_chunks.size()); - return m_chunks[n + m_chunks_skip]; + auto& dep_data = m_dep_data[dep_idx]; + Assume(dep_data.active); + auto& parent_tx_data = m_tx_data[dep_data.parent]; + // Make inactive. + dep_data.active = false; + // Update representatives. + auto& chunk_data = m_tx_data[parent_tx_data.chunk_rep]; + m_cost += chunk_data.chunk_setinfo.transactions.Count(); + auto top_part = dep_data.top_setinfo; + auto bottom_part = chunk_data.chunk_setinfo - top_part; + TxIdx bottom_rep = dep_data.child; + auto& bottom_chunk_data = m_tx_data[bottom_rep]; + bottom_chunk_data.chunk_setinfo = bottom_part; + TxIdx top_rep = dep_data.parent; + auto& top_chunk_data = m_tx_data[top_rep]; + top_chunk_data.chunk_setinfo = top_part; + + // See the comment above in Activate(). We perform the opposite operations here, + // removing instead of adding. + // + // Let UpdateChunk traverse the old parent chunk top_part, and remove bottom_part from + // every dependency's top_set which has the parent in it. At the same time, change the + // representative of each of these transactions to be top_rep. + UpdateChunk(/*chunk=*/top_part.transactions, /*query=*/dep_data.parent, + /*chunk_rep=*/top_rep, /*dep_change=*/bottom_part); + // Let UpdateChunk traverse the old child chunk bottom_part, and remove top_part from every + // dependency's top_set which has the child in it. At the same time, change the + // representative of each of these transactions to be bottom_rep. + UpdateChunk(/*chunk=*/bottom_part.transactions, /*query=*/dep_data.child, + /*chunk_rep=*/bottom_rep, /*dep_change=*/top_part); } - /** Remove some subset of transactions from the linearization. */ - void MarkDone(SetType subset) noexcept + /** Activate a dependency from the chunk represented by bottom_rep to the chunk represented by + * top_rep, which must exist. Return the representative of the merged chunk. */ + TxIdx MergeChunks(TxIdx top_rep, TxIdx bottom_rep) noexcept { - Assume(subset.Any()); - Assume(subset.IsSubsetOf(m_todo)); - m_todo -= subset; - if (GetChunk(0).transactions == subset) { - // If the newly done transactions exactly match the first chunk of the remainder of - // the linearization, we do not need to rechunk; just remember to skip one - // additional chunk. - ++m_chunks_skip; - // With subset marked done, some prefix of m_linearization will be done now. How long - // that prefix is depends on how many done elements were interspersed with subset, - // but at least as many transactions as there are in subset. - m_linearization = m_linearization.subspan(subset.Count()); - } else { - // Otherwise rechunk what remains of m_linearization. - m_chunks.clear(); - m_chunks_skip = 0; - BuildChunks(); + auto& top_chunk = m_tx_data[top_rep]; + Assume(top_chunk.chunk_rep == top_rep); + auto& bottom_chunk = m_tx_data[bottom_rep]; + Assume(bottom_chunk.chunk_rep == bottom_rep); + // Count the number of dependencies between bottom_chunk and top_chunk. + TxIdx num_deps{0}; + for (auto tx : top_chunk.chunk_setinfo.transactions) { + auto& tx_data = m_tx_data[tx]; + num_deps += (tx_data.children & bottom_chunk.chunk_setinfo.transactions).Count(); } + Assume(num_deps > 0); + // Uniformly randomly pick one of them and activate it. + TxIdx pick = m_rng.randrange(num_deps); + for (auto tx : top_chunk.chunk_setinfo.transactions) { + auto& tx_data = m_tx_data[tx]; + auto intersect = tx_data.children & bottom_chunk.chunk_setinfo.transactions; + auto count = intersect.Count(); + if (pick < count) { + for (auto dep : tx_data.child_deps) { + auto& dep_data = m_dep_data[dep]; + if (bottom_chunk.chunk_setinfo.transactions[dep_data.child]) { + if (pick == 0) return Activate(dep); + --pick; + } + } + break; + } + pick -= count; + } + Assume(false); + return TxIdx(-1); } - /** Find the shortest intersection between subset and the prefixes of remaining chunks - * of the linearization that has a feerate not below subset's. - * - * This is a crucial operation in guaranteeing improvements to linearizations. If subset has - * a feerate not below GetChunk(0)'s, then moving IntersectPrefixes(subset) to the front of - * (what remains of) the linearization is guaranteed not to make it worse at any point. - * - * See https://delvingbitcoin.org/t/introduction-to-cluster-linearization/1032 for background. - */ - SetInfo IntersectPrefixes(const SetInfo& subset) const noexcept + /** Perform an upward or downward merge step, on the specified chunk representative. Returns + * the representative of the merged chunk, or TxIdx(-1) if no merge took place. */ + template + TxIdx MergeStep(TxIdx chunk_rep) noexcept { - Assume(subset.transactions.IsSubsetOf(m_todo)); - SetInfo accumulator; - // Iterate over all chunks of the remaining linearization. - for (DepGraphIndex i = 0; i < NumChunksLeft(); ++i) { - // Find what (if any) intersection the chunk has with subset. - const SetType to_add = GetChunk(i).transactions & subset.transactions; - if (to_add.Any()) { - // If adding that to accumulator makes us hit all of subset, we are done as no - // shorter intersection with higher/equal feerate exists. - accumulator.transactions |= to_add; - if (accumulator.transactions == subset.transactions) break; - // Otherwise update the accumulator feerate. - accumulator.feerate += m_depgraph.FeeRate(to_add); - // If that does result in something better, or something with the same feerate but - // smaller, return that. Even if a longer, higher-feerate intersection exists, it - // does not hurt to return the shorter one (the remainder of the longer intersection - // will generally be found in the next call to Intersect, but even if not, it is not - // required for the improvement guarantee this function makes). - if (!(accumulator.feerate << subset.feerate)) return accumulator; + /** Information about the chunk that tx_idx is currently in. */ + auto& chunk_data = m_tx_data[chunk_rep]; + SetType chunk_txn = chunk_data.chunk_setinfo.transactions; + // Iterate over all transactions in the chunk, figuring out which other chunk each + // depends on, but only testing each other chunk once. For those depended-on chunks, + // remember the highest-feerate (if DownWard) or lowest-feerate (if !DownWard) one. + // If multiple equal-feerate candidate chunks to merge with exist, pick a random one + // among them. + + /** Which transactions have been reached from this chunk already. Initialize with the + * chunk itself, so internal dependencies within the chunk are ignored. */ + SetType explored = chunk_txn; + /** The minimum feerate (if downward) or maximum feerate (if upward) to consider when + * looking for candidate chunks to merge with. Initially, this is the original chunk's + * feerate, but is updated to be the current best candidate whenever one is found. */ + FeeFrac best_other_chunk_feerate = chunk_data.chunk_setinfo.feerate; + /** The representative for the best candidate chunk to merge with. -1 if none. */ + TxIdx best_other_chunk_rep = TxIdx(-1); + /** We generate random tiebreak values to pick between equal-feerate candidate chunks. + * This variable stores the tiebreak of the current best candidate. */ + uint64_t best_other_chunk_tiebreak{0}; + for (auto tx : chunk_txn) { + auto& tx_data = m_tx_data[tx]; + /** The transactions reached by following dependencies from tx that have not been + * explored before. */ + auto newly_reached = (DownWard ? tx_data.children : tx_data.parents) - explored; + explored |= newly_reached; + while (newly_reached.Any()) { + // Find a chunk inside newly_reached, and remove it from newly_reached. + auto reached_chunk_rep = m_tx_data[newly_reached.First()].chunk_rep; + auto& reached_chunk = m_tx_data[reached_chunk_rep].chunk_setinfo; + newly_reached -= reached_chunk.transactions; + // See if it has an acceptable feerate. + auto cmp = DownWard ? FeeRateCompare(best_other_chunk_feerate, reached_chunk.feerate) + : FeeRateCompare(reached_chunk.feerate, best_other_chunk_feerate); + if (cmp > 0) continue; + uint64_t tiebreak = m_rng.rand64(); + if (cmp < 0 || tiebreak >= best_other_chunk_tiebreak) { + best_other_chunk_feerate = reached_chunk.feerate; + best_other_chunk_rep = reached_chunk_rep; + best_other_chunk_tiebreak = tiebreak; + } } } - return subset; + // Stop if there are no candidate chunks to merge with. + if (best_other_chunk_rep == TxIdx(-1)) return TxIdx(-1); + if constexpr (DownWard) { + chunk_rep = MergeChunks(chunk_rep, best_other_chunk_rep); + } else { + chunk_rep = MergeChunks(best_other_chunk_rep, chunk_rep); + } + Assume(chunk_rep != TxIdx(-1)); + return chunk_rep; } -}; -/** Class encapsulating the state needed to find the best remaining ancestor set. - * - * It is initialized for an entire DepGraph, and parts of the graph can be dropped by calling - * MarkDone. - * - * As long as any part of the graph remains, FindCandidateSet() can be called which will return a - * SetInfo with the highest-feerate ancestor set that remains (an ancestor set is a single - * transaction together with all its remaining ancestors). - */ -template -class AncestorCandidateFinder -{ - /** Internal dependency graph. */ - const DepGraph& m_depgraph; - /** Which transaction are left to include. */ - SetType m_todo; - /** Precomputed ancestor-set feerates (only kept up-to-date for indices in m_todo). */ - std::vector m_ancestor_set_feerates; -public: - /** Construct an AncestorCandidateFinder for a given cluster. - * - * Complexity: O(N^2) where N=depgraph.TxCount(). - */ - AncestorCandidateFinder(const DepGraph& depgraph LIFETIMEBOUND) noexcept : - m_depgraph(depgraph), - m_todo{depgraph.Positions()}, - m_ancestor_set_feerates(depgraph.PositionRange()) + /** Perform an upward or downward merge sequence on the specified transaction. */ + template + void MergeSequence(TxIdx tx_idx) noexcept { - // Precompute ancestor-set feerates. - for (DepGraphIndex i : m_depgraph.Positions()) { - /** The remaining ancestors for transaction i. */ - SetType anc_to_add = m_depgraph.Ancestors(i); - FeeFrac anc_feerate; - // Reuse accumulated feerate from first ancestor, if usable. - Assume(anc_to_add.Any()); - DepGraphIndex first = anc_to_add.First(); - if (first < i) { - anc_feerate = m_ancestor_set_feerates[first]; - Assume(!anc_feerate.IsEmpty()); - anc_to_add -= m_depgraph.Ancestors(first); - } - // Add in other ancestors (which necessarily include i itself). - Assume(anc_to_add[i]); - anc_feerate += m_depgraph.FeeRate(anc_to_add); - // Store the result. - m_ancestor_set_feerates[i] = anc_feerate; + auto chunk_rep = m_tx_data[tx_idx].chunk_rep; + while (true) { + auto merged_rep = MergeStep(chunk_rep); + if (merged_rep == TxIdx(-1)) break; + chunk_rep = merged_rep; } + // Add the chunk to the queue of improvable chunks. + m_suboptimal_chunks.push_back(chunk_rep); } - /** Remove a set of transactions from the set of to-be-linearized ones. - * - * The same transaction may not be MarkDone()'d twice. - * - * Complexity: O(N*M) where N=depgraph.TxCount(), M=select.Count(). - */ - void MarkDone(SetType select) noexcept + /** Split a chunk, and then merge the resulting two chunks to make the graph topological + * again. */ + void Improve(DepIdx dep_idx) noexcept + { + auto& dep_data = m_dep_data[dep_idx]; + Assume(dep_data.active); + // Deactivate the specified dependency, splitting it into two new chunks: a top containing + // the parent, and a bottom containing the child. The top should have a higher feerate. + Deactivate(dep_idx); + + // At this point we have exactly two chunks which may violate topology constraints (the + // parent chunk and child chunk that were produced by deactivating dep_idx). We can fix + // these using just merge sequences, one upwards and one downwards, avoiding the need for a + // full MakeTopological. + + // Merge the top chunk with lower-feerate chunks it depends on (which may be the bottom it + // was just split from, or other pre-existing chunks). + MergeSequence(dep_data.parent); + // Merge the bottom chunk with higher-feerate chunks that depend on it. + MergeSequence(dep_data.child); + } + +public: + /** Construct a spanning forest for the given DepGraph, with every transaction in its own chunk + * (not topological). */ + explicit SpanningForestState(const DepGraph& depgraph, uint64_t rng_seed) noexcept : m_rng(rng_seed) { - Assume(select.Any()); - Assume(select.IsSubsetOf(m_todo)); - m_todo -= select; - for (auto i : select) { - auto feerate = m_depgraph.FeeRate(i); - for (auto j : m_depgraph.Descendants(i) & m_todo) { - m_ancestor_set_feerates[j] -= feerate; + m_transaction_idxs = depgraph.Positions(); + auto num_transactions = m_transaction_idxs.Count(); + m_tx_data.resize(depgraph.PositionRange()); + // Reserve the maximum number of (reserved) dependencies the cluster can have, so + // m_dep_data won't need any reallocations during construction. For a cluster with N + // transactions, the worst case consists of two sets of transactions, the parents and the + // children, where each child depends on each parent and nothing else. For even N, both + // sets can be sized N/2, which means N^2/4 dependencies. For odd N, one can be (N + 1)/2 + // and the other can be (N - 1)/2, meaning (N^2 - 1)/4 dependencies. Because N^2 is odd in + // this case, N^2/4 (with rounding-down division) is the correct value in both cases. + m_dep_data.reserve((num_transactions * num_transactions) / 4); + for (auto tx : m_transaction_idxs) { + // Fill in transaction data. + auto& tx_data = m_tx_data[tx]; + tx_data.chunk_rep = tx; + tx_data.chunk_setinfo.transactions = SetType::Singleton(tx); + tx_data.chunk_setinfo.feerate = depgraph.FeeRate(tx); + // Add its dependencies. + SetType parents = depgraph.GetReducedParents(tx); + for (auto par : parents) { + auto& par_tx_data = m_tx_data[par]; + auto dep_idx = m_dep_data.size(); + // Construct new dependency. + auto& dep = m_dep_data.emplace_back(); + dep.active = false; + dep.parent = par; + dep.child = tx; + // Add it as parent of the child. + tx_data.parents.Set(par); + // Add it as child of the parent. + par_tx_data.child_deps.push_back(dep_idx); + par_tx_data.children.Set(tx); } } } - /** Check whether any unlinearized transactions remain. */ - bool AllDone() const noexcept + /** Load an existing linearization. Must be called immediately after constructor. The result is + * topological if the linearization is valid. Otherwise, MakeTopological still needs to be + * called. */ + void LoadLinearization(std::span old_linearization) noexcept { - return m_todo.None(); + // Add transactions one by one, in order of existing linearization. + for (DepGraphIndex tx : old_linearization) { + auto chunk_rep = m_tx_data[tx].chunk_rep; + // Merge the chunk upwards, as long as merging succeeds. + while (true) { + chunk_rep = MergeStep(chunk_rep); + if (chunk_rep == TxIdx(-1)) break; + } + } } - /** Count the number of remaining unlinearized transactions. */ - DepGraphIndex NumRemaining() const noexcept + /** Make state topological. Can be called after constructing, or after LoadLinearization. */ + void MakeTopological() noexcept { - return m_todo.Count(); + for (auto tx : m_transaction_idxs) { + auto& tx_data = m_tx_data[tx]; + if (tx_data.chunk_rep == tx) { + m_suboptimal_chunks.emplace_back(tx); + // Randomize the initial order of suboptimal chunks in the queue. + TxIdx j = m_rng.randrange(m_suboptimal_chunks.size()); + if (j != m_suboptimal_chunks.size() - 1) { + std::swap(m_suboptimal_chunks.back(), m_suboptimal_chunks[j]); + } + } + } + while (!m_suboptimal_chunks.empty()) { + // Pop an entry from the potentially-suboptimal chunk queue. + TxIdx chunk = m_suboptimal_chunks.front(); + m_suboptimal_chunks.pop_front(); + auto& chunk_data = m_tx_data[chunk]; + // If what was popped is not currently a chunk representative, continue. This may + // happen when it was merged with something else since being added. + if (chunk_data.chunk_rep != chunk) continue; + int flip = m_rng.randbool(); + for (int i = 0; i < 2; ++i) { + if (i ^ flip) { + // Attempt to merge the chunk upwards. + auto result_up = MergeStep(chunk); + if (result_up != TxIdx(-1)) { + m_suboptimal_chunks.push_back(result_up); + break; + } + } else { + // Attempt to merge the chunk downwards. + auto result_down = MergeStep(chunk); + if (result_down != TxIdx(-1)) { + m_suboptimal_chunks.push_back(result_down); + break; + } + } + } + } } - /** Find the best (highest-feerate, smallest among those in case of a tie) ancestor set - * among the remaining transactions. Requires !AllDone(). - * - * Complexity: O(N) where N=depgraph.TxCount(); - */ - SetInfo FindCandidateSet() const noexcept + /** Initialize the data structure for optimization. It must be topological already. */ + void StartOptimizing() noexcept { - Assume(!AllDone()); - std::optional best; - for (auto i : m_todo) { - if (best.has_value()) { - Assume(!m_ancestor_set_feerates[i].IsEmpty()); - if (!(m_ancestor_set_feerates[i] > m_ancestor_set_feerates[*best])) continue; + // Mark chunks suboptimal. + for (auto tx : m_transaction_idxs) { + auto& tx_data = m_tx_data[tx]; + if (tx_data.chunk_rep == tx) { + m_suboptimal_chunks.push_back(tx); + // Randomize the initial order of suboptimal chunks in the queue. + TxIdx j = m_rng.randrange(m_suboptimal_chunks.size()); + if (j != m_suboptimal_chunks.size() - 1) { + std::swap(m_suboptimal_chunks.back(), m_suboptimal_chunks[j]); + } } - best = i; } - Assume(best.has_value()); - return {m_depgraph.Ancestors(*best) & m_todo, m_ancestor_set_feerates[*best]}; } -}; -/** Class encapsulating the state needed to perform search for good candidate sets. - * - * It is initialized for an entire DepGraph, and parts of the graph can be dropped by calling - * MarkDone(). - * - * As long as any part of the graph remains, FindCandidateSet() can be called to perform a search - * over the set of topologically-valid subsets of that remainder, with a limit on how many - * combinations are tried. - */ -template -class SearchCandidateFinder -{ - /** Internal RNG. */ - InsecureRandomContext m_rng; - /** m_sorted_to_original[i] is the original position that sorted transaction position i had. */ - std::vector m_sorted_to_original; - /** m_original_to_sorted[i] is the sorted position original transaction position i has. */ - std::vector m_original_to_sorted; - /** Internal dependency graph for the cluster (with transactions in decreasing individual - * feerate order). */ - DepGraph m_sorted_depgraph; - /** Which transactions are left to do (indices in m_sorted_depgraph's order). */ - SetType m_todo; - - /** Given a set of transactions with sorted indices, get their original indices. */ - SetType SortedToOriginal(const SetType& arg) const noexcept + /** Try to improve the forest. Returns false if it is optimal, true otherwise. */ + bool OptimizeStep() noexcept { - SetType ret; - for (auto pos : arg) ret.Set(m_sorted_to_original[pos]); - return ret; + while (!m_suboptimal_chunks.empty()) { + // Pop an entry from the potentially-suboptimal chunk queue. + TxIdx chunk = m_suboptimal_chunks.front(); + m_suboptimal_chunks.pop_front(); + auto& chunk_data = m_tx_data[chunk]; + // If what was popped is not currently a chunk representative, continue. This may + // happen when a split chunk merges in Improve() with one or more existing chunks that + // are themselves on the suboptimal queue already. + if (chunk_data.chunk_rep != chunk) continue; + // Remember the best dependency seen so far. + DepIdx candidate_dep = DepIdx(-1); + uint64_t candidate_tiebreak = 0; + // Iterate over all transactions. + for (auto tx : chunk_data.chunk_setinfo.transactions) { + const auto& tx_data = m_tx_data[tx]; + // Iterate over all active child dependencies of the transaction. + const auto children = std::span{tx_data.child_deps}; + for (DepIdx dep_idx : children) { + const auto& dep_data = m_dep_data[dep_idx]; + if (!dep_data.active) continue; + // Skip if this dependency is ineligible (the top chunk that would be created + // does not have higher feerate than the chunk it is currently part of). + auto cmp = FeeRateCompare(dep_data.top_setinfo.feerate, chunk_data.chunk_setinfo.feerate); + if (cmp <= 0) continue; + // Generate a random tiebreak for this dependency, and reject it if its tiebreak + // is worse than the best so far. This means that among all eligible + // dependencies, a uniformly random one will be chosen. + uint64_t tiebreak = m_rng.rand64(); + if (tiebreak < candidate_tiebreak) continue; + // Remember this as our (new) candidate dependency. + candidate_dep = dep_idx; + candidate_tiebreak = tiebreak; + } + } + // If a candidate with positive gain was found, deactivate it and then make the state + // topological again with a sequence of merges. + if (candidate_dep != DepIdx(-1)) Improve(candidate_dep); + // Stop processing for now, even if nothing was activated, as the loop above may have + // had a nontrivial cost. + return !m_suboptimal_chunks.empty(); + } + // No improvable chunk was found, we are done. + return false; } - /** Given a set of transactions with original indices, get their sorted indices. */ - SetType OriginalToSorted(const SetType& arg) const noexcept + /** Construct a topologically-valid linearization from the current forest state. Must be + * topological. */ + std::vector GetLinearization() noexcept { - SetType ret; - for (auto pos : arg) ret.Set(m_original_to_sorted[pos]); + /** The output linearization. */ + std::vector ret; + ret.reserve(m_transaction_idxs.Count()); + /** A heap with all chunks (by representative) that can currently be included, sorted by + * chunk feerate and a random tie-breaker. */ + std::vector> ready_chunks; + /** Information about chunks: + * - The first value is only used for chunk representatives, and counts the number of + * unmet dependencies this chunk has on other chunks (not including dependencies within + * the chunk itself). + * - The second value is the number of unmet dependencies overall. + */ + std::vector> chunk_deps(m_tx_data.size(), {0, 0}); + /** The set of all chunk representatives. */ + SetType chunk_reps; + /** A list with all transactions within the current chunk that can be included. */ + std::vector ready_tx; + // Populate chunk_deps[c] with the number of {out-of-chunk dependencies, dependencies} the + // child has. + for (TxIdx chl_idx : m_transaction_idxs) { + const auto& chl_data = m_tx_data[chl_idx]; + chunk_deps[chl_idx].second = chl_data.parents.Count(); + auto chl_chunk_rep = chl_data.chunk_rep; + chunk_reps.Set(chl_chunk_rep); + for (auto par_idx : chl_data.parents) { + auto par_chunk_rep = m_tx_data[par_idx].chunk_rep; + chunk_deps[chl_chunk_rep].first += (par_chunk_rep != chl_chunk_rep); + } + } + // Construct a heap with all chunks that have no out-of-chunk dependencies. + /** Comparison function for the heap. */ + auto chunk_cmp_fn = [&](const std::pair& a, const std::pair& b) noexcept { + auto& chunk_a = m_tx_data[a.first]; + auto& chunk_b = m_tx_data[b.first]; + Assume(chunk_a.chunk_rep == a.first); + Assume(chunk_b.chunk_rep == b.first); + // First sort by chunk feerate. + if (chunk_a.chunk_setinfo.feerate != chunk_b.chunk_setinfo.feerate) { + return chunk_a.chunk_setinfo.feerate < chunk_b.chunk_setinfo.feerate; + } + // Tie-break randomly. + if (a.second != b.second) return a.second < b.second; + // Lastly, tie-break by chunk representative. + return a.first < b.first; + }; + for (TxIdx chunk_rep : chunk_reps) { + if (chunk_deps[chunk_rep].first == 0) ready_chunks.emplace_back(chunk_rep, m_rng.rand64()); + } + std::make_heap(ready_chunks.begin(), ready_chunks.end(), chunk_cmp_fn); + // Pop chunks off the heap, highest-feerate ones first. + while (!ready_chunks.empty()) { + auto [chunk_rep, _rnd] = ready_chunks.front(); + std::pop_heap(ready_chunks.begin(), ready_chunks.end(), chunk_cmp_fn); + ready_chunks.pop_back(); + Assume(m_tx_data[chunk_rep].chunk_rep == chunk_rep); + Assume(chunk_deps[chunk_rep].first == 0); + const auto& chunk_txn = m_tx_data[chunk_rep].chunk_setinfo.transactions; + // Build heap of all includable transactions in chunk. + for (TxIdx tx_idx : chunk_txn) { + if (chunk_deps[tx_idx].second == 0) { + ready_tx.push_back(tx_idx); + } + } + Assume(!ready_tx.empty()); + // Pick transactions from the ready queue, append them to linearization, and decrement + // dependency counts. + while (!ready_tx.empty()) { + // Move a random queue element to the back. + auto pos = m_rng.randrange(ready_tx.size()); + if (pos != ready_tx.size() - 1) std::swap(ready_tx.back(), ready_tx[pos]); + // Pop from the back. + auto tx_idx = ready_tx.back(); + Assume(chunk_txn[tx_idx]); + ready_tx.pop_back(); + // Append to linearization. + ret.push_back(tx_idx); + // Decrement dependency counts. + auto& tx_data = m_tx_data[tx_idx]; + for (TxIdx chl_idx : tx_data.children) { + auto& chl_data = m_tx_data[chl_idx]; + // Decrement tx dependency count. + Assume(chunk_deps[chl_idx].second > 0); + if (--chunk_deps[chl_idx].second == 0 && chunk_txn[chl_idx]) { + // Child tx has no dependencies left, and is in this chunk. Add it to the tx queue. + ready_tx.push_back(chl_idx); + } + // Decrement chunk dependency count if this is out-of-chunk dependency. + if (chl_data.chunk_rep != chunk_rep) { + Assume(chunk_deps[chl_data.chunk_rep].first > 0); + if (--chunk_deps[chl_data.chunk_rep].first == 0) { + // Child chunk has no dependencies left. Add it to the chunk heap. + ready_chunks.emplace_back(chl_data.chunk_rep, m_rng.rand64()); + std::push_heap(ready_chunks.begin(), ready_chunks.end(), chunk_cmp_fn); + } + } + } + } + } + Assume(ret.size() == m_transaction_idxs.Count()); return ret; } -public: - /** Construct a candidate finder for a graph. + /** Get the diagram for the current state, which must be topological. Test-only. * - * @param[in] depgraph Dependency graph for the to-be-linearized cluster. - * @param[in] rng_seed A random seed to control the search order. + * The linearization produced by GetLinearization() is always at least as good (in the + * CompareChunks() sense) as this diagram, but may be better. * - * Complexity: O(N^2) where N=depgraph.Count(). + * After an OptimizeStep(), the diagram will always be at least as good as before. Once + * OptimizeStep() returns false, the diagram will be equivalent to that produced by + * GetLinearization(), and optimal. */ - SearchCandidateFinder(const DepGraph& depgraph, uint64_t rng_seed) noexcept : - m_rng(rng_seed), - m_sorted_to_original(depgraph.TxCount()), - m_original_to_sorted(depgraph.PositionRange()) + std::vector GetDiagram() const noexcept { - // Determine reordering mapping, by sorting by decreasing feerate. Unused positions are - // not included, as they will never be looked up anyway. - DepGraphIndex sorted_pos{0}; - for (auto i : depgraph.Positions()) { - m_sorted_to_original[sorted_pos++] = i; - } - std::sort(m_sorted_to_original.begin(), m_sorted_to_original.end(), [&](auto a, auto b) { - auto feerate_cmp = depgraph.FeeRate(a) <=> depgraph.FeeRate(b); - if (feerate_cmp == 0) return a < b; - return feerate_cmp > 0; - }); - // Compute reverse mapping. - for (DepGraphIndex i = 0; i < m_sorted_to_original.size(); ++i) { - m_original_to_sorted[m_sorted_to_original[i]] = i; + std::vector ret; + for (auto tx : m_transaction_idxs) { + if (m_tx_data[tx].chunk_rep == tx) { + ret.push_back(m_tx_data[tx].chunk_setinfo.feerate); + } } - // Compute reordered dependency graph. - m_sorted_depgraph = DepGraph(depgraph, m_original_to_sorted, m_sorted_to_original.size()); - m_todo = m_sorted_depgraph.Positions(); + std::sort(ret.begin(), ret.end(), std::greater{}); + return ret; } - /** Check whether any unlinearized transactions remain. */ - bool AllDone() const noexcept - { - return m_todo.None(); - } + /** Determine how much work was performed so far. */ + uint64_t GetCost() const noexcept { return m_cost; } - /** Find a high-feerate topologically-valid subset of what remains of the cluster. - * Requires !AllDone(). - * - * @param[in] max_iterations The maximum number of optimization steps that will be performed. - * @param[in] best A set/feerate pair with an already-known good candidate. This may - * be empty. - * @return A pair of: - * - The best (highest feerate, smallest size as tiebreaker) - * topologically valid subset (and its feerate) that was - * encountered during search. It will be at least as good as the - * best passed in (if not empty). - * - The number of optimization steps that were performed. This will - * be <= max_iterations. If strictly < max_iterations, the - * returned subset is optimal. - * - * Complexity: possibly O(N * min(max_iterations, sqrt(2^N))) where N=depgraph.TxCount(). - */ - std::pair, uint64_t> FindCandidateSet(uint64_t max_iterations, SetInfo best) noexcept + /** Verify internal consistency of the data structure. */ + void SanityCheck(const DepGraph& depgraph) const { - Assume(!AllDone()); - - // Convert the provided best to internal sorted indices. - best.transactions = OriginalToSorted(best.transactions); - - /** Type for work queue items. */ - struct WorkItem - { - /** Set of transactions definitely included (and its feerate). This must be a subset - * of m_todo, and be topologically valid (includes all in-m_todo ancestors of - * itself). */ - SetInfo inc; - /** Set of undecided transactions. This must be a subset of m_todo, and have no overlap - * with inc. The set (inc | und) must be topologically valid. */ - SetType und; - /** (Only when inc is not empty) The best feerate of any superset of inc that is also a - * subset of (inc | und), without requiring it to be topologically valid. It forms a - * conservative upper bound on how good a set this work item can give rise to. - * Transactions whose feerate is below best's are ignored when determining this value, - * which means it may technically be an underestimate, but if so, this work item - * cannot result in something that beats best anyway. */ - FeeFrac pot_feerate; - - /** Construct a new work item. */ - WorkItem(SetInfo&& i, SetType&& u, FeeFrac&& p_f) noexcept : - inc(std::move(i)), und(std::move(u)), pot_feerate(std::move(p_f)) - { - Assume(pot_feerate.IsEmpty() == inc.feerate.IsEmpty()); + // + // Verify dependency parent/child information, and build list of (active) dependencies. + // + std::vector> expected_dependencies; + std::vector> all_dependencies; + std::vector> active_dependencies; + for (auto parent_idx : depgraph.Positions()) { + for (auto child_idx : depgraph.GetReducedChildren(parent_idx)) { + expected_dependencies.emplace_back(parent_idx, child_idx); } - - /** Swap two WorkItems. */ - void Swap(WorkItem& other) noexcept - { - swap(inc, other.inc); - swap(und, other.und); - swap(pot_feerate, other.pot_feerate); + } + for (DepIdx dep_idx = 0; dep_idx < m_dep_data.size(); ++dep_idx) { + const auto& dep_data = m_dep_data[dep_idx]; + all_dependencies.emplace_back(dep_data.parent, dep_data.child, dep_idx); + // Also add to active_dependencies if it is active. + if (m_dep_data[dep_idx].active) { + active_dependencies.emplace_back(dep_data.parent, dep_data.child, dep_idx); } - }; - - /** The queue of work items. */ - VecDeque queue; - queue.reserve(std::max(256, 2 * m_todo.Count())); - - // Create initial entries per connected component of m_todo. While clusters themselves are - // generally connected, this is not necessarily true after some parts have already been - // removed from m_todo. Without this, effort can be wasted on searching "inc" sets that - // span multiple components. - auto to_cover = m_todo; - do { - auto component = m_sorted_depgraph.FindConnectedComponent(to_cover); - to_cover -= component; - // If best is not provided, set it to the first component, so that during the work - // processing loop below, and during the add_fn/split_fn calls, we do not need to deal - // with the best=empty case. - if (best.feerate.IsEmpty()) best = SetInfo(m_sorted_depgraph, component); - queue.emplace_back(/*inc=*/SetInfo{}, - /*und=*/std::move(component), - /*pot_feerate=*/FeeFrac{}); - } while (to_cover.Any()); - - /** Local copy of the iteration limit. */ - uint64_t iterations_left = max_iterations; - - /** The set of transactions in m_todo which have feerate > best's. */ - SetType imp = m_todo; - while (imp.Any()) { - DepGraphIndex check = imp.Last(); - if (m_sorted_depgraph.FeeRate(check) >> best.feerate) break; - imp.Reset(check); + } + std::sort(expected_dependencies.begin(), expected_dependencies.end()); + std::sort(all_dependencies.begin(), all_dependencies.end()); + assert(expected_dependencies.size() == all_dependencies.size()); + for (size_t i = 0; i < expected_dependencies.size(); ++i) { + assert(expected_dependencies[i] == + std::make_pair(std::get<0>(all_dependencies[i]), + std::get<1>(all_dependencies[i]))); } - /** Internal function to add an item to the queue of elements to explore if there are any - * transactions left to split on, possibly improving it before doing so, and to update - * best/imp. - * - * - inc: the "inc" value for the new work item (must be topological). - * - und: the "und" value for the new work item ((inc | und) must be topological). - */ - auto add_fn = [&](SetInfo inc, SetType und) noexcept { - /** SetInfo object with the set whose feerate will become the new work item's - * pot_feerate. It starts off equal to inc. */ - auto pot = inc; - if (!inc.feerate.IsEmpty()) { - // Add entries to pot. We iterate over all undecided transactions whose feerate is - // higher than best. While undecided transactions of lower feerate may improve pot, - // the resulting pot feerate cannot possibly exceed best's (and this item will be - // skipped in split_fn anyway). - for (auto pos : imp & und) { - // Determine if adding transaction pos to pot (ignoring topology) would improve - // it. If not, we're done updating pot. This relies on the fact that - // m_sorted_depgraph, and thus the transactions iterated over, are in decreasing - // individual feerate order. - if (!(m_sorted_depgraph.FeeRate(pos) >> pot.feerate)) break; - pot.Set(m_sorted_depgraph, pos); - } - - // The "jump ahead" optimization: whenever pot has a topologically-valid subset, - // that subset can be added to inc. Any subset of (pot - inc) has the property that - // its feerate exceeds that of any set compatible with this work item (superset of - // inc, subset of (inc | und)). Thus, if T is a topological subset of pot, and B is - // the best topologically-valid set compatible with this work item, and (T - B) is - // non-empty, then (T | B) is better than B and also topological. This is in - // contradiction with the assumption that B is best. Thus, (T - B) must be empty, - // or T must be a subset of B. - // - // See https://delvingbitcoin.org/t/how-to-linearize-your-cluster/303 section 2.4. - const auto init_inc = inc.transactions; - for (auto pos : pot.transactions - inc.transactions) { - // If the transaction's ancestors are a subset of pot, we can add it together - // with its ancestors to inc. Just update the transactions here; the feerate - // update happens below. - auto anc_todo = m_sorted_depgraph.Ancestors(pos) & m_todo; - if (anc_todo.IsSubsetOf(pot.transactions)) inc.transactions |= anc_todo; + // + // Verify the chunks against the list of active dependencies + // + for (auto tx_idx: depgraph.Positions()) { + // Only process chunks for now. + if (m_tx_data[tx_idx].chunk_rep == tx_idx) { + const auto& chunk_data = m_tx_data[tx_idx]; + // Verify that transactions in the chunk point back to it. This guarantees + // that chunks are non-overlapping. + for (auto chunk_tx : chunk_data.chunk_setinfo.transactions) { + assert(m_tx_data[chunk_tx].chunk_rep == tx_idx); } - // Finally update und and inc's feerate to account for the added transactions. - und -= inc.transactions; - inc.feerate += m_sorted_depgraph.FeeRate(inc.transactions - init_inc); - - // If inc's feerate is better than best's, remember it as our new best. - if (inc.feerate > best.feerate) { - best = inc; - // See if we can remove any entries from imp now. - while (imp.Any()) { - DepGraphIndex check = imp.Last(); - if (m_sorted_depgraph.FeeRate(check) >> best.feerate) break; - imp.Reset(check); + // Verify the chunk's transaction set: it must contain the representative, and for + // every active dependency, if it contains the parent or child, it must contain + // both. It must have exactly N-1 active dependencies in it, guaranteeing it is + // acyclic. + SetType expected_chunk = SetType::Singleton(tx_idx); + while (true) { + auto old = expected_chunk; + size_t active_dep_count{0}; + for (const auto& [par, chl, _dep] : active_dependencies) { + if (expected_chunk[par] || expected_chunk[chl]) { + expected_chunk.Set(par); + expected_chunk.Set(chl); + ++active_dep_count; + } + } + if (old == expected_chunk) { + assert(expected_chunk.Count() == active_dep_count + 1); + break; } } - - // If no potential transactions exist beyond the already included ones, no - // improvement is possible anymore. - if (pot.feerate.size == inc.feerate.size) return; - // At this point und must be non-empty. If it were empty then pot would equal inc. - Assume(und.Any()); - } else { - Assume(inc.transactions.None()); - // If inc is empty, we just make sure there are undecided transactions left to - // split on. - if (und.None()) return; - } - - // Actually construct a new work item on the queue. Due to the switch to DFS when queue - // space runs out (see below), we know that no reallocation of the queue should ever - // occur. - Assume(queue.size() < queue.capacity()); - queue.emplace_back(/*inc=*/std::move(inc), - /*und=*/std::move(und), - /*pot_feerate=*/std::move(pot.feerate)); - }; - - /** Internal process function. It takes an existing work item, and splits it in two: one - * with a particular transaction (and its ancestors) included, and one with that - * transaction (and its descendants) excluded. */ - auto split_fn = [&](WorkItem&& elem) noexcept { - // Any queue element must have undecided transactions left, otherwise there is nothing - // to explore anymore. - Assume(elem.und.Any()); - // The included and undecided set are all subsets of m_todo. - Assume(elem.inc.transactions.IsSubsetOf(m_todo) && elem.und.IsSubsetOf(m_todo)); - // Included transactions cannot be undecided. - Assume(!elem.inc.transactions.Overlaps(elem.und)); - // If pot is empty, then so is inc. - Assume(elem.inc.feerate.IsEmpty() == elem.pot_feerate.IsEmpty()); - - const DepGraphIndex first = elem.und.First(); - if (!elem.inc.feerate.IsEmpty()) { - // If no undecided transactions remain with feerate higher than best, this entry - // cannot be improved beyond best. - if (!elem.und.Overlaps(imp)) return; - // We can ignore any queue item whose potential feerate isn't better than the best - // seen so far. - if (elem.pot_feerate <= best.feerate) return; - } else { - // In case inc is empty use a simpler alternative check. - if (m_sorted_depgraph.FeeRate(first) <= best.feerate) return; + assert(chunk_data.chunk_setinfo.transactions == expected_chunk); + // Verify the chunk's feerate. + assert(chunk_data.chunk_setinfo.feerate == + depgraph.FeeRate(chunk_data.chunk_setinfo.transactions)); } + } - // Decide which transaction to split on. Splitting is how new work items are added, and - // how progress is made. One split transaction is chosen among the queue item's - // undecided ones, and: - // - A work item is (potentially) added with that transaction plus its remaining - // descendants excluded (removed from the und set). - // - A work item is (potentially) added with that transaction plus its remaining - // ancestors included (added to the inc set). - // - // To decide what to split on, consider the undecided ancestors of the highest - // individual feerate undecided transaction. Pick the one which reduces the search space - // most. Let I(t) be the size of the undecided set after including t, and E(t) the size - // of the undecided set after excluding t. Then choose the split transaction t such - // that 2^I(t) + 2^E(t) is minimal, tie-breaking by highest individual feerate for t. - DepGraphIndex split = 0; - const auto select = elem.und & m_sorted_depgraph.Ancestors(first); - Assume(select.Any()); - std::optional> split_counts; - for (auto t : select) { - // Call max = max(I(t), E(t)) and min = min(I(t), E(t)). Let counts = {max,min}. - // Sorting by the tuple counts is equivalent to sorting by 2^I(t) + 2^E(t). This - // expression is equal to 2^max + 2^min = 2^max * (1 + 1/2^(max - min)). The second - // factor (1 + 1/2^(max - min)) there is in (1,2]. Thus increasing max will always - // increase it, even when min decreases. Because of this, we can first sort by max. - std::pair counts{ - (elem.und - m_sorted_depgraph.Ancestors(t)).Count(), - (elem.und - m_sorted_depgraph.Descendants(t)).Count()}; - if (counts.first < counts.second) std::swap(counts.first, counts.second); - // Remember the t with the lowest counts. - if (!split_counts.has_value() || counts < *split_counts) { - split = t; - split_counts = counts; + // + // Verify other transaction data. + // + assert(m_transaction_idxs == depgraph.Positions()); + for (auto tx_idx : m_transaction_idxs) { + const auto& tx_data = m_tx_data[tx_idx]; + // Verify it has a valid chunk representative, and that chunk includes this + // transaction. + assert(m_tx_data[tx_data.chunk_rep].chunk_rep == tx_data.chunk_rep); + assert(m_tx_data[tx_data.chunk_rep].chunk_setinfo.transactions[tx_idx]); + // Verify parents/children. + assert(tx_data.parents == depgraph.GetReducedParents(tx_idx)); + assert(tx_data.children == depgraph.GetReducedChildren(tx_idx)); + // Verify list of child dependencies. + std::vector expected_child_deps; + for (const auto& [par_idx, chl_idx, dep_idx] : all_dependencies) { + if (tx_idx == par_idx) { + assert(tx_data.children[chl_idx]); + expected_child_deps.push_back(dep_idx); } } - // Since there was at least one transaction in select, we must always find one. - Assume(split_counts.has_value()); - - // Add a work item corresponding to exclusion of the split transaction. - const auto& desc = m_sorted_depgraph.Descendants(split); - add_fn(/*inc=*/elem.inc, - /*und=*/elem.und - desc); - - // Add a work item corresponding to inclusion of the split transaction. - const auto anc = m_sorted_depgraph.Ancestors(split) & m_todo; - add_fn(/*inc=*/elem.inc.Add(m_sorted_depgraph, anc), - /*und=*/elem.und - anc); - - // Account for the performed split. - --iterations_left; - }; + std::sort(expected_child_deps.begin(), expected_child_deps.end()); + auto child_deps_copy = tx_data.child_deps; + std::sort(child_deps_copy.begin(), child_deps_copy.end()); + assert(expected_child_deps == child_deps_copy); + } - // Work processing loop. - // - // New work items are always added at the back of the queue, but items to process use a - // hybrid approach where they can be taken from the front or the back. // - // Depth-first search (DFS) corresponds to always taking from the back of the queue. This - // is very memory-efficient (linear in the number of transactions). Breadth-first search - // (BFS) corresponds to always taking from the front, which potentially uses more memory - // (up to exponential in the transaction count), but seems to work better in practice. + // Verify active dependencies' top_setinfo. // - // The approach here combines the two: use BFS (plus random swapping) until the queue grows - // too large, at which point we temporarily switch to DFS until the size shrinks again. - while (!queue.empty()) { - // Randomly swap the first two items to randomize the search order. - if (queue.size() > 1 && m_rng.randbool()) { - queue[0].Swap(queue[1]); - } - - // Processing the first queue item, and then using DFS for everything it gives rise to, - // may increase the queue size by the number of undecided elements in there, minus 1 - // for the first queue item being removed. Thus, only when that pushes the queue over - // its capacity can we not process from the front (BFS), and should we use DFS. - while (queue.size() - 1 + queue.front().und.Count() > queue.capacity()) { - if (!iterations_left) break; - auto elem = queue.back(); - queue.pop_back(); - split_fn(std::move(elem)); + for (const auto& [par_idx, chl_idx, dep_idx] : active_dependencies) { + const auto& dep_data = m_dep_data[dep_idx]; + // Verify the top_info's transactions: it must contain the parent, and for every + // active dependency, except dep_idx itself, if it contains the parent or child, it + // must contain both. + SetType expected_top = SetType::Singleton(par_idx); + while (true) { + auto old = expected_top; + for (const auto& [par2_idx, chl2_idx, dep2_idx] : active_dependencies) { + if (dep2_idx != dep_idx && (expected_top[par2_idx] || expected_top[chl2_idx])) { + expected_top.Set(par2_idx); + expected_top.Set(chl2_idx); + } + } + if (old == expected_top) break; } - - // Process one entry from the front of the queue (BFS exploration) - if (!iterations_left) break; - auto elem = queue.front(); - queue.pop_front(); - split_fn(std::move(elem)); + assert(!expected_top[chl_idx]); + assert(dep_data.top_setinfo.transactions == expected_top); + // Verify the top_info's feerate. + assert(dep_data.top_setinfo.feerate == + depgraph.FeeRate(dep_data.top_setinfo.transactions)); } - // Return the found best set (converted to the original transaction indices), and the - // number of iterations performed. - best.transactions = SortedToOriginal(best.transactions); - return {std::move(best), max_iterations - iterations_left}; - } - - /** Remove a subset of transactions from the cluster being linearized. - * - * Complexity: O(N) where N=done.Count(). - */ - void MarkDone(const SetType& done) noexcept - { - const auto done_sorted = OriginalToSorted(done); - Assume(done_sorted.Any()); - Assume(done_sorted.IsSubsetOf(m_todo)); - m_todo -= done_sorted; + // + // Verify m_suboptimal_chunks. + // + for (size_t i = 0; i < m_suboptimal_chunks.size(); ++i) { + auto tx_idx = m_suboptimal_chunks[i]; + assert(m_transaction_idxs[tx_idx]); + } } }; /** Find or improve a linearization for a cluster. * * @param[in] depgraph Dependency graph of the cluster to be linearized. - * @param[in] max_iterations Upper bound on the number of optimization steps that will be done. + * @param[in] max_iterations Upper bound on the amount of work that will be done. * @param[in] rng_seed A random number seed to control search order. This prevents peers * from predicting exactly which clusters would be hard for us to * linearize. @@ -1048,85 +1346,30 @@ class SearchCandidateFinder * - A boolean indicating whether the result is guaranteed to be * optimal. * - How many optimization steps were actually performed. - * - * Complexity: possibly O(N * min(max_iterations + N, sqrt(2^N))) where N=depgraph.TxCount(). */ template std::tuple, bool, uint64_t> Linearize(const DepGraph& depgraph, uint64_t max_iterations, uint64_t rng_seed, std::span old_linearization = {}) noexcept { - Assume(old_linearization.empty() || old_linearization.size() == depgraph.TxCount()); - if (depgraph.TxCount() == 0) return {{}, true, 0}; - - uint64_t iterations_left = max_iterations; - std::vector linearization; - - AncestorCandidateFinder anc_finder(depgraph); - std::optional> src_finder; - linearization.reserve(depgraph.TxCount()); - bool optimal = true; - - // Treat the initialization of SearchCandidateFinder as taking N^2/64 (rounded up) iterations - // (largely due to the cost of constructing the internal sorted-by-feerate DepGraph inside - // SearchCandidateFinder), a rough approximation based on benchmark. If we don't have that - // many, don't start it. - uint64_t start_iterations = (uint64_t{depgraph.TxCount()} * depgraph.TxCount() + 63) / 64; - if (iterations_left > start_iterations) { - iterations_left -= start_iterations; - src_finder.emplace(depgraph, rng_seed); + /** Initialize a spanning forest data structure for this cluster. */ + SpanningForestState forest(depgraph, rng_seed); + if (!old_linearization.empty()) { + forest.LoadLinearization(old_linearization); + } else { + forest.MakeTopological(); } - - /** Chunking of what remains of the old linearization. */ - LinearizationChunking old_chunking(depgraph, old_linearization); - - while (true) { - // Find the highest-feerate prefix of the remainder of old_linearization. - SetInfo best_prefix; - if (old_chunking.NumChunksLeft()) best_prefix = old_chunking.GetChunk(0); - - // Then initialize best to be either the best remaining ancestor set, or the first chunk. - auto best = anc_finder.FindCandidateSet(); - if (!best_prefix.feerate.IsEmpty() && best_prefix.feerate >= best.feerate) best = best_prefix; - - uint64_t iterations_done_now = 0; - uint64_t max_iterations_now = 0; - if (src_finder) { - // Treat the invocation of SearchCandidateFinder::FindCandidateSet() as costing N/4 - // up-front (rounded up) iterations (largely due to the cost of connected-component - // splitting), a rough approximation based on benchmarks. - uint64_t base_iterations = (anc_finder.NumRemaining() + 3) / 4; - if (iterations_left > base_iterations) { - // Invoke bounded search to update best, with up to half of our remaining - // iterations as limit. - iterations_left -= base_iterations; - max_iterations_now = (iterations_left + 1) / 2; - std::tie(best, iterations_done_now) = src_finder->FindCandidateSet(max_iterations_now, best); - iterations_left -= iterations_done_now; - } - } - - if (iterations_done_now == max_iterations_now) { - optimal = false; - // If the search result is not (guaranteed to be) optimal, run intersections to make - // sure we don't pick something that makes us unable to reach further diagram points - // of the old linearization. - if (old_chunking.NumChunksLeft() > 0) { - best = old_chunking.IntersectPrefixes(best); + // Make improvement steps to it until we hit the max_iterations limit, or an optimal result + // is found. + bool optimal = false; + if (forest.GetCost() < max_iterations) { + forest.StartOptimizing(); + do { + if (!forest.OptimizeStep()) { + optimal = true; + break; } - } - - // Add to output in topological order. - depgraph.AppendTopo(linearization, best.transactions); - - // Update state to reflect best is no longer to be linearized. - anc_finder.MarkDone(best.transactions); - if (anc_finder.AllDone()) break; - if (src_finder) src_finder->MarkDone(best.transactions); - if (old_chunking.NumChunksLeft() > 0) { - old_chunking.MarkDone(best.transactions); - } + } while (forest.GetCost() < max_iterations); } - - return {std::move(linearization), optimal, max_iterations - iterations_left}; + return {forest.GetLinearization(), optimal, forest.GetCost()}; } /** Improve a given linearization. @@ -1330,48 +1573,6 @@ void PostLinearize(const DepGraph& depgraph, std::span l } } -/** Merge two linearizations for the same cluster into one that is as good as both. - * - * Complexity: O(N^2) where N=depgraph.TxCount(); O(N) if both inputs are identical. - */ -template -std::vector MergeLinearizations(const DepGraph& depgraph, std::span lin1, std::span lin2) -{ - Assume(lin1.size() == depgraph.TxCount()); - Assume(lin2.size() == depgraph.TxCount()); - - /** Chunkings of what remains of both input linearizations. */ - LinearizationChunking chunking1(depgraph, lin1), chunking2(depgraph, lin2); - /** Output linearization. */ - std::vector ret; - if (depgraph.TxCount() == 0) return ret; - ret.reserve(depgraph.TxCount()); - - while (true) { - // As long as we are not done, both linearizations must have chunks left. - Assume(chunking1.NumChunksLeft() > 0); - Assume(chunking2.NumChunksLeft() > 0); - // Find the set to output by taking the best remaining chunk, and then intersecting it with - // prefixes of remaining chunks of the other linearization. - SetInfo best; - const auto& lin1_firstchunk = chunking1.GetChunk(0); - const auto& lin2_firstchunk = chunking2.GetChunk(0); - if (lin2_firstchunk.feerate >> lin1_firstchunk.feerate) { - best = chunking1.IntersectPrefixes(lin2_firstchunk); - } else { - best = chunking2.IntersectPrefixes(lin1_firstchunk); - } - // Append the result to the output and mark it as done. - depgraph.AppendTopo(ret, best.transactions); - chunking1.MarkDone(best.transactions); - if (chunking1.NumChunksLeft() == 0) break; - chunking2.MarkDone(best.transactions); - } - - Assume(ret.size() == depgraph.TxCount()); - return ret; -} - /** Make linearization topological, retaining its ordering where possible. */ template void FixLinearization(const DepGraph& depgraph, std::span linearization) noexcept diff --git a/depend/bitcoin/src/coins.cpp b/depend/bitcoin/src/coins.cpp index 1ca5fca3..14381ecb 100644 --- a/depend/bitcoin/src/coins.cpp +++ b/depend/bitcoin/src/coins.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2022 The Bitcoin Core developers +// Copyright (c) 2012-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/args.cpp b/depend/bitcoin/src/common/args.cpp index 88a28edc..3ffa4d3f 100644 --- a/depend/bitcoin/src/common/args.cpp +++ b/depend/bitcoin/src/common/args.cpp @@ -164,7 +164,7 @@ std::list ArgsManager::GetUnrecognizedSections() const LOCK(cs_args); std::list unrecognized = m_config_sections; - unrecognized.remove_if([](const SectionInfo& appeared){ return available_sections.find(appeared.m_name) != available_sections.end(); }); + unrecognized.remove_if([](const SectionInfo& appeared){ return available_sections.contains(appeared.m_name); }); return unrecognized; } @@ -832,7 +832,7 @@ std::variant ArgsManager::GetChainArg() const bool ArgsManager::UseDefaultSection(const std::string& arg) const { - return m_network == ChainTypeToString(ChainType::MAIN) || m_network_only_args.count(arg) == 0; + return m_network == ChainTypeToString(ChainType::MAIN) || !m_network_only_args.contains(arg); } common::SettingsValue ArgsManager::GetSetting(const std::string& arg) const diff --git a/depend/bitcoin/src/common/config.cpp b/depend/bitcoin/src/common/config.cpp index 79c0424a..a2cf9381 100644 --- a/depend/bitcoin/src/common/config.cpp +++ b/depend/bitcoin/src/common/config.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2023 The Bitcoin Core developers +// Copyright (c) 2023-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/init.cpp b/depend/bitcoin/src/common/init.cpp index 5a704404..7a1d664c 100644 --- a/depend/bitcoin/src/common/init.cpp +++ b/depend/bitcoin/src/common/init.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2023 The Bitcoin Core developers +// Copyright (c) 2023-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/init.h b/depend/bitcoin/src/common/init.h index 380ac3ac..2d3eacd2 100644 --- a/depend/bitcoin/src/common/init.h +++ b/depend/bitcoin/src/common/init.h @@ -1,4 +1,4 @@ -// Copyright (c) 2023 The Bitcoin Core developers +// Copyright (c) 2023-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/interfaces.cpp b/depend/bitcoin/src/common/interfaces.cpp index c8bbe2b3..ffd85e61 100644 --- a/depend/bitcoin/src/common/interfaces.cpp +++ b/depend/bitcoin/src/common/interfaces.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2021-2022 The Bitcoin Core developers +// Copyright (c) 2021-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/messages.cpp b/depend/bitcoin/src/common/messages.cpp index 983c9826..123db93c 100644 --- a/depend/bitcoin/src/common/messages.cpp +++ b/depend/bitcoin/src/common/messages.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/messages.h b/depend/bitcoin/src/common/messages.h index 5d33edac..4cabdc79 100644 --- a/depend/bitcoin/src/common/messages.h +++ b/depend/bitcoin/src/common/messages.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2020 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/netif.cpp b/depend/bitcoin/src/common/netif.cpp index ed891f12..cba4d4e7 100644 --- a/depend/bitcoin/src/common/netif.cpp +++ b/depend/bitcoin/src/common/netif.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2024 The Bitcoin Core developers +// Copyright (c) 2024-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/netif.h b/depend/bitcoin/src/common/netif.h index 55bc023b..769bcbcc 100644 --- a/depend/bitcoin/src/common/netif.h +++ b/depend/bitcoin/src/common/netif.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 The Bitcoin Core developers +// Copyright (c) 2024-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/pcp.h b/depend/bitcoin/src/common/pcp.h index b3e36d13..121349b0 100644 --- a/depend/bitcoin/src/common/pcp.h +++ b/depend/bitcoin/src/common/pcp.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 The Bitcoin Core developers +// Copyright (c) 2024-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/run_command.cpp b/depend/bitcoin/src/common/run_command.cpp index 1f6d51b4..57683e03 100644 --- a/depend/bitcoin/src/common/run_command.cpp +++ b/depend/bitcoin/src/common/run_command.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022 The Bitcoin Core developers +// Copyright (c) 2022-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/run_command.h b/depend/bitcoin/src/common/run_command.h index 2fbdc071..56c94f83 100644 --- a/depend/bitcoin/src/common/run_command.h +++ b/depend/bitcoin/src/common/run_command.h @@ -1,4 +1,4 @@ -// Copyright (c) 2022 The Bitcoin Core developers +// Copyright (c) 2022-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/settings.cpp b/depend/bitcoin/src/common/settings.cpp index fbe531c7..e9b92979 100644 --- a/depend/bitcoin/src/common/settings.cpp +++ b/depend/bitcoin/src/common/settings.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2022 The Bitcoin Core developers +// Copyright (c) 2019-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/settings.h b/depend/bitcoin/src/common/settings.h index 0e9d376e..bc7b89a9 100644 --- a/depend/bitcoin/src/common/settings.h +++ b/depend/bitcoin/src/common/settings.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2022 The Bitcoin Core developers +// Copyright (c) 2019-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/signmessage.cpp b/depend/bitcoin/src/common/signmessage.cpp index 1612751e..a86310e1 100644 --- a/depend/bitcoin/src/common/signmessage.cpp +++ b/depend/bitcoin/src/common/signmessage.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/signmessage.h b/depend/bitcoin/src/common/signmessage.h index 215b563b..4533875a 100644 --- a/depend/bitcoin/src/common/signmessage.h +++ b/depend/bitcoin/src/common/signmessage.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/types.h b/depend/bitcoin/src/common/types.h index fb9ee4bf..7b5da0fc 100644 --- a/depend/bitcoin/src/common/types.h +++ b/depend/bitcoin/src/common/types.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010-2021 The Bitcoin Core developers +// Copyright (c) 2010-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/url.cpp b/depend/bitcoin/src/common/url.cpp index ecf88d07..30ac26a1 100644 --- a/depend/bitcoin/src/common/url.cpp +++ b/depend/bitcoin/src/common/url.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2022 The Bitcoin Core developers +// Copyright (c) 2015-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/common/url.h b/depend/bitcoin/src/common/url.h index 203f41c7..718a607f 100644 --- a/depend/bitcoin/src/common/url.h +++ b/depend/bitcoin/src/common/url.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2022 The Bitcoin Core developers +// Copyright (c) 2015-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/compat/assumptions.h b/depend/bitcoin/src/compat/assumptions.h index 7b66ab1b..9910c95d 100644 --- a/depend/bitcoin/src/compat/assumptions.h +++ b/depend/bitcoin/src/compat/assumptions.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2021 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/compat/byteswap.h b/depend/bitcoin/src/compat/byteswap.h index 0d0b0792..ec961503 100644 --- a/depend/bitcoin/src/compat/byteswap.h +++ b/depend/bitcoin/src/compat/byteswap.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2022 The Bitcoin Core developers +// Copyright (c) 2014-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/compat/compat.h b/depend/bitcoin/src/compat/compat.h index acb57b26..b7fe6b98 100644 --- a/depend/bitcoin/src/compat/compat.h +++ b/depend/bitcoin/src/compat/compat.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/compat/cpuid.h b/depend/bitcoin/src/compat/cpuid.h index 4237c8eb..1dddc1ea 100644 --- a/depend/bitcoin/src/compat/cpuid.h +++ b/depend/bitcoin/src/compat/cpuid.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022 The Bitcoin Core developers +// Copyright (c) 2017-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/compat/endian.h b/depend/bitcoin/src/compat/endian.h index 4f584281..1553056a 100644 --- a/depend/bitcoin/src/compat/endian.h +++ b/depend/bitcoin/src/compat/endian.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2022 The Bitcoin Core developers +// Copyright (c) 2014-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/compat/stdin.cpp b/depend/bitcoin/src/compat/stdin.cpp index c11763f6..20540f2a 100644 --- a/depend/bitcoin/src/compat/stdin.cpp +++ b/depend/bitcoin/src/compat/stdin.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2022 The Bitcoin Core developers +// Copyright (c) 2018-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/compat/stdin.h b/depend/bitcoin/src/compat/stdin.h index 468fe4d6..1b74c7f9 100644 --- a/depend/bitcoin/src/compat/stdin.h +++ b/depend/bitcoin/src/compat/stdin.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Bitcoin Core developers +// Copyright (c) 2018-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/compressor.cpp b/depend/bitcoin/src/compressor.cpp index 668e2558..ad5859c4 100644 --- a/depend/bitcoin/src/compressor.cpp +++ b/depend/bitcoin/src/compressor.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2021 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/consensus/amount.h b/depend/bitcoin/src/consensus/amount.h index f0eb4e07..2a65a831 100644 --- a/depend/bitcoin/src/consensus/amount.h +++ b/depend/bitcoin/src/consensus/amount.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2021 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/consensus/merkle.cpp b/depend/bitcoin/src/consensus/merkle.cpp index 703a824e..84ff352d 100644 --- a/depend/bitcoin/src/consensus/merkle.cpp +++ b/depend/bitcoin/src/consensus/merkle.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2020 The Bitcoin Core developers +// Copyright (c) 2015-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/consensus/merkle.h b/depend/bitcoin/src/consensus/merkle.h index 29282d21..03b5a1b5 100644 --- a/depend/bitcoin/src/consensus/merkle.h +++ b/depend/bitcoin/src/consensus/merkle.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2019 The Bitcoin Core developers +// Copyright (c) 2015-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/consensus/params.h b/depend/bitcoin/src/consensus/params.h index f33ff15f..93ee071f 100644 --- a/depend/bitcoin/src/consensus/params.h +++ b/depend/bitcoin/src/consensus/params.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/consensus/tx_check.cpp b/depend/bitcoin/src/consensus/tx_check.cpp index b3fee1e8..251417c8 100644 --- a/depend/bitcoin/src/consensus/tx_check.cpp +++ b/depend/bitcoin/src/consensus/tx_check.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021 The Bitcoin Core developers +// Copyright (c) 2017-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/consensus/tx_check.h b/depend/bitcoin/src/consensus/tx_check.h index 21f84240..faaeca93 100644 --- a/depend/bitcoin/src/consensus/tx_check.h +++ b/depend/bitcoin/src/consensus/tx_check.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2019 The Bitcoin Core developers +// Copyright (c) 2017-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/consensus/tx_verify.cpp b/depend/bitcoin/src/consensus/tx_verify.cpp index c38b9643..00022a33 100644 --- a/depend/bitcoin/src/consensus/tx_verify.cpp +++ b/depend/bitcoin/src/consensus/tx_verify.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021 The Bitcoin Core developers +// Copyright (c) 2017-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/consensus/validation.h b/depend/bitcoin/src/consensus/validation.h index 2b2dd4bb..37a40e76 100644 --- a/depend/bitcoin/src/consensus/validation.h +++ b/depend/bitcoin/src/consensus/validation.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/core_io.h b/depend/bitcoin/src/core_io.h index 1874c93a..f768590c 100644 --- a/depend/bitcoin/src/core_io.h +++ b/depend/bitcoin/src/core_io.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/core_memusage.h b/depend/bitcoin/src/core_memusage.h index 6f1ace99..e96cd734 100644 --- a/depend/bitcoin/src/core_memusage.h +++ b/depend/bitcoin/src/core_memusage.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2018 The Bitcoin Core developers +// Copyright (c) 2015-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/depend/bitcoin/src/core_read.cpp b/depend/bitcoin/src/core_read.cpp index 27d0d9d7..935f4659 100644 --- a/depend/bitcoin/src/core_read.cpp +++ b/depend/bitcoin/src/core_read.cpp @@ -1,20 +1,30 @@ -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include -#include +#include // IWYU pragma: keep #include +#include