diff --git a/.gitignore b/.gitignore index 9a73e23bdb..99a841eb69 100644 --- a/.gitignore +++ b/.gitignore @@ -75,7 +75,7 @@ libconftest.dylib* *.log *.trs -*.dmg +*.zip *.json.h *.raw.h diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fac98fea98..30f47434c4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -377,6 +377,15 @@ linux64_multiprocess-test: variables: BUILD_TARGET: linux64_multiprocess +linux64_nowallet-test: + extends: + - .test-template + - .skip-in-fast-mode-template + needs: + - linux64_nowallet-build + variables: + BUILD_TARGET: linux64_nowallet + #linux64_valgrind-test: # extends: # - .test-template diff --git a/Makefile.am b/Makefile.am index 0794ac8c02..b059d0c6f7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,8 +15,6 @@ endif .PHONY: deploy FORCE .INTERMEDIATE: $(COVERAGE_INFO) -export PYTHONPATH - if BUILD_BITCOIN_LIBS pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libdashconsensus.pc @@ -36,7 +34,7 @@ space := $(empty) $(empty) OSX_APP=Dash-Qt.app OSX_VOLNAME = $(subst $(space),-,$(PACKAGE_NAME)) -OSX_DMG = $(OSX_VOLNAME).dmg +OSX_ZIP = $(OSX_VOLNAME).zip OSX_DEPLOY_SCRIPT=$(top_srcdir)/contrib/macdeploy/macdeployqtplus OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/dash.icns OSX_PLIST=$(top_builddir)/share/qt/Info.plist #not installed @@ -119,15 +117,16 @@ OSX_APP_BUILT=$(OSX_APP)/Contents/PkgInfo $(OSX_APP)/Contents/Resources/empty.lp $(OSX_APP)/Contents/MacOS/Dash-Qt $(OSX_APP)/Contents/Resources/Base.lproj/InfoPlist.strings if BUILD_DARWIN -$(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING) - $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR) -dmg +$(OSX_ZIP): $(OSX_APP_BUILT) $(OSX_PACKAGING) + $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR) -zip -deploydir: $(OSX_DMG) +deploydir: $(OSX_ZIP) else !BUILD_DARWIN APP_DIST_DIR=$(top_builddir)/dist -$(OSX_DMG): deploydir - $(XORRISOFS) -D -l -V "$(OSX_VOLNAME)" -no-pad -r -dir-mode 0755 -o $@ $(APP_DIST_DIR) -- $(if $(SOURCE_DATE_EPOCH),-volume_date all_file_dates =$(SOURCE_DATE_EPOCH)) +$(OSX_ZIP): deploydir + if [ -n "$(SOURCE_DATE_EPOCH)" ]; then find $(APP_DIST_DIR) -exec touch -d @$(SOURCE_DATE_EPOCH) {} +; fi + cd $(APP_DIST_DIR) && find . | sort | $(ZIP) -X@ $@ $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Dash-Qt: $(OSX_APP_BUILT) $(OSX_PACKAGING) OBJDUMP=$(OBJDUMP) $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR) @@ -135,7 +134,7 @@ $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Dash-Qt: $(OSX_APP_BUILT) $(OSX_PACKAG deploydir: $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Dash-Qt endif !BUILD_DARWIN -deploy: $(OSX_DMG) +deploy: $(OSX_ZIP) endif $(BITCOIN_QT_BIN): FORCE @@ -294,7 +293,7 @@ EXTRA_DIST += \ test/util/data/txcreatesignv2.hex \ test/util/rpcauth-test.py -CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER) +CLEANFILES = $(OSX_ZIP) $(BITCOIN_WIN_INSTALLER) DISTCHECK_CONFIGURE_FLAGS = --enable-man diff --git a/ci/test/00_setup_env_mac.sh b/ci/test/00_setup_env_mac.sh index 6270df634a..3764caa0de 100755 --- a/ci/test/00_setup_env_mac.sh +++ b/ci/test/00_setup_env_mac.sh @@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_macos_cross export HOST=x86_64-apple-darwin -export PACKAGES="cmake libz-dev python3-setuptools xorriso" +export PACKAGES="clang cmake lld llvm zip" export XCODE_VERSION=15.0 export XCODE_BUILD_ID=15A240d export RUN_UNIT_TESTS=false diff --git a/ci/test/00_setup_env_native_fuzz.sh b/ci/test/00_setup_env_native_fuzz.sh index 2ba78325ff..d1bb30d199 100755 --- a/ci/test/00_setup_env_native_fuzz.sh +++ b/ci/test/00_setup_env_native_fuzz.sh @@ -16,4 +16,4 @@ export RUN_UNIT_TESTS=false export RUN_FUNCTIONAL_TESTS=false export RUN_FUZZ_TESTS=true export GOAL="install" -export BITCOIN_CONFIG="--enable-zmq --disable-ccache --enable-fuzz --with-sanitizers=fuzzer,address,undefined,integer --enable-suppress-external-warnings CC=clang-16 CXX=clang++-16 --with-boost-process" +export BITCOIN_CONFIG="--enable-zmq --disable-ccache --enable-fuzz --with-sanitizers=fuzzer,address,undefined,integer --enable-suppress-external-warnings CC=clang-18 CXX=clang++-18 --with-boost-process" diff --git a/ci/test/00_setup_env_native_fuzz_with_valgrind.sh b/ci/test/00_setup_env_native_fuzz_with_valgrind.sh index b5c6b60b4a..9860123546 100755 --- a/ci/test/00_setup_env_native_fuzz_with_valgrind.sh +++ b/ci/test/00_setup_env_native_fuzz_with_valgrind.sh @@ -14,4 +14,4 @@ export RUN_FUNCTIONAL_TESTS=false export RUN_FUZZ_TESTS=true export FUZZ_TESTS_CONFIG="--valgrind" export GOAL="install" -export BITCOIN_CONFIG="--enable-fuzz --with-sanitizers=fuzzer --enable-suppress-external-warnings CC=clang-16 CXX=clang++-16" +export BITCOIN_CONFIG="--enable-fuzz --with-sanitizers=fuzzer --enable-suppress-external-warnings CC=clang-18 CXX=clang++-18" diff --git a/ci/test/00_setup_env_native_multiprocess.sh b/ci/test/00_setup_env_native_multiprocess.sh index d23fae22b5..04d1b1df55 100755 --- a/ci/test/00_setup_env_native_multiprocess.sh +++ b/ci/test/00_setup_env_native_multiprocess.sh @@ -11,5 +11,5 @@ export PACKAGES="cmake python3 llvm clang" export DEP_OPTS="DEBUG=1 MULTIPROCESS=1" export GOAL="install" export TEST_RUNNER_EXTRA="--v2transport" -export BITCOIN_CONFIG="--with-boost-process --enable-debug CC=clang-16 CXX=clang++-16" # Use clang to avoid OOM +export BITCOIN_CONFIG="--with-boost-process --enable-debug CC=clang-18 CXX=clang++-18" # Use clang to avoid OOM export BITCOIND=dash-node # Used in functional tests diff --git a/ci/test/00_setup_env_native_tsan.sh b/ci/test/00_setup_env_native_tsan.sh index add809a28c..7e6ce2b7fa 100755 --- a/ci/test/00_setup_env_native_tsan.sh +++ b/ci/test/00_setup_env_native_tsan.sh @@ -7,11 +7,11 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_tsan -export PACKAGES="clang-16 llvm-16 libclang-rt-16-dev libc++abi-16-dev libc++-16-dev python3-zmq" -export DEP_OPTS="CC=clang-16 CXX='clang++-16 -stdlib=libc++'" +export PACKAGES="clang-18 llvm-18 libclang-rt-18-dev libc++abi-18-dev libc++-18-dev python3-zmq" +export DEP_OPTS="CC=clang-18 CXX='clang++-18 -stdlib=libc++'" export TEST_RUNNER_EXTRA="--extended --exclude feature_pruning,feature_dbcrash,wallet_multiwallet.py" # Temporarily suppress ASan heap-use-after-free (see issue #14163) export TEST_RUNNER_EXTRA="${TEST_RUNNER_EXTRA} --timeout-factor=4" # Increase timeout because sanitizers slow down export GOAL="install" -export BITCOIN_CONFIG="--enable-zmq --with-gui=no --with-sanitizers=thread CC=clang-16 CXX=clang++-16 CXXFLAGS='-g' --with-boost-process" +export BITCOIN_CONFIG="--enable-zmq --with-gui=no --with-sanitizers=thread CC=clang-18 CXX=clang++-18 CXXFLAGS='-g' --with-boost-process" export CPPFLAGS="-DARENA_DEBUG -DDEBUG_LOCKORDER -DDEBUG_LOCKCONTENTION" export PYZMQ=true diff --git a/ci/test/00_setup_env_native_ubsan.sh b/ci/test/00_setup_env_native_ubsan.sh index 3d44490a4f..9fb440dfd4 100755 --- a/ci/test/00_setup_env_native_ubsan.sh +++ b/ci/test/00_setup_env_native_ubsan.sh @@ -8,8 +8,8 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_ubsan -export PACKAGES="clang-16 llvm-16 python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev" +export PACKAGES="clang-18 llvm-18 python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev" export DEP_OPTS="NO_UPNP=1 DEBUG=1" export GOAL="install" -export BITCOIN_CONFIG="--enable-zmq --enable-reduce-exports --enable-crash-hooks --with-sanitizers=undefined CC=clang-16 CXX=clang++-16" +export BITCOIN_CONFIG="--enable-zmq --enable-reduce-exports --enable-crash-hooks --with-sanitizers=undefined CC=clang-18 CXX=clang++-18" export PYZMQ=true diff --git a/ci/test/00_setup_env_native_valgrind.sh b/ci/test/00_setup_env_native_valgrind.sh index 2703963a05..b0793313fb 100755 --- a/ci/test/00_setup_env_native_valgrind.sh +++ b/ci/test/00_setup_env_native_valgrind.sh @@ -11,4 +11,4 @@ export USE_VALGRIND=1 export NO_DEPENDS=1 export TEST_RUNNER_EXTRA="--exclude rpc_bind --timeout-factor=4" # Excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547 export GOAL="install" -export BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --with-gui=no --enable-suppress-external-warnings CC=clang-16 CXX=clang++-16" # TODO enable GUI +export BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --with-gui=no --enable-suppress-external-warnings CC=clang-18 CXX=clang++-18" # TODO enable GUI diff --git a/configure.ac b/configure.ac index af682ac9c1..915dc8d49d 100644 --- a/configure.ac +++ b/configure.ac @@ -127,8 +127,6 @@ AC_PATH_TOOL(DSYMUTIL, dsymutil) AC_PATH_PROG(DOXYGEN, doxygen) AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$DOXYGEN"]) -AC_ARG_VAR(PYTHONPATH, Augments the default search path for python module files) - AC_ARG_ENABLE([wallet], [AS_HELP_STRING([--disable-wallet], [disable wallet (enabled by default)])], @@ -843,7 +841,7 @@ case $host in ;; *) AC_PATH_TOOL([DSYMUTIL], [dsymutil], dsymutil) - AC_PATH_PROGS([XORRISOFS], [xorrisofs], xorrisofs) + AC_PATH_PROG([ZIP], [zip], [zip]) dnl libtool will try to strip the static lib, which is a problem for dnl cross-builds because strip attempts to call a hard-coded ld, @@ -1934,7 +1932,6 @@ AC_CONFIG_LINKS([contrib/devtools/test-security-check.py:contrib/devtools/test-s AC_CONFIG_LINKS([contrib/devtools/symbol-check.py:contrib/devtools/symbol-check.py]) AC_CONFIG_LINKS([contrib/devtools/test-symbol-check.py:contrib/devtools/test-symbol-check.py]) AC_CONFIG_LINKS([contrib/filter-lcov.py:contrib/filter-lcov.py]) -AC_CONFIG_LINKS([contrib/macdeploy/background.tiff:contrib/macdeploy/background.tiff]) AC_CONFIG_LINKS([test/functional/test_runner.py:test/functional/test_runner.py]) AC_CONFIG_LINKS([test/fuzz/test_runner.py:test/fuzz/test_runner.py]) AC_CONFIG_LINKS([test/util/test_runner.py:test/util/test_runner.py]) @@ -2014,5 +2011,6 @@ echo " CPPFLAGS = $DEBUG_CPPFLAGS $HARDENED_CPPFLAGS $CORE_CPPFLAGS echo " CXX = $CXX" echo " CXXFLAGS = $DEBUG_CXXFLAGS $HARDENED_CXXFLAGS $WARN_CXXFLAGS $NOWARN_CXXFLAGS $ERROR_CXXFLAGS $GPROF_CXXFLAGS $CORE_CXXFLAGS $CXXFLAGS" echo " LDFLAGS = $PTHREAD_LIBS $HARDENED_LDFLAGS $GPROF_LDFLAGS $CORE_LDFLAGS $LDFLAGS" +echo " AR = $AR" echo " ARFLAGS = $ARFLAGS" echo diff --git a/contrib/containers/ci/Dockerfile b/contrib/containers/ci/Dockerfile index 85df2c3105..6312faade4 100644 --- a/contrib/containers/ci/Dockerfile +++ b/contrib/containers/ci/Dockerfile @@ -55,23 +55,27 @@ RUN set -ex; \ # Install Clang+LLVM and set it as default # We don't need all packages but the default set doesn't include some # packages we want so we will need to install some of them manually. -ARG LLVM_VERSION=16 +ARG LLVM_VERSION=18 RUN set -ex; \ echo "Installing LLVM and Clang ${LLVM_VERSION}..."; \ - curl -sL https://apt.llvm.org/llvm.sh | bash -s "${LLVM_VERSION}"; \ + curl -sL https://apt.llvm.org/llvm.sh | bash -s -- "${LLVM_VERSION}"; \ echo "Installing additional packages..."; \ apt-get update && apt-get install $APT_ARGS \ "clang-format-${LLVM_VERSION}" \ "clang-tidy-${LLVM_VERSION}" \ "libc++-${LLVM_VERSION}-dev" \ "libc++abi-${LLVM_VERSION}-dev" \ - "libclang-rt-${LLVM_VERSION}-dev"; \ + "libclang-rt-${LLVM_VERSION}-dev" \ + "lld-${LLVM_VERSION}"; \ rm -rf /var/lib/apt/lists/*; \ echo "Setting defaults..."; \ lldbUpdAltArgs="update-alternatives --install /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-${LLVM_VERSION} 100"; \ - for binName in clang clang++ clang-format clang-tidy clangd ld.lld lldb lldb-server; do \ + for binName in clang clang++ clang-format clang-tidy clangd dsymutil lld lldb lldb-server llvm-ar llvm-cov llvm-nm llvm-objdump llvm-ranlib llvm-strip; do \ lldbUpdAltArgs="${lldbUpdAltArgs} --slave /usr/bin/${binName} ${binName} /usr/bin/${binName}-${LLVM_VERSION}"; \ done; \ + for binName in ld64.lld ld.lld lld-link wasm-ld; do \ + lldbUpdAltArgs="${lldbUpdAltArgs} --slave /usr/bin/${binName} ${binName} /usr/bin/lld-${LLVM_VERSION}"; \ + done; \ sh -c "${lldbUpdAltArgs}"; # LD_LIBRARY_PATH is empty by default, this is the first entry ENV LD_LIBRARY_PATH="/usr/lib/llvm-${LLVM_VERSION}/lib" @@ -159,7 +163,7 @@ RUN apt-get update && apt-get install $APT_ARGS \ valgrind \ wine-stable \ wine64 \ - xorriso \ + zip \ && rm -rf /var/lib/apt/lists/* # This is a hack. It is needed because gcc-multilib and g++-multilib are conflicting with g++-arm-linux-gnueabihf. This is diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py index 7c34f59369..f4b6847a94 100755 --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -251,8 +251,8 @@ def check_MACHO_sdk(binary) -> bool: return True return False -def check_MACHO_ld64(binary) -> bool: - if binary.build_version.tools[0].version == [711, 0, 0]: +def check_MACHO_lld(binary) -> bool: + if binary.build_version.tools[0].version == [18, 1, 6]: return True return False @@ -295,7 +295,7 @@ def check_ELF_ABI(binary) -> bool: ('DYNAMIC_LIBRARIES', check_MACHO_libraries), ('MIN_OS', check_MACHO_min_os), ('SDK', check_MACHO_sdk), - ('LD64', check_MACHO_ld64), + ('LLD', check_MACHO_lld), ], lief.EXE_FORMATS.PE: [ ('DYNAMIC_LIBRARIES', check_PE_libraries), diff --git a/contrib/devtools/test-security-check.py b/contrib/devtools/test-security-check.py index 5b0c606f04..ae6dc51b60 100755 --- a/contrib/devtools/test-security-check.py +++ b/contrib/devtools/test-security-check.py @@ -121,21 +121,15 @@ def test_MACHO(self): arch = get_arch(cc, source, executable) if arch == lief.ARCHITECTURES.X86: - self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace','-Wl,-allow_stack_execute','-fno-stack-protector', '-Wl,-no_fixup_chains']), - (1, executable+': failed NOUNDEFS Canary FIXUP_CHAINS PIE NX CONTROL_FLOW')) - self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace','-Wl,-allow_stack_execute','-fno-stack-protector', '-Wl,-fixup_chains']), - (1, executable+': failed NOUNDEFS Canary PIE NX CONTROL_FLOW')) - self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace','-Wl,-allow_stack_execute','-fstack-protector-all', '-Wl,-fixup_chains']), - (1, executable+': failed NOUNDEFS PIE NX CONTROL_FLOW')) - self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace','-fstack-protector-all', '-Wl,-fixup_chains']), - (1, executable+': failed NOUNDEFS PIE CONTROL_FLOW')) - self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-fstack-protector-all', '-Wl,-fixup_chains']), - (1, executable+': failed PIE CONTROL_FLOW')) - self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-fstack-protector-all', '-Wl,-fixup_chains']), - (1, executable+': failed PIE CONTROL_FLOW')) - self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-fstack-protector-all', '-fcf-protection=full', '-Wl,-fixup_chains']), - (1, executable+': failed PIE')) - self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-pie','-fstack-protector-all', '-fcf-protection=full', '-Wl,-fixup_chains']), + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace','-fno-stack-protector', '-Wl,-no_fixup_chains']), + (1, executable+': failed NOUNDEFS Canary FIXUP_CHAINS PIE CONTROL_FLOW')) + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-flat_namespace','-fno-stack-protector', '-Wl,-fixup_chains']), + (1, executable+': failed NOUNDEFS Canary CONTROL_FLOW')) + self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-flat_namespace','-fstack-protector-all', '-Wl,-fixup_chains']), + (1, executable+': failed NOUNDEFS CONTROL_FLOW')) + self.assertEqual(call_security_check(cc, source, executable, ['-fstack-protector-all', '-Wl,-fixup_chains']), + (1, executable+': failed CONTROL_FLOW')) + self.assertEqual(call_security_check(cc, source, executable, ['-fstack-protector-all', '-fcf-protection=full', '-Wl,-fixup_chains']), (0, '')) else: # arm64 darwin doesn't support non-PIE binaries, control flow or executable stacks diff --git a/contrib/guix/guix-build b/contrib/guix/guix-build index 1fef7400f5..122c8dc22d 100755 --- a/contrib/guix/guix-build +++ b/contrib/guix/guix-build @@ -194,7 +194,7 @@ fi if ! getent services http https ftp > /dev/null 2>&1; then cat << EOF -ERR: Your system's C library can not find service database entries for at least +ERR: Your system's C library cannot find service database entries for at least one of the following services: http, https, ftp. Hint: Most likely, /etc/services does not exist yet (common for docker images diff --git a/contrib/guix/libexec/build.sh b/contrib/guix/libexec/build.sh index 4c4f8d09b6..ea1d5079ee 100755 --- a/contrib/guix/libexec/build.sh +++ b/contrib/guix/libexec/build.sh @@ -135,18 +135,7 @@ for p in "${PATHS[@]}"; do done # Disable Guix ld auto-rpath behavior -case "$HOST" in - *darwin*) - # The auto-rpath behavior is necessary for darwin builds as some native - # tools built by depends refer to and depend on Guix-built native - # libraries - # - # After the native packages in depends are built, the ld wrapper should - # no longer affect our build, as clang would instead reach for - # x86_64-apple-darwin-ld from cctools - ;; - *) export GUIX_LD_WRAPPER_DISABLE_RPATH=yes ;; -esac +export GUIX_LD_WRAPPER_DISABLE_RPATH=yes # Make /usr/bin if it doesn't exist [ -e /usr/bin ] || mkdir -p /usr/bin @@ -175,16 +164,6 @@ esac # Environment variables for determinism export TAR_OPTIONS="--owner=0 --group=0 --numeric-owner --mtime='@${SOURCE_DATE_EPOCH}' --sort=name" export TZ="UTC" -case "$HOST" in - *darwin*) - # cctools AR, unlike GNU binutils AR, does not have a deterministic mode - # or a configure flag to enable determinism by default, it only - # understands if this env-var is set or not. See: - # - # https://github.com/tpoechtrager/cctools-port/blob/55562e4073dea0fbfd0b20e0bf69ffe6390c7f97/cctools/ar/archive.c#L334 - export ZERO_AR_DATE=yes - ;; -esac #################### # Depends Building # @@ -201,8 +180,7 @@ make -C depends --jobs="$JOBS" HOST="$HOST" \ x86_64_linux_AR=x86_64-linux-gnu-gcc-ar \ x86_64_linux_RANLIB=x86_64-linux-gnu-gcc-ranlib \ x86_64_linux_NM=x86_64-linux-gnu-gcc-nm \ - x86_64_linux_STRIP=x86_64-linux-gnu-strip \ - FORCE_USE_SYSTEM_CLANG=1 + x86_64_linux_STRIP=x86_64-linux-gnu-strip ########################### @@ -326,7 +304,7 @@ mkdir -p "$DISTSRC" | gzip -9n > "${OUTDIR}/${DISTNAME}-${HOST}-unsigned.tar.gz" \ || ( rm -f "${OUTDIR}/${DISTNAME}-${HOST}-unsigned.tar.gz" && exit 1 ) ) - make deploy ${V:+V=1} OSX_DMG="${OUTDIR}/${DISTNAME}-${HOST}-unsigned.dmg" + make deploy ${V:+V=1} OSX_ZIP="${OUTDIR}/${DISTNAME}-${HOST}-unsigned.zip" ;; esac ( diff --git a/contrib/guix/libexec/codesign.sh b/contrib/guix/libexec/codesign.sh index c097628690..12482a6e46 100755 --- a/contrib/guix/libexec/codesign.sh +++ b/contrib/guix/libexec/codesign.sh @@ -78,11 +78,12 @@ mkdir -p "$DISTSRC" # Apply detached codesignatures to dist/ (in-place) signapple apply dist/Dash-Qt.app codesignatures/osx/dist - # Make a DMG from dist/ - xorrisofs -D -l -V "$(< osx_volname)" -no-pad -r -dir-mode 0755 \ - -o "${OUTDIR}/${DISTNAME}-${HOST}.dmg" \ - dist \ - -- -volume_date all_file_dates ="$SOURCE_DATE_EPOCH" + # Make a .zip from dist/ + cd dist/ + find . -print0 \ + | xargs -0r touch --no-dereference --date="@${SOURCE_DATE_EPOCH}" + find . | sort \ + | zip -X@ "${OUTDIR}/${DISTNAME}-${HOST}.zip" ;; *) exit 1 diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm index 8b632c0b4f..789792f554 100644 --- a/contrib/guix/manifest.scm +++ b/contrib/guix/manifest.scm @@ -3,7 +3,6 @@ ((gnu packages bash) #:select (bash-minimal)) (gnu packages bison) ((gnu packages certs) #:select (nss-certs)) - ((gnu packages cdrom) #:select (xorriso)) ((gnu packages cmake) #:select (cmake-minimal)) (gnu packages commencement) (gnu packages compression) @@ -578,6 +577,7 @@ inspecting signatures in Mach-O binaries.") gzip xz ;; Build tools + gcc-toolchain-12 cmake-minimal gnu-make libtool @@ -593,23 +593,18 @@ inspecting signatures in Mach-O binaries.") python-lief) (let ((target (getenv "HOST"))) (cond ((string-suffix? "-mingw32" target) - (list ;; Native GCC 12 toolchain - gcc-toolchain-12 - zip + (list zip (make-mingw-pthreads-cross-toolchain "x86_64-w64-mingw32") nsis-x86_64 nss-certs osslsigncode)) ((string-contains target "-linux-") - (list ;; Native GCC 12 toolchain - gcc-toolchain-12 - (list gcc-toolchain-12 "static") + (list (list gcc-toolchain-12 "static") (make-bitcoin-cross-toolchain target))) ((string-contains target "darwin") - (list ;; Native GCC 11 toolchain - gcc-toolchain-11 - binutils - clang-toolchain-17 + (list clang-toolchain-18 + lld-18 + (make-lld-wrapper lld-18 #:lld-as-ld? #t) python-signapple - xorriso)) + zip)) (else '()))))) diff --git a/contrib/macdeploy/README.md b/contrib/macdeploy/README.md index 7d8f0958e2..cf32a07602 100644 --- a/contrib/macdeploy/README.md +++ b/contrib/macdeploy/README.md @@ -6,7 +6,7 @@ The `macdeployqtplus` script should not be run manually. Instead, after building make deploy ``` -When complete, it will have produced `Dash-Qt.dmg`. +When complete, it will have produced `Dash-Core.zip`. ## SDK Extraction @@ -54,53 +54,25 @@ path to `Xcode.app` (extracted in the previous stage) as the first argument. The generated archive should be: `Xcode-15.0-15A240d-extracted-SDK-with-libcxx-headers.tar.gz`. The `sha256sum` should be `c0c2e7bb92c1fee0c4e9f3a485e4530786732d6c6dd9e9f418c282aa6892f55d`. -## Deterministic macOS DMG Notes +## Deterministic macOS App Notes -Working macOS DMGs are created in Linux by combining a recent `clang`, the Apple -`binutils` (`ld`, `ar`, etc) and DMG authoring tools. +macOS Applications are created on Linux using a recent LLVM. -Apple uses `clang` extensively for development and has upstreamed the necessary -functionality so that a vanilla clang can take advantage. It supports the use of `-F`, -`-target`, `-mmacosx-version-min`, and `-isysroot`, which are all necessary when -building for macOS. +All builds must target an Apple SDK. These SDKs are free to download, but not redistributable. +See the SDK Extraction notes above for how to obtain it. -Apple's version of `binutils` (called `cctools`) contains lots of functionality missing in the -FSF's `binutils`. In addition to extra linker options for frameworks and sysroots, several -other tools are needed as well. These do not build under Linux, so they have been patched to -do so. The work here was used as a starting point: [mingwandroid/toolchain4](https://github.com/mingwandroid/toolchain4). +The Guix build process has been designed to avoid including the SDK's files in Guix's outputs. +All interim tarballs are fully deterministic and may be freely redistributed. -In order to build a working toolchain, the following source packages are needed from -Apple: `cctools`, `dyld`, and `ld64`. +Using an Apple-blessed key to sign binaries is a requirement to produce (distributable) macOS +binaries. Because this private key cannot be shared, we'll have to be a bit creative in order +for the build process to remain somewhat deterministic. Here's how it works: -These tools inject timestamps by default, which produce non-deterministic binaries. The -`ZERO_AR_DATE` environment variable is used to disable that. - -This version of `cctools` has been patched to use the current version of `clang`'s headers -and its `libLTO.so` rather than those from `llvmgcc`, as it was originally done in `toolchain4`. - -To complicate things further, all builds must target an Apple SDK. These SDKs are free to -download, but not redistributable. See the SDK Extraction notes above for how to obtain it. - -The Guix process builds 2 sets of files: Linux tools, then Apple binaries which are -created using these tools. The build process has been designed to avoid including the -SDK's files in Guix's outputs. All interim tarballs are fully deterministic and may be freely -redistributed. - -[`xorrisofs`](https://www.gnu.org/software/xorriso/) is used to create the DMG. - -A background image is added to DMG files by inserting a `.DS_Store` during creation. - -As of OS X 10.9 Mavericks, using an Apple-blessed key to sign binaries is a requirement in -order to satisfy the new Gatekeeper requirements. Because this private key cannot be -shared, we'll have to be a bit creative in order for the build process to remain somewhat -deterministic. Here's how it works: - -- Builders use Guix to create an unsigned release. This outputs an unsigned DMG which - users may choose to bless and run. It also outputs an unsigned app structure in the form - of a tarball, which also contains all of the tools that have been previously (deterministically) - built in order to create a final DMG. +- Builders use Guix to create an unsigned release. This outputs an unsigned ZIP which + users may choose to bless, self-codesign, and run. It also outputs an unsigned app structure + in the form of a tarball. - The Apple keyholder uses this unsigned app to create a detached signature, using the - script that is also included there. Detached signatures are available from this [repository](https://github.com/dashpay/dash-detached-sigs). + included script. Detached signatures are available from this [repository](https://github.com/dashpay/dash-detached-sigs). -- Builders feed the unsigned app + detached signature back into Guix. It uses the - pre-built tools to recombine the pieces into a deterministic DMG. +- Builders feed the unsigned app + detached signature back into Guix, which combines the + pieces into a deterministic ZIP. diff --git a/contrib/macdeploy/background.tiff b/contrib/macdeploy/background.tiff deleted file mode 100644 index 1fb088c837..0000000000 Binary files a/contrib/macdeploy/background.tiff and /dev/null differ diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus index ba7d5e5263..9042a06066 100755 --- a/contrib/macdeploy/macdeployqtplus +++ b/contrib/macdeploy/macdeployqtplus @@ -18,8 +18,6 @@ import sys, re, os, platform, shutil, stat, subprocess, os.path from argparse import ArgumentParser -from ds_store import DSStore -from mac_alias import Alias from pathlib import Path from subprocess import PIPE, run from typing import List, Optional @@ -385,7 +383,7 @@ def deployPlugins(appBundleInfo: ApplicationBundleInfo, deploymentInfo: Deployme ap = ArgumentParser(description="""Improved version of macdeployqt. -Outputs a ready-to-deploy app in a folder "dist" and optionally wraps it in a .dmg file. +Outputs a ready-to-deploy app in a folder "dist" and optionally wraps it in a .zip file. Note, that the "dist" folder will be deleted before deploying on each run. Optionally, Qt translation files (.qm) can be added to the bundle.""") @@ -395,8 +393,8 @@ ap.add_argument("appname", nargs=1, metavar="appname", help="name of the app bei ap.add_argument("-verbose", nargs="?", const=True, help="Output additional debugging information") ap.add_argument("-no-plugins", dest="plugins", action="store_false", default=True, help="skip plugin deployment") ap.add_argument("-no-strip", dest="strip", action="store_false", default=True, help="don't run 'strip' on the binaries") -ap.add_argument("-dmg", nargs="?", const="", metavar="basename", help="create a .dmg disk image") ap.add_argument("-translations-dir", nargs=1, metavar="path", default=None, help="Path to Qt's translations. Base translations will automatically be added to the bundle's resources.") +ap.add_argument("-zip", nargs="?", const="", metavar="zip", help="create a .zip containing the app bundle") config = ap.parse_args() @@ -417,12 +415,9 @@ if os.path.exists("dist"): print("+ Removing existing dist folder +") shutil.rmtree("dist") -if os.path.exists(appname + ".dmg"): - print("+ Removing existing DMG +") - os.unlink(appname + ".dmg") - -if os.path.exists(appname + ".temp.dmg"): - os.unlink(appname + ".temp.dmg") +if os.path.exists(appname + ".zip"): + print("+ Removing existing .zip +") + os.unlink(appname + ".zip") # ------------------------------------------------ @@ -497,99 +492,13 @@ with open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb") as f: # ------------------------------------------------ -print("+ Generating .DS_Store +") - -output_file = os.path.join("dist", ".DS_Store") - -ds = DSStore.open(output_file, 'w+') - -ds['.']['bwsp'] = { - 'WindowBounds': '{{300, 280}, {500, 343}}', - 'PreviewPaneVisibility': False, -} - -icvp = { - 'gridOffsetX': 0.0, - 'textSize': 12.0, - 'viewOptionsVersion': 1, - 'backgroundImageAlias': b'\x00\x00\x00\x00\x02\x1e\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x94\\\xb0H+\x00\x05\x00\x00\x00\x98\x0fbackground.tiff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x99\xd19\xb0\xf8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\r\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b.background\x00\x00\x10\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x11\x00\x08\x00\x00\xd19\xb0\xf8\x00\x00\x00\x01\x00\x04\x00\x00\x00\x98\x00\x0e\x00 \x00\x0f\x00b\x00a\x00c\x00k\x00g\x00r\x00o\x00u\x00n\x00d\x00.\x00t\x00i\x00f\x00f\x00\x0f\x00\x02\x00\x00\x00\x12\x00\x1c/.background/background.tiff\x00\x14\x01\x06\x00\x00\x00\x00\x01\x06\x00\x02\x00\x00\x0cMacintosh HD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xce\x97\xab\xc3H+\x00\x00\x01\x88[\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02u\xab\x8d\xd1\x94\\\xb0devrddsk\xff\xff\xff\xff\x00\x00\t \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07bitcoin\x00\x00\x10\x00\x08\x00\x00\xce\x97\xab\xc3\x00\x00\x00\x11\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x01\x00\x14\x01\x88[\x88\x00\x16\xa9\t\x00\x08\xfaR\x00\x08\xfaQ\x00\x02d\x8e\x00\x0e\x00\x02\x00\x00\x00\x0f\x00\x1a\x00\x0c\x00M\x00a\x00c\x00i\x00n\x00t\x00o\x00s\x00h\x00 \x00H\x00D\x00\x13\x00\x01/\x00\x00\x15\x00\x02\x00\x14\xff\xff\x00\x00\xff\xff\x00\x00', - 'backgroundColorBlue': 1.0, - 'iconSize': 96.0, - 'backgroundColorGreen': 1.0, - 'arrangeBy': 'none', - 'showIconPreview': True, - 'gridSpacing': 100.0, - 'gridOffsetY': 0.0, - 'showItemInfo': False, - 'labelOnBottom': True, - 'backgroundType': 2, - 'backgroundColorRed': 1.0 -} -alias = Alias().from_bytes(icvp['backgroundImageAlias']) -alias.volume.name = appname -alias.volume.posix_path = '/Volumes/' + appname -icvp['backgroundImageAlias'] = alias.to_bytes() -ds['.']['icvp'] = icvp - -ds['.']['vSrn'] = ('long', 1) - -ds['Applications']['Iloc'] = (370, 156) -ds['Dash-Qt.app']['Iloc'] = (128, 156) - -ds.flush() -ds.close() - -# ------------------------------------------------ - if platform.system() == "Darwin": subprocess.check_call(f"codesign --deep --force --sign - {target}", shell=True) -print("+ Installing background.tiff +") - -bg_path = os.path.join('dist', '.background', 'background.tiff') -os.mkdir(os.path.dirname(bg_path)) - -tiff_path = os.path.join('contrib', 'macdeploy', 'background.tiff') -shutil.copy2(tiff_path, bg_path) - -# ------------------------------------------------ - -print("+ Generating symlink for /Applications +") - -os.symlink("/Applications", os.path.join('dist', "Applications")) - # ------------------------------------------------ -if config.dmg is not None: - - print("+ Preparing .dmg disk image +") - - if verbose: - print("Determining size of \"dist\"...") - size = 0 - for path, dirs, files in os.walk("dist"): - for file in files: - size += os.path.getsize(os.path.join(path, file)) - size += int(size * 0.15) - - if verbose: - print("Creating temp image for modification...") - - tempname: str = appname + ".temp.dmg" - - run(["hdiutil", "create", tempname, "-srcfolder", "dist", "-format", "UDRW", "-size", str(size), "-volname", appname], check=True, universal_newlines=True) - - if verbose: - print("Attaching temp image...") - output = run(["hdiutil", "attach", tempname, "-readwrite"], check=True, universal_newlines=True, stdout=PIPE).stdout - - print("+ Finalizing .dmg disk image +") - - run(["hdiutil", "detach", f"/Volumes/{appname}"], universal_newlines=True) - - run(["hdiutil", "convert", tempname, "-format", "UDZO", "-o", appname, "-imagekey", "zlib-level=9"], check=True, universal_newlines=True) - - os.unlink(tempname) +if config.zip is not None: + shutil.make_archive('{}'.format(appname), format='zip', root_dir='dist', base_dir='Dash-Qt.app') # ------------------------------------------------ diff --git a/depends/Makefile b/depends/Makefile index b13e07b6f8..8583521f3f 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -178,9 +178,6 @@ all_packages = $(packages) $(native_packages) meta_depends = Makefile config.guess config.sub funcs.mk builders/default.mk hosts/default.mk hosts/$(host_os).mk builders/$(build_os).mk -$(host_arch)_$(host_os)_native_binutils?=$($(host_os)_native_binutils) -$(host_arch)_$(host_os)_native_toolchain?=$($(host_os)_native_toolchain) - include funcs.mk final_build_id_long+=$(shell $(build_SHA256SUM) config.site.in) @@ -210,9 +207,8 @@ $(host_prefix)/.stamp_$(final_build_id): $(native_packages) $(packages) # tool needs to be available in $PATH at all times. # # 2. If the tool is _**not**_ expected to be available in $PATH at all times -# (such as is the case for our native_cctools binutils tools), it needs to -# be referred to by its absolute path, such as would be output by the -# AC_PATH_{PROG,TOOL} macros. +# it needs to be referred to by its absolute path, such as would be output +# by the AC_PATH_{PROG,TOOL} macros. # # Minor note: it is also okay to refer to tools by their absolute path even if # we expect them to be available in $PATH at all times, more specificity does @@ -227,6 +223,7 @@ $(host_prefix)/share/config.site : config.site.in $(host_prefix)/.stamp_$(final_ -e 's|@NM@|$(host_NM)|' \ -e 's|@STRIP@|$(host_STRIP)|' \ -e 's|@OBJDUMP@|$(host_OBJDUMP)|' \ + -e 's|@DSYMUTIL@|$(host_DSYMUTIL)|' \ -e 's|@build_os@|$(build_os)|' \ -e 's|@host_os@|$(host_os)|' \ -e 's|@CFLAGS@|$(strip $(host_CFLAGS) $(host_$(release_type)_CFLAGS))|' \ diff --git a/depends/README.md b/depends/README.md index 2208c539cb..59fb62b24d 100644 --- a/depends/README.md +++ b/depends/README.md @@ -45,13 +45,17 @@ The paths are automatically configured and no other options are needed unless ta ### Install the required dependencies: Ubuntu & Debian +#### Common + + apt install automake bison cmake curl libtool make patch pkg-config python3 xz-utils + #### For macOS cross compilation - sudo apt-get install curl bsdmainutils cmake libz-dev python3-setuptools xorriso + apt install clang lld llvm g++ zip -Note: You must obtain the macOS SDK before proceeding with a cross-compile. -Under the depends directory, create a subdirectory named `SDKs`. -Then, place the extracted SDK under this new directory. +Clang 18 or later is required. You must also obtain the macOS SDK before +proceeding with a cross-compile. Under the depends directory, create a +subdirectory named `SDKs`. Then, place the extracted SDK under this new directory. For more information, see [SDK Extraction](../contrib/macdeploy/README.md#sdk-extraction). #### For Win64 cross compilation @@ -62,7 +66,7 @@ For more information, see [SDK Extraction](../contrib/macdeploy/README.md#sdk-ex Common linux dependencies: - sudo apt-get install make automake curl g++-multilib libtool binutils bsdmainutils pkg-config python3 patch bison + sudo apt-get install g++-multilib binutils For linux ARM cross compilation: @@ -120,9 +124,6 @@ The following can be set when running make: `make FOO=bar` - `DEBUG`: Disable some optimizations and enable more runtime checking - `HOST_ID_SALT`: Optional salt to use when generating host package ids - `BUILD_ID_SALT`: Optional salt to use when generating build package ids -- `FORCE_USE_SYSTEM_CLANG`: (EXPERTS ONLY) When cross-compiling for macOS, use Clang found in the - system's `$PATH` rather than the default prebuilt release of Clang - from llvm.org. Clang 8 or later is required - `LOG`: Use file-based logging for individual packages. During a package build its log file resides in the `depends` directory, and the log file is printed out automatically in case of build error. After successful build log files are moved along with package archives diff --git a/depends/builders/darwin.mk b/depends/builders/darwin.mk index 3aea314ad8..2b59353e84 100644 --- a/depends/builders/darwin.mk +++ b/depends/builders/darwin.mk @@ -5,6 +5,7 @@ build_darwin_RANLIB:=$(shell xcrun -f ranlib) build_darwin_STRIP:=$(shell xcrun -f strip) build_darwin_OBJDUMP:=$(shell xcrun -f objdump) build_darwin_NM:=$(shell xcrun -f nm) +build_darwin_DSYMUTIL:=$(shell xcrun -f dsymutil) build_darwin_SHA256SUM=shasum -a 256 build_darwin_DOWNLOAD=curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o @@ -16,8 +17,7 @@ darwin_RANLIB:=$(shell xcrun -f ranlib) darwin_STRIP:=$(shell xcrun -f strip) darwin_OBJDUMP:=$(shell xcrun -f objdump) darwin_NM:=$(shell xcrun -f nm) -darwin_native_binutils= -darwin_native_toolchain= +darwin_DSYMUTIL:=$(shell xcrun -f dsymutil) x86_64_darwin_CFLAGS += -arch x86_64 x86_64_darwin_CXXFLAGS += -arch x86_64 diff --git a/depends/builders/default.mk b/depends/builders/default.mk index fa7dfbb005..2a1709d98a 100644 --- a/depends/builders/default.mk +++ b/depends/builders/default.mk @@ -13,7 +13,7 @@ build_$(build_os)_$1 ?= $$(default_build_$1) build_$(build_arch)_$(build_os)_$1 ?= $$(build_$(build_os)_$1) build_$1=$$(build_$(build_arch)_$(build_os)_$1) endef -$(foreach var,CC CXX AR TAR RANLIB NM STRIP SHA256SUM DOWNLOAD OBJDUMP TOUCH,$(eval $(call add_build_tool_func,$(var)))) +$(foreach var,CC CXX AR TAR RANLIB NM STRIP SHA256SUM DOWNLOAD OBJDUMP DSYMUTIL TOUCH,$(eval $(call add_build_tool_func,$(var)))) define add_build_flags_func build_$(build_arch)_$(build_os)_$1 += $(build_$(build_os)_$1) build_$1=$$(build_$(build_arch)_$(build_os)_$1) diff --git a/depends/config.site.in b/depends/config.site.in index 1df388666e..26d5bcfcc2 100644 --- a/depends/config.site.in +++ b/depends/config.site.in @@ -78,7 +78,6 @@ if test "@host_os@" = darwin; then BREW=no fi -PATH="${depends_prefix}/native/bin:${PATH}" PKG_CONFIG="$(which pkg-config) --static" # These two need to remain exported because pkg-config does not see them @@ -98,11 +97,10 @@ fi if test -n "@CXX@" -a -z "${CXX}"; then CXX="@CXX@" fi -PYTHONPATH="${depends_prefix}/native/lib/python3/dist-packages${PYTHONPATH:+${PATH_SEPARATOR}}${PYTHONPATH}" if test -n "@AR@"; then AR="@AR@" - ac_cv_path_ac_pt_AR="${AR}" + ac_cv_path_AR="${AR}" fi if test -n "@RANLIB@"; then @@ -123,7 +121,12 @@ fi if test "@host_os@" = darwin; then if test -n "@OBJDUMP@"; then OBJDUMP="@OBJDUMP@" - ac_cv_path_ac_pt_OBJDUMP="${OBJDUMP}" + ac_cv_path_OBJDUMP="${OBJDUMP}" + fi + + if test -n "@DSYMUTIL@"; then + DSYMUTIL="@DSYMUTIL@" + ac_cv_path_DSYMUTIL="${DSYMUTIL}" fi fi diff --git a/depends/funcs.mk b/depends/funcs.mk index d51329cdc4..aeaff2288b 100644 --- a/depends/funcs.mk +++ b/depends/funcs.mk @@ -46,7 +46,7 @@ endef define int_get_build_id $(eval $(1)_dependencies += $($(1)_$(host_arch)_$(host_os)_dependencies) $($(1)_$(host_os)_dependencies)) -$(eval $(1)_all_dependencies:=$(call int_get_all_dependencies,$(1),$($($(1)_type)_native_toolchain) $($($(1)_type)_native_binutils) $($(1)_dependencies))) +$(eval $(1)_all_dependencies:=$(call int_get_all_dependencies,$(1),$($(1)_dependencies))) $(foreach dep,$($(1)_all_dependencies),$(eval $(1)_build_id_deps+=$(dep)-$($(dep)_version)-$($(dep)_recipe_hash))) $(eval $(1)_build_id_long:=$(1)-$($(1)_version)-$($(1)_recipe_hash)-$(release_type) $($(1)_build_id_deps) $($($(1)_type)_id)) $(eval $(1)_build_id:=$(shell echo -n "$($(1)_build_id_long)" | $(build_SHA256SUM) | cut -c-$(HASH_LENGTH))) @@ -297,6 +297,3 @@ $(foreach package,$(all_packages),$(eval $(call int_config_attach_build_config,$ #create build targets $(foreach package,$(all_packages),$(eval $(call int_add_cmds,$(package)))) - -#special exception: if a toolchain package exists, all non-native packages depend on it -$(foreach package,$(packages),$(eval $($(package)_extracted): |$($($(host_arch)_$(host_os)_native_toolchain)_cached) $($($(host_arch)_$(host_os)_native_binutils)_cached) )) diff --git a/depends/gen_id b/depends/gen_id index a0cd586461..83bc308542 100755 --- a/depends/gen_id +++ b/depends/gen_id @@ -50,7 +50,6 @@ echo "BEGIN AR" bash -c "${AR} --version" env | grep '^AR_' - echo "ZERO_AR_DATE=${ZERO_AR_DATE}" echo "END AR" echo "BEGIN RANLIB" diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk index a683a9bc34..564381d1e9 100644 --- a/depends/hosts/darwin.mk +++ b/depends/hosts/darwin.mk @@ -2,31 +2,10 @@ OSX_MIN_VERSION=11.0 OSX_SDK_VERSION=14.0 XCODE_VERSION=15.0 XCODE_BUILD_ID=15A240d -LD64_VERSION=711 +LLD_VERSION=711 OSX_SDK=$(SDK_PATH)/Xcode-$(XCODE_VERSION)-$(XCODE_BUILD_ID)-extracted-SDK-with-libcxx-headers -darwin_native_binutils=native_cctools - -ifeq ($(strip $(FORCE_USE_SYSTEM_CLANG)),) -# FORCE_USE_SYSTEM_CLANG is empty, so we use our depends-managed, pinned clang -# from llvm.org - -# Clang is a dependency of native_cctools when FORCE_USE_SYSTEM_CLANG is empty -darwin_native_toolchain=native_cctools - -clang_prog=$(build_prefix)/bin/clang -clangxx_prog=$(clang_prog)++ -llvm_config_prog=$(build_prefix)/bin/llvm-config - -darwin_OBJDUMP=$(build_prefix)/bin/$(host)-objdump - -else -# FORCE_USE_SYSTEM_CLANG is non-empty, so we use the clang from the user's -# system - -darwin_native_toolchain= - # We can't just use $(shell command -v clang) because GNU Make handles builtins # in a special way and doesn't know that `command` is a POSIX-standard builtin # prior to 1af314465e5dfe3e8baa839a32a72e83c04f26ef, first released in v4.2.90. @@ -36,22 +15,13 @@ darwin_native_toolchain= # Source: https://lists.gnu.org/archive/html/bug-make/2017-11/msg00017.html clang_prog=$(shell $(SHELL) $(.SHELLFLAGS) "command -v clang") clangxx_prog=$(shell $(SHELL) $(.SHELLFLAGS) "command -v clang++") -llvm_config_prog=$(shell $(SHELL) $(.SHELLFLAGS) "command -v llvm-config") - -llvm_lib_dir=$(shell $(llvm_config_prog) --libdir) +darwin_AR=$(shell $(SHELL) $(.SHELLFLAGS) "command -v llvm-ar") +darwin_DSYMUTIL=$(shell $(SHELL) $(.SHELLFLAGS) "command -v dsymutil") +darwin_NM=$(shell $(SHELL) $(.SHELLFLAGS) "command -v llvm-nm") darwin_OBJDUMP=$(shell $(SHELL) $(.SHELLFLAGS) "command -v llvm-objdump") -endif - -cctools_TOOLS=AR RANLIB STRIP NM - -# Make-only lowercase function -lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$1)))))))))))))))))))))))))) - -# For well-known tools provided by cctools, make sure that their well-known -# variable is set to the full path of the tool, just like how AC_PATH_{TOO,PROG} -# would. -$(foreach TOOL,$(cctools_TOOLS),$(eval darwin_$(TOOL) = $$(build_prefix)/bin/$$(host)-$(call lc,$(TOOL)))) +darwin_RANLIB=$(shell $(SHELL) $(.SHELLFLAGS) "command -v llvm-ranlib") +darwin_STRIP=$(shell $(SHELL) $(.SHELLFLAGS) "command -v llvm-strip") # Flag explanations: # @@ -60,11 +30,6 @@ $(foreach TOOL,$(cctools_TOOLS),$(eval darwin_$(TOOL) = $$(build_prefix)/bin/$$( # Ensures that modern linker features are enabled. See here for more # details: https://github.com/bitcoin/bitcoin/pull/19407. # -# -B$(build_prefix)/bin -# -# Explicitly point to our binaries (e.g. cctools) so that they are -# ensured to be found and preferred over other possibilities. -# # -isysroot$(OSX_SDK) -nostdlibinc # # Disable default include paths built into the compiler as well as @@ -79,12 +44,16 @@ $(foreach TOOL,$(cctools_TOOLS),$(eval darwin_$(TOOL) = $$(build_prefix)/bin/$$( # # Indicate to the linker the platform, the oldest supported version, # and the SDK used. +# +# -no_adhoc_codesign +# +# Disable adhoc codesigning (for now) when using LLVM tooling, to avoid +# non-determinism issues with the Identifier field. darwin_CC=env -u C_INCLUDE_PATH -u CPLUS_INCLUDE_PATH \ -u OBJC_INCLUDE_PATH -u OBJCPLUS_INCLUDE_PATH -u CPATH \ -u LIBRARY_PATH \ $(clang_prog) --target=$(host) \ - -B$(build_prefix)/bin \ -isysroot$(OSX_SDK) -nostdlibinc \ -iwithsysroot/usr/include -iframeworkwithsysroot/System/Library/Frameworks @@ -92,18 +61,18 @@ darwin_CXX=env -u C_INCLUDE_PATH -u CPLUS_INCLUDE_PATH \ -u OBJC_INCLUDE_PATH -u OBJCPLUS_INCLUDE_PATH -u CPATH \ -u LIBRARY_PATH \ $(clangxx_prog) --target=$(host) \ - -B$(build_prefix)/bin \ -isysroot$(OSX_SDK) -nostdlibinc \ -iwithsysroot/usr/include/c++/v1 \ -iwithsysroot/usr/include -iframeworkwithsysroot/System/Library/Frameworks -darwin_CFLAGS=-pipe -std=$(C_STANDARD) -mmacosx-version-min=$(OSX_MIN_VERSION) -darwin_CXXFLAGS=-pipe -std=$(CXX_STANDARD) -mmacosx-version-min=$(OSX_MIN_VERSION) +darwin_CFLAGS=-pipe -std=$(C_STANDARD) -mmacos-version-min=$(OSX_MIN_VERSION) +darwin_CXXFLAGS=-pipe -std=$(CXX_STANDARD) -mmacos-version-min=$(OSX_MIN_VERSION) darwin_LDFLAGS=-Wl,-platform_version,macos,$(OSX_MIN_VERSION),$(OSX_SDK_VERSION) ifneq ($(build_os),darwin) -darwin_CFLAGS += -mlinker-version=$(LD64_VERSION) -darwin_CXXFLAGS += -mlinker-version=$(LD64_VERSION) +darwin_CFLAGS += -mlinker-version=$(LLD_VERSION) +darwin_CXXFLAGS += -mlinker-version=$(LLD_VERSION) +darwin_LDFLAGS += -Wl,-no_adhoc_codesign -fuse-ld=lld endif darwin_release_CFLAGS=-O2 diff --git a/depends/hosts/default.mk b/depends/hosts/default.mk index c9ee7cc950..d82c33f29c 100644 --- a/depends/hosts/default.mk +++ b/depends/hosts/default.mk @@ -38,5 +38,5 @@ host_$1 = $$($(host_arch)_$(host_os)_$1) host_$(release_type)_$1 = $$($(host_arch)_$(host_os)_$(release_type)_$1) endef -$(foreach tool,CC CXX AR RANLIB STRIP NM OBJCOPY OBJDUMP,$(eval $(call add_host_tool_func,$(tool)))) +$(foreach tool,CC CXX AR RANLIB STRIP NM OBJCOPY OBJDUMP DSYMUTIL,$(eval $(call add_host_tool_func,$(tool)))) $(foreach flags,CFLAGS CXXFLAGS CPPFLAGS LDFLAGS, $(eval $(call add_host_flags_func,$(flags)))) diff --git a/depends/packages/gmp.mk b/depends/packages/gmp.mk index ff0dda5835..3d645cd02a 100644 --- a/depends/packages/gmp.mk +++ b/depends/packages/gmp.mk @@ -3,6 +3,7 @@ $(package)_version=6.3.0 $(package)_download_path=https://ftp.gnu.org/gnu/gmp $(package)_file_name=gmp-$($(package)_version).tar.bz2 $(package)_sha256_hash=ac28211a7cfb609bae2e2c8d6058d66c8fe96434f740cf6fe2e47b000d1c20cb +$(package)_patches=include_ldflags_in_configure.patch define $(package)_set_vars $(package)_config_opts += --disable-shared --enable-cxx --enable-fat @@ -11,6 +12,10 @@ $(package)_cflags_armv7l += -march=armv7-a $(package)_cflags_x86_64 += -march=x86-64 endef +define $(package)_preprocess_cmds + patch -p1 < $($(package)_patch_dir)/include_ldflags_in_configure.patch +endef + define $(package)_config_cmds $($(package)_autoconf) endef diff --git a/depends/packages/native_cctools.mk b/depends/packages/native_cctools.mk deleted file mode 100644 index 3148e51048..0000000000 --- a/depends/packages/native_cctools.mk +++ /dev/null @@ -1,39 +0,0 @@ -package=native_cctools -$(package)_version=c74fafe86076713cb8e6f937af43b6df6da1f42d -$(package)_download_path=https://github.com/tpoechtrager/cctools-port/archive -$(package)_file_name=$($(package)_version).tar.gz -$(package)_sha256_hash=e2c1588d505a69c32e079f4e616e0f117d5478429040e394f624f43f2796e6bc -$(package)_build_subdir=cctools -$(package)_dependencies=native_libtapi - -define $(package)_set_vars - $(package)_config_opts=--target=$(host) --enable-lto-support - $(package)_config_opts+=--with-llvm-config=$(llvm_config_prog) - $(package)_ldflags+=-Wl,-rpath=\\$$$$$$$$\$$$$$$$$ORIGIN/../lib - $(package)_cc=$(clang_prog) - $(package)_cxx=$(clangxx_prog) -endef - -ifneq ($(strip $(FORCE_USE_SYSTEM_CLANG)),) -define $(package)_preprocess_cmds - mkdir -p $($(package)_staging_prefix_dir)/lib && \ - cp $(llvm_lib_dir)/libLTO.so $($(package)_staging_prefix_dir)/lib/ -endef -else -endif - -define $(package)_config_cmds - $($(package)_autoconf) -endef - -define $(package)_build_cmds - $(MAKE) -endef - -define $(package)_stage_cmds - $(MAKE) DESTDIR=$($(package)_staging_dir) install -endef - -define $(package)_postprocess_cmds - rm -rf share -endef diff --git a/depends/packages/native_ds_store.mk b/depends/packages/native_ds_store.mk deleted file mode 100644 index 51a95f48ef..0000000000 --- a/depends/packages/native_ds_store.mk +++ /dev/null @@ -1,15 +0,0 @@ -package=native_ds_store -$(package)_version=1.3.0 -$(package)_download_path=https://github.com/dmgbuild/ds_store/archive/ -$(package)_file_name=v$($(package)_version).tar.gz -$(package)_sha256_hash=76b3280cd4e19e5179defa23fb594a9dd32643b0c80d774bd3108361d94fb46d -$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages - -define $(package)_build_cmds - python3 setup.py build -endef - -define $(package)_stage_cmds - mkdir -p $($(package)_install_libdir) && \ - python3 setup.py install --root=$($(package)_staging_dir) --prefix=$(build_prefix) --install-lib=$($(package)_install_libdir) -endef diff --git a/depends/packages/native_libtapi.mk b/depends/packages/native_libtapi.mk deleted file mode 100644 index fb5ab0b4dc..0000000000 --- a/depends/packages/native_libtapi.mk +++ /dev/null @@ -1,22 +0,0 @@ -package=native_libtapi -$(package)_version=eb33a59f2e30ff9724dc1ea8bee8b5229b0557c9 -$(package)_download_path=https://github.com/tpoechtrager/apple-libtapi/archive -$(package)_file_name=$($(package)_version).tar.gz -$(package)_sha256_hash=d4d46c64622f13d6938cecf989046d9561011bb59e8ee835f8f39825d67f578f -$(package)_patches=disable_zlib.patch - -ifeq ($(strip $(FORCE_USE_SYSTEM_CLANG)),) -$(package)_dependencies=native_llvm -endif - -define $(package)_preprocess_cmds - patch -p1 < $($(package)_patch_dir)/disable_zlib.patch -endef - -define $(package)_build_cmds - CC=$(clang_prog) CXX=$(clangxx_prog) INSTALLPREFIX=$($(package)_staging_prefix_dir) ./build.sh -endef - -define $(package)_stage_cmds - ./install.sh -endef diff --git a/depends/packages/native_llvm.mk b/depends/packages/native_llvm.mk deleted file mode 100644 index 1953c91bf4..0000000000 --- a/depends/packages/native_llvm.mk +++ /dev/null @@ -1,26 +0,0 @@ -package=native_llvm -$(package)_version=17.0.6 -$(package)_major_version=$(firstword $(subst ., ,$($(package)_version))) -$(package)_download_path=https://github.com/llvm/llvm-project/releases/download/llvmorg-$($(package)_version) -ifneq (,$(findstring aarch64,$(BUILD))) -$(package)_file_name=clang+llvm-$($(package)_version)-aarch64-linux-gnu.tar.xz -$(package)_sha256_hash=6dd62762285326f223f40b8e4f2864b5c372de3f7de0731cb7cd55ca5287b75a -else -$(package)_file_name=clang+llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-22.04.tar.xz -$(package)_sha256_hash=884ee67d647d77e58740c1e645649e29ae9e8a6fe87c1376be0f3a30f3cc9ab3 -endif - -define $(package)_stage_cmds - mkdir -p $($(package)_staging_prefix_dir)/lib/clang/$($(package)_major_version)/include && \ - mkdir -p $($(package)_staging_prefix_dir)/bin && \ - mkdir -p $($(package)_staging_prefix_dir)/include/llvm-c && \ - cp bin/clang $($(package)_staging_prefix_dir)/bin/ && \ - cp -P bin/clang++ $($(package)_staging_prefix_dir)/bin/ && \ - cp bin/dsymutil $($(package)_staging_prefix_dir)/bin/$(host)-dsymutil && \ - cp bin/llvm-config $($(package)_staging_prefix_dir)/bin/ && \ - cp bin/llvm-objdump $($(package)_staging_prefix_dir)/bin/$(host)-objdump && \ - cp include/llvm-c/ExternC.h $($(package)_staging_prefix_dir)/include/llvm-c && \ - cp include/llvm-c/lto.h $($(package)_staging_prefix_dir)/include/llvm-c && \ - cp lib/libLTO.so $($(package)_staging_prefix_dir)/lib/ && \ - cp -r lib/clang/$($(package)_major_version)/include/* $($(package)_staging_prefix_dir)/lib/clang/$($(package)_major_version)/include/ -endef diff --git a/depends/packages/native_mac_alias.mk b/depends/packages/native_mac_alias.mk deleted file mode 100644 index ddd631186e..0000000000 --- a/depends/packages/native_mac_alias.mk +++ /dev/null @@ -1,15 +0,0 @@ -package=native_mac_alias -$(package)_version=2.2.0 -$(package)_download_path=https://github.com/dmgbuild/mac_alias/archive/ -$(package)_file_name=v$($(package)_version).tar.gz -$(package)_sha256_hash=421e6d7586d1f155c7db3e7da01ca0dacc9649a509a253ad7077b70174426499 -$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages - -define $(package)_build_cmds - python3 setup.py build -endef - -define $(package)_stage_cmds - mkdir -p $($(package)_install_libdir) && \ - python3 setup.py install --root=$($(package)_staging_dir) --prefix=$(build_prefix) --install-lib=$($(package)_install_libdir) -endef diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 65044553a2..ea64a497dd 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -23,14 +23,3 @@ multiprocess_packages = libmultiprocess capnp multiprocess_native_packages = native_libmultiprocess native_capnp usdt_linux_packages=systemtap - -darwin_native_packages = native_ds_store native_mac_alias - -ifneq ($(build_os),darwin) -darwin_native_packages += native_cctools native_libtapi - -ifeq ($(strip $(FORCE_USE_SYSTEM_CLANG)),) -darwin_native_packages+= native_llvm -endif - -endif diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 6cb6e53ed7..67d6b812b7 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -15,6 +15,7 @@ $(package)_patches += no-xlib.patch $(package)_patches += fix_android_jni_static.patch $(package)_patches += dont_hardcode_pwd.patch $(package)_patches += qtbase-moc-ignore-gcc-macro.patch +$(package)_patches += no_warnings_for_symbols.patch $(package)_patches += rcc_hardcode_timestamp.patch $(package)_patches += duplicate_lcqpafonts.patch $(package)_patches += guix_cross_lib_path.patch @@ -138,7 +139,7 @@ ifneq ($(build_os),darwin) $(package)_config_opts_darwin += -xplatform macx-clang-linux $(package)_config_opts_darwin += -device-option MAC_SDK_PATH=$(OSX_SDK) $(package)_config_opts_darwin += -device-option MAC_SDK_VERSION=$(OSX_SDK_VERSION) -$(package)_config_opts_darwin += -device-option CROSS_COMPILE="$(host)-" +$(package)_config_opts_darwin += -device-option CROSS_COMPILE="llvm-" $(package)_config_opts_darwin += -device-option MAC_TARGET=$(host) $(package)_config_opts_darwin += -device-option XCODE_VERSION=$(XCODE_VERSION) endif @@ -248,6 +249,7 @@ define $(package)_preprocess_cmds patch -p1 -i $($(package)_patch_dir)/no-xlib.patch && \ patch -p1 -i $($(package)_patch_dir)/qtbase-moc-ignore-gcc-macro.patch && \ patch -p1 -i $($(package)_patch_dir)/memory_resource.patch && \ + patch -p1 -i $($(package)_patch_dir)/no_warnings_for_symbols.patch && \ patch -p1 -i $($(package)_patch_dir)/clang_18_libpng.patch && \ patch -p1 -i $($(package)_patch_dir)/rcc_hardcode_timestamp.patch && \ patch -p1 -i $($(package)_patch_dir)/duplicate_lcqpafonts.patch && \ diff --git a/depends/patches/gmp/include_ldflags_in_configure.patch b/depends/patches/gmp/include_ldflags_in_configure.patch new file mode 100644 index 0000000000..8ddc304da0 --- /dev/null +++ b/depends/patches/gmp/include_ldflags_in_configure.patch @@ -0,0 +1,621 @@ +Use LDFLAGS when configure is compiling test programs. + +Needed for macOS cross-compilation support using lld (ld64.lld) as +a linker, done by including '-fuse-ld=lld' in LDFLAGS. Defining it +in CC or CXX will result in unused argument warnings if the compiler +isn't expected to link files. + +diff --git a/acinclude.m4 b/acinclude.m4 +index 9cf9483..99edd43 100644 +--- a/acinclude.m4 ++++ b/acinclude.m4 +@@ -1752,7 +1752,7 @@ AC_CACHE_CHECK([if globals are prefixed by underscore], + cat >conftest.c <conftest.out + if grep "[[ ]]_gurkmacka" conftest.out >/dev/null; then +@@ -1984,7 +1984,7 @@ const int foo[[]] = {1,2,3}; + EOF + echo "Test program:" >&AC_FD_CC + cat conftest.c >&AC_FD_CC +-gmp_compile="$CC $CFLAGS $CPPFLAGS -S conftest.c >&AC_FD_CC" ++gmp_compile="$CC $CFLAGS $CPPFLAGS $LDFLAGS -S conftest.c >&AC_FD_CC" + if AC_TRY_EVAL(gmp_compile); then + echo "Compiler output:" >&AC_FD_CC + cat conftest.s >&AC_FD_CC +@@ -2382,7 +2382,7 @@ for tmp_underscore in "" "_"; do + ${tmp_gsym_prefix}main$gmp_cv_asm_label_suffix + addl $ ${tmp_underscore}_GLOBAL_OFFSET_TABLE_, %ebx + EOF +- gmp_compile="$CCAS $CFLAGS $CPPFLAGS $lt_prog_compiler_pic conftest.s >&AC_FD_CC && $CC $CFLAGS $CPPFLAGS $lt_prog_compiler_pic conftest.$OBJEXT >&AC_FD_CC" ++ gmp_compile="$CCAS $CFLAGS $CPPFLAGS $LDFLAGS $lt_prog_compiler_pic conftest.s >&AC_FD_CC && $CC $CFLAGS $CPPFLAGS $LDFLAGS $lt_prog_compiler_pic conftest.$OBJEXT >&AC_FD_CC" + if AC_TRY_EVAL(gmp_compile); then + if test "$tmp_underscore" = "_"; then + gmp_cv_asm_x86_got_underscore=yes +@@ -3019,7 +3019,7 @@ int *bar() { return &foo; } + EOF + echo "Test program:" >&AC_FD_CC + cat conftest.c >&AC_FD_CC +-gmp_compile="$CC $CFLAGS $CPPFLAGS -S conftest.c >&AC_FD_CC" ++gmp_compile="$CC $CFLAGS $CPPFLAGS $LDFLAGS -S conftest.c >&AC_FD_CC" + if AC_TRY_EVAL(gmp_compile); then + echo "Compiler output:" >&AC_FD_CC + cat conftest.s >&AC_FD_CC +@@ -3164,7 +3164,7 @@ AC_DEFUN([GMP_C_ATTRIBUTE_MALLOC], + [cat >conftest.c </dev/null; then + gmp_cv_c_attribute_malloc=no +@@ -3279,7 +3279,7 @@ int main(){ + return 0; + }] + EOF +-gmp_compile="$CC $CFLAGS $CPPFLAGS conftest.c -o conftest$EXEEXT >&AC_FD_CC 2>&1" ++gmp_compile="$CC $CFLAGS $CPPFLAGS $LDFLAGS conftest.c -o conftest$EXEEXT >&AC_FD_CC 2>&1" + if AC_TRY_EVAL(gmp_compile); then + cat >conftest.awk <<\EOF + [ +diff --git a/configure b/configure +index 7910aa0..15121e2 100755 +--- a/configure ++++ b/configure +@@ -5885,7 +5885,7 @@ for abi in $abilist; do + choke me + #endif + EOF +-gmp_compile="$cc -c conftest.c >&5" ++gmp_compile="$cc $LDFLAGS -c conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -5978,7 +5978,7 @@ if test "$gmp_prog_cc_works" = yes; then + int main () { return 0; } + EOF + echo "Test compile: " >&5 +- gmp_compile="$cc $cflags $cppflags conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -6032,7 +6032,7 @@ void *f() { return g(); } + int main () { return 0; } + EOF + echo "Test compile: function pointer return" >&5 +- gmp_compile="$cc $cflags $cppflags conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -6088,7 +6088,7 @@ int cmov () { return (n >= 0 ? n : 0); } + int main () { return 0; } + EOF + echo "Test compile: cmov instruction" >&5 +- gmp_compile="$cc $cflags $cppflags conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -6145,7 +6145,7 @@ unsigned long gcc303 () { return (unsigned long) d; } + int main () { return 0; } + EOF + echo "Test compile: double -> ulong conversion" >&5 +- gmp_compile="$cc $cflags $cppflags conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -6200,7 +6200,7 @@ unsigned long fneg () { return -fneg_data; } + int main () { return 0; } + EOF + echo "Test compile: double negation" >&5 +- gmp_compile="$cc $cflags $cppflags conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -6256,7 +6256,7 @@ float ftod () { return (float) ftod_data; } + int main () { return 0; } + EOF + echo "Test compile: double -> float conversion" >&5 +- gmp_compile="$cc $cflags $cppflags conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -6341,7 +6341,7 @@ param_init () + int main () { return 0; } + EOF + echo "Test compile: gnupro alpha ev6 char spilling" >&5 +- gmp_compile="$cc $cflags $cppflags conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -6392,7 +6392,7 @@ if test "$gmp_prog_cc_works" = yes; then + int k; int foo () { __builtin_alloca (k); } + EOF + echo "Test compile: __builtin_alloca availability" >&5 +- gmp_compile="$cc $cflags $cppflags conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -6438,7 +6438,7 @@ int foo () + int main () { return 0; } + EOF + echo "Test compile: alloca array" >&5 +- gmp_compile="$cc $cflags $cppflags conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -6516,7 +6516,7 @@ int f () + int main () { return 0; } + EOF + echo "Test compile: abs int -> double conversion" >&5 +- gmp_compile="$cc $cflags $cppflags conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -6581,7 +6581,7 @@ int dummy; + int main () { return 0; } + EOF + echo "Test compile: long long reliability test 1" >&5 +- gmp_compile="$cc $cflags $cppflags conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -6642,7 +6642,7 @@ int dummy; + int main () { return 0; } + EOF + echo "Test compile: long long reliability test 2" >&5 +- gmp_compile="$cc $cflags $cppflags conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -6703,7 +6703,7 @@ int dummy; + int main () { return 0; } + EOF + echo "Test compile: freebsd hacked gcc" >&5 +- gmp_compile="$cc $cflags $cppflags conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -6802,7 +6802,7 @@ main () + + EOF + echo "Test compile: mpn_lshift_com optimization" >&5 +- gmp_compile="$cc $cflags $cppflags conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -6911,7 +6911,7 @@ main () + + EOF + echo "Test compile: mpn_lshift_com optimization 2" >&5 +- gmp_compile="$cc $cflags $cppflags conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -6970,7 +6970,7 @@ int foo; + int bar () { return foo; } + EOF + tmp_got_emitted=no +-gmp_compile="$cc $cflags $cppflags -fPIC -S conftest.c >&5 2>&1" ++gmp_compile="$cc $cflags $cppflags $LDFLAGS -fPIC -S conftest.c >&5 2>&1" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7044,7 +7044,7 @@ cat >conftest.s <<\EOF + .byte 254, 220, 186, 152, 118, 84, 50, 16 + EOF + tmp_got_good=yes +-gmp_compile="$cc $cflags $cppflags -fPIC -o conftest.o -c conftest.s >&5 2>&1" ++gmp_compile="$cc $cflags $cppflags $LDFLAGS -fPIC -o conftest.o -c conftest.s >&5 2>&1" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7094,7 +7094,7 @@ long long bar () { return foo; } + int main () { return 0; } + EOF + gmp_prog_cc_works=no +-gmp_compile="$cc $cflags $cppflags -c conftest.c >&5" ++gmp_compile="$cc $cflags $cppflags $LDFLAGS -c conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7221,7 +7221,7 @@ result=no + cat >conftest.s <&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7256,7 +7256,7 @@ main () + } + EOF + gmp_c_testlist_sizeof=no +-gmp_compile="$cc $cflags -c conftest.c >&5" ++gmp_compile="$cc $cflags $LDFLAGS -c conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7424,7 +7424,7 @@ _main: + xorl %eax, %eax + ret + EOF +- gmp_compile="$cc $cflags $cppflags conftest.s -o conftest >&5" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS conftest.s -o conftest >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7489,7 +7489,7 @@ $as_echo_n "checking compiler $cc $cflags -no-cpp-precomp... " >&6; } + cat >conftest.c <&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7522,7 +7522,7 @@ result=no + cat >conftest.c <&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7553,7 +7553,7 @@ result=no + cat >conftest.c <&5 +-gmp_compile="$cc $cflags $cppflags -c conftest.c >&5 2>&1" ++gmp_compile="$cc $cflags $cppflags $LDFLAGS -c conftest.c >&5 2>&1" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7561,7 +7561,7 @@ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + test $ac_status = 0; }; then : ; + else + # empty fails +- gmp_compile="$cc $cflags $cppflags -Wa,-oldas -c conftest.c >&5 2>&1" ++ gmp_compile="$cc $cflags $cppflags $LDFLAGS -Wa,-oldas -c conftest.c >&5 2>&1" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7597,7 +7597,7 @@ if test "$gmp_prog_cc_works" = yes; then + int main () { return 0; } + EOF + echo "Test compile: " >&5 +- gmp_compile="$cc $cflags $cppflags $flag conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7651,7 +7651,7 @@ void *f() { return g(); } + int main () { return 0; } + EOF + echo "Test compile: function pointer return" >&5 +- gmp_compile="$cc $cflags $cppflags $flag conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7707,7 +7707,7 @@ int cmov () { return (n >= 0 ? n : 0); } + int main () { return 0; } + EOF + echo "Test compile: cmov instruction" >&5 +- gmp_compile="$cc $cflags $cppflags $flag conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7764,7 +7764,7 @@ unsigned long gcc303 () { return (unsigned long) d; } + int main () { return 0; } + EOF + echo "Test compile: double -> ulong conversion" >&5 +- gmp_compile="$cc $cflags $cppflags $flag conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7819,7 +7819,7 @@ unsigned long fneg () { return -fneg_data; } + int main () { return 0; } + EOF + echo "Test compile: double negation" >&5 +- gmp_compile="$cc $cflags $cppflags $flag conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7875,7 +7875,7 @@ float ftod () { return (float) ftod_data; } + int main () { return 0; } + EOF + echo "Test compile: double -> float conversion" >&5 +- gmp_compile="$cc $cflags $cppflags $flag conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -7960,7 +7960,7 @@ param_init () + int main () { return 0; } + EOF + echo "Test compile: gnupro alpha ev6 char spilling" >&5 +- gmp_compile="$cc $cflags $cppflags $flag conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -8011,7 +8011,7 @@ if test "$gmp_prog_cc_works" = yes; then + int k; int foo () { __builtin_alloca (k); } + EOF + echo "Test compile: __builtin_alloca availability" >&5 +- gmp_compile="$cc $cflags $cppflags $flag conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -8057,7 +8057,7 @@ int foo () + int main () { return 0; } + EOF + echo "Test compile: alloca array" >&5 +- gmp_compile="$cc $cflags $cppflags $flag conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -8135,7 +8135,7 @@ int f () + int main () { return 0; } + EOF + echo "Test compile: abs int -> double conversion" >&5 +- gmp_compile="$cc $cflags $cppflags $flag conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -8200,7 +8200,7 @@ int dummy; + int main () { return 0; } + EOF + echo "Test compile: long long reliability test 1" >&5 +- gmp_compile="$cc $cflags $cppflags $flag conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -8261,7 +8261,7 @@ int dummy; + int main () { return 0; } + EOF + echo "Test compile: long long reliability test 2" >&5 +- gmp_compile="$cc $cflags $cppflags $flag conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -8322,7 +8322,7 @@ int dummy; + int main () { return 0; } + EOF + echo "Test compile: freebsd hacked gcc" >&5 +- gmp_compile="$cc $cflags $cppflags $flag conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -8421,7 +8421,7 @@ main () + + EOF + echo "Test compile: mpn_lshift_com optimization" >&5 +- gmp_compile="$cc $cflags $cppflags $flag conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -8530,7 +8530,7 @@ main () + + EOF + echo "Test compile: mpn_lshift_com optimization 2" >&5 +- gmp_compile="$cc $cflags $cppflags $flag conftest.c >&5" ++ gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -8589,7 +8589,7 @@ int foo; + int bar () { return foo; } + EOF + tmp_got_emitted=no +-gmp_compile="$cc $cflags $cppflags $flag -fPIC -S conftest.c >&5 2>&1" ++gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS -fPIC -S conftest.c >&5 2>&1" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -8663,7 +8663,7 @@ cat >conftest.s <<\EOF + .byte 254, 220, 186, 152, 118, 84, 50, 16 + EOF + tmp_got_good=yes +-gmp_compile="$cc $cflags $cppflags $flag -fPIC -o conftest.o -c conftest.s >&5 2>&1" ++gmp_compile="$cc $cflags $cppflags $flag $LDFLAGS -fPIC -o conftest.o -c conftest.s >&5 2>&1" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -9974,7 +9974,7 @@ main () + return 0; + } + EOF +-gmp_compile="$HOST_CC conftest.c" ++gmp_compile="$HOST_CC $LDFLAGS conftest.c" + cc_for_build_works=no + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 +@@ -10027,7 +10027,7 @@ else + fi + + else +- for i in "$CC" "$CC $CFLAGS $CPPFLAGS" cc gcc c89 c99; do ++ for i in "$CC" "$CC $CFLAGS $CPPFLAGS $LDFLAGS" cc gcc c89 c99; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system compiler $i" >&5 + $as_echo_n "checking build system compiler $i... " >&6; } + # remove anything that might look like compiler output to our "||" expression +@@ -10080,7 +10080,7 @@ else + #define FOO BAR + EOF + echo "Test compile: " >&5 +- gmp_cxxcompile="$CXX $CPPFLAGS $CXXFLAGS conftest.cc >&5" ++ gmp_cxxcompile="$CXX $CPPFLAGS $CXXFLAGS $LDFLAGS conftest.cc >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_cxxcompile\""; } >&5 + (eval $gmp_cxxcompile) 2>&5 + ac_status=$? +@@ -10570,7 +10570,7 @@ using namespace foo; + int main (void) { return 0; } + EOF + echo "Test compile: namespace" >&5 +- gmp_cxxcompile="$CXX $CPPFLAGS $CXXFLAGS conftest.cc >&5" ++ gmp_cxxcompile="$CXX $CPPFLAGS $CXXFLAGS $LDFLAGS conftest.cc >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_cxxcompile\""; } >&5 + (eval $gmp_cxxcompile) 2>&5 + ac_status=$? +@@ -10616,7 +10616,7 @@ void someoutput (void) { std::cout << 123; } + int main (void) { return 0; } + EOF + echo "Test compile: std iostream" >&5 +- gmp_cxxcompile="$CXX $CPPFLAGS $CXXFLAGS conftest.cc >&5" ++ gmp_cxxcompile="$CXX $CPPFLAGS $CXXFLAGS $LDFLAGS conftest.cc >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_cxxcompile\""; } >&5 + (eval $gmp_cxxcompile) 2>&5 + ac_status=$? +@@ -23651,7 +23651,7 @@ else + cat >conftest.c <&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -24421,7 +24421,7 @@ int main(){ + return 0; + } + EOF +-gmp_compile="$CC $CFLAGS $CPPFLAGS conftest.c -o conftest$EXEEXT >&5 2>&1" ++gmp_compile="$CC $CFLAGS $CPPFLAGS $LDFLAGS conftest.c -o conftest$EXEEXT >&5 2>&1" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -25833,7 +25833,7 @@ else + cat >conftest.c <&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -25914,7 +25914,7 @@ const int foo[] = {1,2,3}; + EOF + echo "Test program:" >&5 + cat conftest.c >&5 +-gmp_compile="$CC $CFLAGS $CPPFLAGS -S conftest.c >&5" ++gmp_compile="$CC $CFLAGS $CPPFLAGS $LDFLAGS -S conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -26580,7 +26580,7 @@ int *bar() { return &foo; } + EOF + echo "Test program:" >&5 + cat conftest.c >&5 +-gmp_compile="$CC $CFLAGS $CPPFLAGS -S conftest.c >&5" ++gmp_compile="$CC $CFLAGS $CPPFLAGS $LDFLAGS -S conftest.c >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +@@ -27031,7 +27031,7 @@ for tmp_underscore in "" "_"; do + ${tmp_gsym_prefix}main$gmp_cv_asm_label_suffix + addl $ ${tmp_underscore}_GLOBAL_OFFSET_TABLE_, %ebx + EOF +- gmp_compile="$CCAS $CFLAGS $CPPFLAGS $lt_prog_compiler_pic conftest.s >&5 && $CC $CFLAGS $CPPFLAGS $lt_prog_compiler_pic conftest.$OBJEXT >&5" ++ gmp_compile="$CCAS $CFLAGS $CPPFLAGS $LDFLAGS $lt_prog_compiler_pic conftest.s >&5 && $CC $CFLAGS $CPPFLAGS $LDFLAGS $lt_prog_compiler_pic conftest.$OBJEXT >&5" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5 + (eval $gmp_compile) 2>&5 + ac_status=$? +diff --git a/configure.ac b/configure.ac +index 082077b..f43e1c1 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2272,14 +2272,14 @@ for abi in $abilist; do + instrument) cflags="$cflags -finstrument-functions" ;; + esac + +- GMP_PROG_CC_WORKS($cc $cflags $cppflags,,continue) ++ GMP_PROG_CC_WORKS($cc $cflags $cppflags $LDFLAGS,,continue) + + # If we're supposed to be using a "long long" for a limb, check that + # it works. + eval limb_chosen=\"\$limb$abi1\" + test -n "$limb_chosen" || eval limb_chosen=\"\$limb$abi2\" + if test "$limb_chosen" = longlong; then +- GMP_PROG_CC_WORKS_LONGLONG($cc $cflags $cppflags,,continue) ++ GMP_PROG_CC_WORKS_LONGLONG($cc $cflags $cppflags $LDFLAGS,,continue) + fi + + # The tests to perform on this $cc, if any +@@ -2294,8 +2294,8 @@ for abi in $abilist; do + hpc-hppa-2-0) GMP_HPC_HPPA_2_0($cc,,testlist_pass=no) ;; + gcc-arm-umodsi) GMP_GCC_ARM_UMODSI($cc,,testlist_pass=no) ;; + gcc-mips-o32) GMP_GCC_MIPS_O32($cc,,testlist_pass=no) ;; +- hppa-level-2.0) GMP_HPPA_LEVEL_20($cc $cflags,,testlist_pass=no) ;; +- sizeof*) GMP_C_TEST_SIZEOF($cc $cflags,$tst,,testlist_pass=no) ;; ++ hppa-level-2.0) GMP_HPPA_LEVEL_20($cc $cflags $LDFLAGS,,testlist_pass=no) ;; ++ sizeof*) GMP_C_TEST_SIZEOF($cc $cflags $LDFLAGS,$tst,,testlist_pass=no) ;; + esac + if test $testlist_pass = no; then break; fi + done +@@ -2415,8 +2415,8 @@ if test $found_compiler = yes; then + # pentium4 case. + # + if test "$abi" = 32; then +- GMP_GCC_PENTIUM4_SSE2($cc $cflags $cppflags,, continue) +- GMP_OS_X86_XMM($cc $cflags $cppflags,, continue) ++ GMP_GCC_PENTIUM4_SSE2($cc $cflags $cppflags $LDFLAGS,, continue) ++ GMP_OS_X86_XMM($cc $cflags $cppflags $LDFLAGS,, continue) + fi + ;; + -no-cpp-precomp) +@@ -2429,19 +2429,19 @@ if test $found_compiler = yes; then + -Wa,-m*) + case $host in + alpha*-*-*) +- GMP_GCC_WA_MCPU($cc $cflags, $flag, , [continue]) ++ GMP_GCC_WA_MCPU($cc $cflags $LDFLAGS, $flag, , [continue]) + ;; + esac + ;; + -Wa,-oldas) +- GMP_GCC_WA_OLDAS($cc $cflags $cppflags, ++ GMP_GCC_WA_OLDAS($cc $cflags $cppflags $LDFLAGS, + [cflags="$cflags $flag" + break], + [continue]) + ;; + esac + +- GMP_PROG_CC_WORKS($cc $cflags $cppflags $flag, ++ GMP_PROG_CC_WORKS($cc $cflags $cppflags $flag $LDFLAGS, + [cflags="$cflags $flag" + break]) + done diff --git a/depends/patches/native_libtapi/disable_zlib.patch b/depends/patches/native_libtapi/disable_zlib.patch deleted file mode 100644 index 6c7691214a..0000000000 --- a/depends/patches/native_libtapi/disable_zlib.patch +++ /dev/null @@ -1,17 +0,0 @@ -build: disable zlib - -This isn't needed, and causes issues when clang-tblgen -is built, but trys to reach for a system libz.so. - -diff --git a/build.sh b/build.sh -index e25d2f732..ec8422621 100755 ---- a/build.sh -+++ b/build.sh -@@ -66,6 +66,7 @@ cmake ../src/llvm \ - -DCMAKE_INSTALL_PREFIX=$INSTALLPREFIX \ - -DTAPI_REPOSITORY_STRING=$TAPI_VERSION \ - -DTAPI_FULL_VERSION=$TAPI_VERSION \ -+ -DLLVM_ENABLE_ZLIB=OFF \ - $CMAKE_EXTRA_ARGS - - echo "" diff --git a/depends/patches/qt/mac-qmake.conf b/depends/patches/qt/mac-qmake.conf index cb94bf07b4..a29db20004 100644 --- a/depends/patches/qt/mac-qmake.conf +++ b/depends/patches/qt/mac-qmake.conf @@ -13,6 +13,7 @@ QMAKE_MAC_SDK.macosx.Path = $${MAC_SDK_PATH} QMAKE_MAC_SDK.macosx.platform_name = macosx QMAKE_MAC_SDK.macosx.SDKVersion = $${MAC_SDK_VERSION} QMAKE_MAC_SDK.macosx.PlatformPath = /phony +QMAKE_CXXFLAGS += -fuse-ld=lld !host_build: QMAKE_CFLAGS += -target $${MAC_TARGET} !host_build: QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_CFLAGS !host_build: QMAKE_CXXFLAGS += -target $${MAC_TARGET} diff --git a/depends/patches/qt/no_warnings_for_symbols.patch b/depends/patches/qt/no_warnings_for_symbols.patch new file mode 100644 index 0000000000..11cdc599ed --- /dev/null +++ b/depends/patches/qt/no_warnings_for_symbols.patch @@ -0,0 +1,11 @@ +--- a/qtbase/mkspecs/features/mac/no_warn_empty_obj_files.prf ++++ b/qtbase/mkspecs/features/mac/no_warn_empty_obj_files.prf +@@ -1,7 +1,7 @@ + # Prevent warnings about object files without any symbols. This is a common + # thing in Qt as we tend to build files unconditionally, and then use ifdefs + # to compile out parts that are not relevant. +-QMAKE_RANLIB += -no_warning_for_no_symbols ++# QMAKE_RANLIB += -no_warning_for_no_symbols + + # We have to tell 'ar' to not run ranlib by itself + QMAKE_AR += -S diff --git a/doc/build-osx.md b/doc/build-osx.md index 2c020c2670..c532dc9648 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -213,14 +213,8 @@ brew install python #### Deploy Dependencies -You can deploy a `.dmg` containing the Dash Core application using `make deploy`. -This command depends on a couple of python packages, so it is required that you have `python` installed. - -Ensuring that `python` is installed, you can install the deploy dependencies by running the following commands in your terminal: - -``` bash -pip3 install ds_store mac_alias -``` +You can deploy a `.zip` containing the Dash Core application using `make deploy`. +It is required that you have `python` installed. ## Building Dash Core @@ -289,7 +283,7 @@ make check # Run tests if Python 3 is available ### 3. Deploy (optional) -You can also create a `.dmg` containing the `.app` bundle by running the following command: +You can also create a `.zip` containing the `.app` bundle by running the following command: ``` bash make deploy diff --git a/doc/descriptors.md b/doc/descriptors.md index c90463657a..6a94b867c3 100644 --- a/doc/descriptors.md +++ b/doc/descriptors.md @@ -117,6 +117,47 @@ Key order does not matter for `sortedmulti()`. `sortedmulti()` behaves in the sa as `multi()` does but the keys are reordered in the resulting script such that they are lexicographically ordered as described in BIP67. +#### Basic multisig example + +For a good example of a basic M-of-N multisig between multiple participants using descriptor +wallets and PSBTs, as well as a signing flow, see [this functional test](/test/functional/wallet_multisig_descriptor_psbt.py). + +Disclaimers: It is important to note that this example serves as a quick-start and is kept basic for readability. A downside of the approach +outlined here is that each participant must maintain (and backup) two separate wallets: a signer and the corresponding multisig. +It should also be noted that privacy best-practices are not "by default" here - participants should take care to only use the signer to sign +transactions related to the multisig. Lastly, it is not recommended to use anything other than a Bitcoin Core descriptor wallet to serve as your +signer(s). Other wallets, whether hardware or software, likely impose additional checks and safeguards to prevent users from signing transactions that +could lead to loss of funds, or are deemed security hazards. Conforming to various 3rd-party checks and verifications is not in the scope of this example. + +The basic steps are: + + 1. Every participant generates an xpub. The most straightforward way is to create a new descriptor wallet which we will refer to as + the participant's signer wallet. Avoid reusing this wallet for any purpose other than signing transactions from the + corresponding multisig we are about to create. Hint: extract the wallet's xpubs using `listdescriptors` and pick the one from the + `pkh` descriptor since it's least likely to be accidentally reused (legacy addresses) + 2. Create a watch-only descriptor wallet (blank, private keys disabled). Now the multisig is created by importing the two descriptors: + `wsh(sortedmulti(,XPUB1/0/*,XPUB2/0/*,…,XPUBN/0/*))` and `wsh(sortedmulti(,XPUB1/1/*,XPUB2/1/*,…,XPUBN/1/*))` + (one descriptor w/ `0` for receiving addresses and another w/ `1` for change). Every participant does this + 3. A receiving address is generated for the multisig. As a check to ensure step 2 was done correctly, every participant + should verify they get the same addresses + 4. Funds are sent to the resulting address + 5. A sending transaction from the multisig is created using `walletcreatefundedpsbt` (anyone can initiate this). It is simple to do + this in the GUI by going to the `Send` tab in the multisig wallet and creating an unsigned transaction (PSBT) + 6. At least `M` participants check the PSBT with their multisig using `decodepsbt` to verify the transaction is OK before signing it. + 7. (If OK) the participant signs the PSBT with their signer wallet using `walletprocesspsbt`. It is simple to do this in the GUI by + loading the PSBT from file and signing it + 8. The signed PSBTs are collected with `combinepsbt`, finalized w/ `finalizepsbt`, and then the resulting transaction is broadcasted + to the network. Note that any wallet (eg one of the signers or multisig) is capable of doing this. + 9. Checks that balances are correct after the transaction has been included in a block + +You may prefer a daisy chained signing flow where each participant signs the PSBT one after another until +the PSBT has been signed `M` times and is "complete." For the most part, the steps above remain the same, except (6, 7) +change slightly from signing the original PSBT in parallel to signing it in series. `combinepsbt` is not necessary with +this signing flow and the last (`m`th) signer can just broadcast the PSBT after signing. Note that a parallel signing flow may be +preferable in cases where there are more signers. This signing flow is also included in the test / Python example. +[The test](/test/functional/wallet_multisig_descriptor_psbt.py) is meant to be documentation as much as it is a functional test, so +it is kept as simple and readable as possible. + ### BIP32 derived keys and chains Most modern wallet software and hardware uses keys that are derived using diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 1f3aef04a6..04013dfcb6 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -445,7 +445,7 @@ other input. failure, it will throw an exception, which can be caught to recover from the error. - For example, a nullptr dereference or any other logic bug in RPC code - means that the RPC code is faulty and can not be executed. However, the + means that the RPC code is faulty and cannot be executed. However, the logic bug can be shown to the user and the program can continue to run. * `Assume` should be used to document assumptions when program execution can safely continue even if the assumption is violated. In debug builds it @@ -1352,7 +1352,7 @@ A few guidelines for introducing and reviewing new RPC interfaces: - Don't forget to fill in the argument names correctly in the RPC command table. - - *Rationale*: If not, the call can not be used with name-based arguments. + - *Rationale*: If not, the call cannot be used with name-based arguments. - Add every non-string RPC argument `(method, idx, name)` to the table `vRPCConvertParams` in `rpc/client.cpp`. diff --git a/doc/psbt.md b/doc/psbt.md index 3b10489a3b..c40023c437 100644 --- a/doc/psbt.md +++ b/doc/psbt.md @@ -92,6 +92,9 @@ hardware implementations will typically implement multiple roles simultaneously. #### Multisig with multiple Bitcoin Core instances +For a quick start see [Basic M-of-N multisig example using descriptor wallets and PSBTs](./descriptors.md#basic-multisig-example). +If you are using legacy wallets feel free to continue with the example provided here. + Alice, Bob, and Carol want to create a 2-of-3 multisig address. They're all using Bitcoin Core. We assume their wallets only contain the multisig funds. In case they also have a personal wallet, this can be accomplished through the diff --git a/doc/release-notes-6516.md b/doc/release-notes-6516.md new file mode 100644 index 0000000000..2c9f50c291 --- /dev/null +++ b/doc/release-notes-6516.md @@ -0,0 +1,5 @@ +Build Changes +------------- + +The macOS distribution is no longer packaged in a disk image (DMG) and +is now packaged in a ZIP archive. diff --git a/doc/release-process.md b/doc/release-process.md index 6089e43eab..f9b01fae20 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -88,7 +88,7 @@ git -C ./guix.sigs pull _Note: this step can be skipped if [our CI](https://github.com/dashpay/dash/blob/master/ci/test/00_setup_env.sh#L64) still uses bitcoin's SDK package (see SDK_URL)_ Create the macOS SDK tarball, see the [macOS build -instructions](build-osx.md#deterministic-macos-dmg-notes) for +instructions](build-osx.md#deterministic-macos-app-notes) for details. ### Build and attest to build outputs: @@ -178,7 +178,7 @@ Commit your signature for the signed macOS/Windows binaries: ```sh pushd ./guix.sigs git add "${VERSION}/${SIGNER}"/all.SHA256SUMS{,.asc} -git commit -m "Add ${SIGNER} ${VERSION} signed binaries signatures" +git commit -m "Add attestations by ${SIGNER} for ${VERSION} codesigned" git push # Assuming you can push to the guix.sigs tree popd ``` diff --git a/src/bench/bls.cpp b/src/bench/bls.cpp index b9fd3ac163..c22321da40 100644 --- a/src/bench/bls.cpp +++ b/src/bench/bls.cpp @@ -29,12 +29,12 @@ static void BuildTestVectors(size_t count, size_t invalidCount, secKeys[i].MakeNewKey(); pubKeys[i] = secKeys[i].GetPublicKey(); msgHashes[i] = GetRandHash(); - sigs[i] = secKeys[i].Sign(msgHashes[i]); + sigs[i] = secKeys[i].Sign(msgHashes[i], false); if (invalid[i]) { CBLSSecretKey s; s.MakeNewKey(); - sigs[i] = s.Sign(msgHashes[i]); + sigs[i] = s.Sign(msgHashes[i], false); } } } @@ -71,8 +71,8 @@ static void BLS_SignatureAggregate_Normal(benchmark::Bench& bench) CBLSSecretKey secKey1, secKey2; secKey1.MakeNewKey(); secKey2.MakeNewKey(); - CBLSSignature sig1 = secKey1.Sign(hash); - CBLSSignature sig2 = secKey2.Sign(hash); + CBLSSignature sig1 = secKey1.Sign(hash, false); + CBLSSignature sig2 = secKey2.Sign(hash, false); // Benchmark. bench.run([&] { @@ -89,7 +89,7 @@ static void BLS_Sign_Normal(benchmark::Bench& bench) // Benchmark. bench.minEpochIterations(100).run([&] { uint256 hash = GetRandHash(); - sig = secKey.Sign(hash); + sig = secKey.Sign(hash, false); }); } diff --git a/src/bls/bls.cpp b/src/bls/bls.cpp index 85a96c3e3e..09f192cd67 100644 --- a/src/bls/bls.cpp +++ b/src/bls/bls.cpp @@ -117,11 +117,6 @@ CBLSPublicKey CBLSSecretKey::GetPublicKey() const return pubKey; } -CBLSSignature CBLSSecretKey::Sign(const uint256& hash) const -{ - return Sign(hash, bls::bls_legacy_scheme.load()); -} - CBLSSignature CBLSSecretKey::Sign(const uint256& hash, const bool specificLegacyScheme) const { if (!IsValid()) { diff --git a/src/bls/bls.h b/src/bls/bls.h index b1b0eb5f75..0e3671b5a0 100644 --- a/src/bls/bls.h +++ b/src/bls/bls.h @@ -57,10 +57,6 @@ class CBLSWrapper static constexpr size_t SerSize = _SerSize; explicit CBLSWrapper() = default; - explicit CBLSWrapper(Span vecBytes) : CBLSWrapper() - { - SetByteVector(vecBytes, bls::bls_legacy_scheme.load()); - } CBLSWrapper(const CBLSWrapper& ref) = default; CBLSWrapper& operator=(const CBLSWrapper& ref) = default; @@ -131,11 +127,6 @@ class CBLSWrapper return impl.Serialize(specificLegacyScheme); } - std::vector ToByteVector() const - { - return ToByteVector(bls::bls_legacy_scheme.load()); - } - const uint256& GetHash() const { if (cachedHash.IsNull()) { @@ -215,11 +206,6 @@ class CBLSWrapper return true; } - inline bool CheckMalleable(Span vecBytes) const - { - return CheckMalleable(vecBytes, bls::bls_legacy_scheme.load()); - } - inline std::string ToString(const bool specificLegacyScheme) const { std::vector buf = ToByteVector(specificLegacyScheme); @@ -263,6 +249,7 @@ class CBLSId : public CBLSWrapper explicit CBLSId(const uint256& nHash); }; +//! CBLSSecretKey is invariant to BLS scheme for Creation / Serialization / Deserialization class CBLSSecretKey : public CBLSWrapper { public: @@ -272,6 +259,11 @@ class CBLSSecretKey : public CBLSWrapper vecBytes) + { + // The second param here is not 'is_legacy', but `modOrder` + SetByteVector(vecBytes, false); + } CBLSSecretKey(const CBLSSecretKey&) = default; CBLSSecretKey& operator=(const CBLSSecretKey&) = default; @@ -279,12 +271,14 @@ class CBLSSecretKey : public CBLSWrapper sks); #ifndef BUILD_BITCOIN_INTERNAL + //! MakeNewKey() is invariant to BLS scheme void MakeNewKey(); #endif + //! SecretKeyShare() is invariant to BLS scheme bool SecretKeyShare(Span msk, const CBLSId& id); + //! GetPublicKey() is invariant to BLS scheme [[nodiscard]] CBLSPublicKey GetPublicKey() const; - [[nodiscard]] CBLSSignature Sign(const uint256& hash) const; [[nodiscard]] CBLSSignature Sign(const uint256& hash, const bool specificLegacyScheme) const; }; @@ -338,6 +332,10 @@ class CBLSSignature : public CBLSWrapper bytes, bool is_serialized_legacy) + { + SetByteVector(bytes, is_serialized_legacy); + } CBLSSignature(const CBLSSignature&) = default; CBLSSignature& operator=(const CBLSSignature&) = default; diff --git a/src/bls/bls_ies.cpp b/src/bls/bls_ies.cpp index 1068e078fc..e6282c0285 100644 --- a/src/bls/bls_ies.cpp +++ b/src/bls/bls_ies.cpp @@ -9,8 +9,7 @@ #include -template -static bool EncryptBlob(const void* in, size_t inSize, Out& out, const void* symKey, const void* iv) +static bool EncryptBlob(const void* in, size_t inSize, std::vector& out, const void* symKey, const void* iv) { out.resize(inSize); @@ -38,24 +37,6 @@ uint256 CBLSIESEncryptedBlob::GetIV(size_t idx) const return iv; } -bool CBLSIESEncryptedBlob::Encrypt(size_t idx, const CBLSPublicKey& peerPubKey, const void* plainTextData, size_t dataSize) -{ - CBLSSecretKey ephemeralSecretKey; - ephemeralSecretKey.MakeNewKey(); - ephemeralPubKey = ephemeralSecretKey.GetPublicKey(); - - CBLSPublicKey pk; - if (!pk.DHKeyExchange(ephemeralSecretKey, peerPubKey)) { - return false; - } - - std::vector symKey = pk.ToByteVector(); - symKey.resize(32); - - uint256 iv = GetIV(idx); - return EncryptBlob(plainTextData, dataSize, data, symKey.data(), iv.begin()); -} - bool CBLSIESEncryptedBlob::Decrypt(size_t idx, const CBLSSecretKey& secretKey, CDataStream& decryptedDataRet) const { CBLSPublicKey pk; @@ -63,7 +44,7 @@ bool CBLSIESEncryptedBlob::Decrypt(size_t idx, const CBLSSecretKey& secretKey, C return false; } - std::vector symKey = pk.ToByteVector(); + std::vector symKey = pk.ToByteVector(false); symKey.resize(32); uint256 iv = GetIV(idx); @@ -75,24 +56,6 @@ bool CBLSIESEncryptedBlob::IsValid() const return ephemeralPubKey.IsValid() && !data.empty() && !ivSeed.IsNull(); } - -bool CBLSIESMultiRecipientBlobs::Encrypt(const std::vector& recipients, const BlobVector& _blobs) -{ - if (recipients.size() != _blobs.size()) { - return false; - } - - InitEncrypt(_blobs.size()); - - for (size_t i = 0; i < _blobs.size(); i++) { - if (!Encrypt(i, recipients[i], _blobs[i])) { - return false; - } - } - - return true; -} - void CBLSIESMultiRecipientBlobs::InitEncrypt(size_t count) { ephemeralSecretKey.MakeNewKey(); @@ -117,7 +80,7 @@ bool CBLSIESMultiRecipientBlobs::Encrypt(size_t idx, const CBLSPublicKey& recipi return false; } - std::vector symKey = pk.ToByteVector(); + std::vector symKey = pk.ToByteVector(false); symKey.resize(32); return EncryptBlob(blob.data(), blob.size(), blobs[idx], symKey.data(), ivVector[idx].begin()); @@ -134,7 +97,7 @@ bool CBLSIESMultiRecipientBlobs::Decrypt(size_t idx, const CBLSSecretKey& sk, Bl return false; } - std::vector symKey = pk.ToByteVector(); + std::vector symKey = pk.ToByteVector(false); symKey.resize(32); uint256 iv = ivSeed; diff --git a/src/bls/bls_ies.h b/src/bls/bls_ies.h index 002d41a86b..72633e1aa5 100644 --- a/src/bls/bls_ies.h +++ b/src/bls/bls_ies.h @@ -8,6 +8,11 @@ #include #include +/** + * All objects in this module working from assumption that basic scheme is + * available on all masternodes. Serialization of public key for Encrypt and + * Decrypt by bls_ies.h done using Basic Scheme. + */ class CBLSIESEncryptedBlob { public: @@ -22,7 +27,6 @@ class CBLSIESEncryptedBlob READWRITE(obj.ephemeralPubKey, obj.ivSeed, obj.data); } - bool Encrypt(size_t idx, const CBLSPublicKey& peerPubKey, const void* data, size_t dataSize); bool Decrypt(size_t idx, const CBLSSecretKey& secretKey, CDataStream& decryptedDataRet) const; bool IsValid() const; }; @@ -40,17 +44,6 @@ class CBLSIESEncryptedObject : public CBLSIESEncryptedBlob data = dataIn; } - bool Encrypt(size_t idx, const CBLSPublicKey& peerPubKey, const Object& obj, int nVersion) - { - try { - CDataStream ds(SER_NETWORK, nVersion); - ds << obj; - return CBLSIESEncryptedBlob::Encrypt(idx, peerPubKey, ds.data(), ds.size()); - } catch (const std::exception&) { - return false; - } - } - bool Decrypt(size_t idx, const CBLSSecretKey& secretKey, Object& objRet, int nVersion) const { CDataStream ds(SER_NETWORK, nVersion); @@ -80,8 +73,6 @@ class CBLSIESMultiRecipientBlobs CBLSSecretKey ephemeralSecretKey; std::vector ivVector; - bool Encrypt(const std::vector& recipients, const BlobVector& _blobs); - void InitEncrypt(size_t count); bool Encrypt(size_t idx, const CBLSPublicKey& recipient, const Blob& blob); bool Decrypt(size_t idx, const CBLSSecretKey& sk, Blob& blobRet) const; @@ -96,28 +87,6 @@ template class CBLSIESMultiRecipientObjects : public CBLSIESMultiRecipientBlobs { public: - using ObjectVector = std::vector; - - bool Encrypt(const std::vector& recipients, const ObjectVector& _objects, int nVersion) - { - BlobVector blobs; - blobs.resize(_objects.size()); - - try { - CDataStream ds(SER_NETWORK, nVersion); - for (size_t i = 0; i < _objects.size(); i++) { - ds.clear(); - - ds << _objects[i]; - blobs[i].assign(UCharCast(ds.data()), UCharCast(ds.data() + ds.size())); - } - } catch (const std::exception&) { - return false; - } - - return CBLSIESMultiRecipientBlobs::Encrypt(recipients, blobs); - } - bool Encrypt(size_t idx, const CBLSPublicKey& recipient, const Object& obj, int nVersion) { CDataStream ds(SER_NETWORK, nVersion); diff --git a/src/bls/bls_worker.cpp b/src/bls/bls_worker.cpp index f5197e8fa5..4767d02ed3 100644 --- a/src/bls/bls_worker.cpp +++ b/src/bls/bls_worker.cpp @@ -762,7 +762,7 @@ bool CBLSWorker::VerifyVerificationVectors(Span vvecs) void CBLSWorker::AsyncSign(const CBLSSecretKey& secKey, const uint256& msgHash, const CBLSWorker::SignDoneCallback& doneCallback) { workerPool.push([secKey, msgHash, doneCallback](int threadId) { - doneCallback(secKey.Sign(msgHash)); + doneCallback(secKey.Sign(msgHash, bls::bls_legacy_scheme.load())); }); } diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 40e77891c9..22fc808efb 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -799,7 +799,7 @@ class CRegTestParams : public CChainParams { consensus.DIP0020Height = 1; // Always active unless overridden consensus.DIP0024Height = 1; // Always have dip0024 quorums unless overridden consensus.DIP0024QuorumsHeight = 1; // Always have dip0024 quorums unless overridden - consensus.V19Height = 900; + consensus.V19Height = 1; // Always active unless overriden consensus.V20Height = 900; consensus.MN_RRHeight = 900; consensus.MinBIP9WarningHeight = 0; @@ -1031,6 +1031,8 @@ static void MaybeUpdateHeights(const ArgsManager& args, Consensus::Params& conse consensus.DIP0008Height = int{height}; } else if (name == "dip0024") { consensus.DIP0024QuorumsHeight = int{height}; + } else if (name == "v19") { + consensus.V19Height = int{height}; } else if (name == "v20") { consensus.V20Height = int{height}; } else if (name == "mn_rr") { @@ -1365,3 +1367,27 @@ void SelectParams(const std::string& network) SelectBaseParams(network); globalChainParams = CreateChainParams(gArgs, network); } + +void SetupChainParamsOptions(ArgsManager& argsman) +{ + SetupChainParamsBaseOptions(argsman); + + argsman.AddArg("-budgetparams=::", "Override masternode, budget and superblock start heights (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-dip3params=:", "Override DIP3 activation and enforcement heights (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-highsubsidyblocks=", "The number of blocks with a higher than normal subsidy to mine at the start of a chain. Block after that height will have fixed subsidy base. (default: 0, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-highsubsidyfactor=", "The factor to multiply the normal block subsidy by while in the highsubsidyblocks window of a chain (default: 1, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-llmqchainlocks=", "Override the default LLMQ type used for ChainLocks. Allows using ChainLocks with smaller LLMQs. (default: llmq_devnet, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-llmqdevnetparams=:", "Override the default LLMQ size for the LLMQ_DEVNET quorum (devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-llmqinstantsenddip0024=", "Override the default LLMQ type used for InstantSendDIP0024. (default: llmq_devnet_dip0024, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-llmqplatform=", "Override the default LLMQ type used for Platform. (default: llmq_devnet_platform, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-llmqmnhf=", "Override the default LLMQ type used for EHF. (default: llmq_devnet, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-llmqtestinstantsenddip0024=", "Override the default LLMQ type used for InstantSendDIP0024. Used mainly to test Platform. (default: llmq_test_dip0024, regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-llmqtestinstantsendparams=:", "Override the default LLMQ size for the LLMQ_TEST_INSTANTSEND quorums (default: 3:2, regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-llmqtestparams=:", "Override the default LLMQ size for the LLMQ_TEST quorum (default: 3:2, regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-minimumdifficultyblocks=", "The number of blocks that can be mined with the minimum difficulty at the start of a chain (default: 0, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-powtargetspacing=", "Override the default PowTargetSpacing value in seconds (default: 2.5 minutes, devnet-only)", ArgsManager::ALLOW_INT, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-testactivationheight=name@height.", "Set the activation height of 'name' (bip147, bip34, dersig, cltv, csv, brr, dip0001, dip0008, dip0024, v19, v20, mn_rr). (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-vbparams=::(:min_activation_height(::(:::)))", + "Use given start/end times and min_activation_height for specified version bits deployment (regtest-only). " + "Specifying window, threshold/thresholdstart, thresholdmin, falloffcoeff and mnactivation is optional.", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); +} diff --git a/src/chainparams.h b/src/chainparams.h index b832f04880..8f1471f369 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -214,4 +214,9 @@ const CChainParams &Params(); */ void SelectParams(const std::string& chain); +/** + *Set the arguments for chainparams + */ +void SetupChainParamsOptions(ArgsManager& argsman); + #endif // BITCOIN_CHAINPARAMS_H diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 1a05491f06..e97b48d56d 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -17,30 +17,11 @@ const std::string CBaseChainParams::REGTEST = "regtest"; void SetupChainParamsBaseOptions(ArgsManager& argsman) { - argsman.AddArg("-budgetparams=::", "Override masternode, budget and superblock start heights (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-devnet=", "Use devnet chain with provided name", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-dip3params=:", "Override DIP3 activation and enforcement heights (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-testactivationheight=name@height.", "Set the activation height of 'name' (bip147, bip34, dersig, cltv, csv, brr, dip0001, dip0008, dip0024, v20, mn_rr). (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-highsubsidyblocks=", "The number of blocks with a higher than normal subsidy to mine at the start of a chain. Block after that height will have fixed subsidy base. (default: 0, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-highsubsidyfactor=", "The factor to multiply the normal block subsidy by while in the highsubsidyblocks window of a chain (default: 1, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-llmqchainlocks=", "Override the default LLMQ type used for ChainLocks. Allows using ChainLocks with smaller LLMQs. (default: llmq_devnet, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-llmqdevnetparams=:", "Override the default LLMQ size for the LLMQ_DEVNET quorum (devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-llmqinstantsenddip0024=", "Override the default LLMQ type used for InstantSendDIP0024. (default: llmq_devnet_dip0024, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-llmqplatform=", "Override the default LLMQ type used for Platform. (default: llmq_devnet_platform, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-llmqmnhf=", "Override the default LLMQ type used for EHF. (default: llmq_devnet, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-llmqtestinstantsenddip0024=", "Override the default LLMQ type used for InstantSendDIP0024. Used mainly to test Platform. (default: llmq_test_dip0024, regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-llmqtestinstantsendparams=:", "Override the default LLMQ size for the LLMQ_TEST_INSTANTSEND quorums (default: 3:2, regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-llmqtestparams=:", "Override the default LLMQ size for the LLMQ_TEST quorum (default: 3:2, regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-powtargetspacing=", "Override the default PowTargetSpacing value in seconds (default: 2.5 minutes, devnet-only)", ArgsManager::ALLOW_INT, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-minimumdifficultyblocks=", "The number of blocks that can be mined with the minimum difficulty at the start of a chain (default: 0, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-chain=", "Use the chain (default: main). Allowed values: main, test, regtest", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-devnet=", "Use devnet chain with provided name", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-regtest", "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. " "This is intended for regression testing tools and app development. Equivalent to -chain=regtest", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-testnet", "Use the test chain. Equivalent to -chain=test", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-vbparams=::(:min_activation_height(::(:::)))", - "Use given start/end times and min_activation_height for specified version bits deployment (regtest-only). " - "Specifying window, threshold/thresholdstart, thresholdmin, falloffcoeff and mnactivation is optional.", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); - } static std::unique_ptr globalChainBaseParams; diff --git a/src/coinjoin/client.cpp b/src/coinjoin/client.cpp index a25f32510d..4858223e07 100644 --- a/src/coinjoin/client.cpp +++ b/src/coinjoin/client.cpp @@ -166,6 +166,7 @@ void CCoinJoinClientManager::ProcessMessage(CNode& peer, CChainState& active_cha CCoinJoinClientSession::CCoinJoinClientSession(const std::shared_ptr& wallet, CoinJoinWalletManager& walletman, CCoinJoinClientManager& clientman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, const CMasternodeSync& mn_sync, + const llmq::CInstantSendManager& isman, const std::unique_ptr& queueman, bool is_masternode) : m_wallet(wallet), @@ -174,6 +175,7 @@ CCoinJoinClientSession::CCoinJoinClientSession(const std::shared_ptr& w m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mn_sync(mn_sync), + m_isman{isman}, m_queueman(queueman), m_is_masternode{is_masternode} {} @@ -589,7 +591,8 @@ bool CCoinJoinClientSession::SignFinalTransaction(CNode& peer, CChainState& acti // Make sure all inputs/outputs are valid PoolMessage nMessageID{MSG_NOERR}; - if (!IsValidInOuts(active_chainstate, mempool, finalMutableTransaction.vin, finalMutableTransaction.vout, nMessageID, nullptr)) { + if (!IsValidInOuts(active_chainstate, m_isman, mempool, finalMutableTransaction.vin, finalMutableTransaction.vout, + nMessageID, nullptr)) { WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- ERROR! IsValidInOuts() failed: %s\n", __func__, CoinJoin::GetMessageByID(nMessageID).translated); UnlockCoins(); keyHolderStorage.ReturnAll(); @@ -953,7 +956,7 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(ChainstateManager& chainman return false; } } else { - if (!CoinJoin::IsCollateralValid(chainman, mempool, CTransaction(txMyCollateral))) { + if (!CoinJoin::IsCollateralValid(chainman, m_isman, mempool, CTransaction(txMyCollateral))) { WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::DoAutomaticDenominating -- invalid collateral, recreating...\n"); if (!CreateCollateralTransaction(txMyCollateral, strReason)) { WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::DoAutomaticDenominating -- create collateral error: %s\n", strReason); @@ -1012,7 +1015,7 @@ bool CCoinJoinClientManager::DoAutomaticDenominating(ChainstateManager& chainman AssertLockNotHeld(cs_deqsessions); LOCK(cs_deqsessions); if (int(deqSessions.size()) < CCoinJoinClientOptions::GetSessions()) { - deqSessions.emplace_back(m_wallet, m_walletman, *this, m_dmnman, m_mn_metaman, m_mn_sync, m_queueman, + deqSessions.emplace_back(m_wallet, m_walletman, *this, m_dmnman, m_mn_metaman, m_mn_sync, m_isman, m_queueman, m_is_masternode); } for (auto& session : deqSessions) { @@ -1915,7 +1918,8 @@ void CoinJoinWalletManager::Add(const std::shared_ptr& wallet) LOCK(cs_wallet_manager_map); m_wallet_manager_map.try_emplace(wallet->GetName(), std::make_unique(wallet, *this, m_dmnman, m_mn_metaman, - m_mn_sync, m_queueman, m_is_masternode)); + m_mn_sync, m_isman, m_queueman, + m_is_masternode)); } g_wallet_init_interface.InitCoinJoinSettings(*this); } diff --git a/src/coinjoin/client.h b/src/coinjoin/client.h index 2eccc1cfc2..da8f850c92 100644 --- a/src/coinjoin/client.h +++ b/src/coinjoin/client.h @@ -77,13 +77,14 @@ class CoinJoinWalletManager { public: CoinJoinWalletManager(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, - const CTxMemPool& mempool, const CMasternodeSync& mn_sync, + const CTxMemPool& mempool, const CMasternodeSync& mn_sync, const llmq::CInstantSendManager& isman, const std::unique_ptr& queueman, bool is_masternode) : m_chainman(chainman), m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mempool(mempool), m_mn_sync(mn_sync), + m_isman{isman}, m_queueman(queueman), m_is_masternode{is_masternode} {} @@ -125,6 +126,7 @@ class CoinJoinWalletManager { CMasternodeMetaMan& m_mn_metaman; const CTxMemPool& m_mempool; const CMasternodeSync& m_mn_sync; + const llmq::CInstantSendManager& m_isman; const std::unique_ptr& m_queueman; const bool m_is_masternode; @@ -142,6 +144,7 @@ class CCoinJoinClientSession : public CCoinJoinBaseSession CDeterministicMNManager& m_dmnman; CMasternodeMetaMan& m_mn_metaman; const CMasternodeSync& m_mn_sync; + const llmq::CInstantSendManager& m_isman; const std::unique_ptr& m_queueman; // Track node type @@ -201,6 +204,7 @@ class CCoinJoinClientSession : public CCoinJoinBaseSession explicit CCoinJoinClientSession(const std::shared_ptr& wallet, CoinJoinWalletManager& walletman, CCoinJoinClientManager& clientman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, const CMasternodeSync& mn_sync, + const llmq::CInstantSendManager& isman, const std::unique_ptr& queueman, bool is_masternode); void ProcessMessage(CNode& peer, CChainState& active_chainstate, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv); @@ -266,6 +270,7 @@ class CCoinJoinClientManager CDeterministicMNManager& m_dmnman; CMasternodeMetaMan& m_mn_metaman; const CMasternodeSync& m_mn_sync; + const llmq::CInstantSendManager& m_isman; const std::unique_ptr& m_queueman; // Track node type @@ -302,13 +307,14 @@ class CCoinJoinClientManager explicit CCoinJoinClientManager(const std::shared_ptr& wallet, CoinJoinWalletManager& walletman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, - const CMasternodeSync& mn_sync, + const CMasternodeSync& mn_sync, const llmq::CInstantSendManager& isman, const std::unique_ptr& queueman, bool is_masternode) : m_wallet(wallet), m_walletman(walletman), m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mn_sync(mn_sync), + m_isman{isman}, m_queueman(queueman), m_is_masternode{is_masternode} { diff --git a/src/coinjoin/coinjoin.cpp b/src/coinjoin/coinjoin.cpp index 74fc644a70..78f34d1549 100644 --- a/src/coinjoin/coinjoin.cpp +++ b/src/coinjoin/coinjoin.cpp @@ -62,7 +62,7 @@ bool CCoinJoinQueue::Sign(const CActiveMasternodeManager& mn_activeman) bool CCoinJoinQueue::CheckSignature(const CBLSPublicKey& blsPubKey) const { - if (!CBLSSignature(Span{vchSig}).VerifyInsecure(blsPubKey, GetSignatureHash(), false)) { + if (!CBLSSignature(Span{vchSig}, false).VerifyInsecure(blsPubKey, GetSignatureHash(), false)) { LogPrint(BCLog::COINJOIN, "CCoinJoinQueue::CheckSignature -- VerifyInsecure() failed\n"); return false; } @@ -101,7 +101,7 @@ bool CCoinJoinBroadcastTx::Sign(const CActiveMasternodeManager& mn_activeman) bool CCoinJoinBroadcastTx::CheckSignature(const CBLSPublicKey& blsPubKey) const { - if (!CBLSSignature(Span{vchSig}).VerifyInsecure(blsPubKey, GetSignatureHash(), false)) { + if (!CBLSSignature(Span{vchSig}, false).VerifyInsecure(blsPubKey, GetSignatureHash(), false)) { LogPrint(BCLog::COINJOIN, "CCoinJoinBroadcastTx::CheckSignature -- VerifyInsecure() failed\n"); return false; } @@ -207,7 +207,10 @@ std::string CCoinJoinBaseSession::GetStateString() const } } -bool CCoinJoinBaseSession::IsValidInOuts(CChainState& active_chainstate, const CTxMemPool& mempool, const std::vector& vin, const std::vector& vout, PoolMessage& nMessageIDRet, bool* fConsumeCollateralRet) const +bool CCoinJoinBaseSession::IsValidInOuts(CChainState& active_chainstate, const llmq::CInstantSendManager& isman, + const CTxMemPool& mempool, const std::vector& vin, + const std::vector& vout, PoolMessage& nMessageIDRet, + bool* fConsumeCollateralRet) const { std::set setScripPubKeys; nMessageIDRet = MSG_NOERR; @@ -268,7 +271,7 @@ bool CCoinJoinBaseSession::IsValidInOuts(CChainState& active_chainstate, const C Coin coin; if (!viewMemPool.GetCoin(txin.prevout, coin) || coin.IsSpent() || - (coin.nHeight == MEMPOOL_HEIGHT && !llmq::quorumInstantSendManager->IsLocked(txin.prevout.hash))) { + (coin.nHeight == MEMPOOL_HEIGHT && !isman.IsLocked(txin.prevout.hash))) { LogPrint(BCLog::COINJOIN, "CCoinJoinBaseSession::%s -- ERROR: missing, spent or non-locked mempool input! txin=%s\n", __func__, txin.ToString()); nMessageIDRet = ERR_MISSING_TX; return false; @@ -313,7 +316,8 @@ bool ATMPIfSaneFee(ChainstateManager& chainman, const CTransactionRef& tx, bool } // check to make sure the collateral provided by the client is valid -bool CoinJoin::IsCollateralValid(ChainstateManager& chainman, const CTxMemPool& mempool, const CTransaction& txCollateral) +bool CoinJoin::IsCollateralValid(ChainstateManager& chainman, const llmq::CInstantSendManager& isman, + const CTxMemPool& mempool, const CTransaction& txCollateral) { if (txCollateral.vout.empty()) return false; if (txCollateral.nLockTime != 0) return false; @@ -334,7 +338,7 @@ bool CoinJoin::IsCollateralValid(ChainstateManager& chainman, const CTxMemPool& Coin coin; auto mempoolTx = mempool.get(txin.prevout.hash); if (mempoolTx != nullptr) { - if (mempool.isSpent(txin.prevout) || !llmq::quorumInstantSendManager->IsLocked(txin.prevout.hash)) { + if (mempool.isSpent(txin.prevout) || !isman.IsLocked(txin.prevout.hash)) { LogPrint(BCLog::COINJOIN, "CoinJoin::IsCollateralValid -- spent or non-locked mempool input! txin=%s\n", txin.ToString()); return false; } diff --git a/src/coinjoin/coinjoin.h b/src/coinjoin/coinjoin.h index 68e2f40c05..3d5e1f8022 100644 --- a/src/coinjoin/coinjoin.h +++ b/src/coinjoin/coinjoin.h @@ -33,6 +33,7 @@ class TxValidationState; namespace llmq { class CChainLocksHandler; +class CInstantSendManager; } // namespace llmq extern RecursiveMutex cs_main; @@ -308,7 +309,9 @@ class CCoinJoinBaseSession virtual void SetNull() EXCLUSIVE_LOCKS_REQUIRED(cs_coinjoin); - bool IsValidInOuts(CChainState& active_chainstate, const CTxMemPool& mempool, const std::vector& vin, const std::vector& vout, PoolMessage& nMessageIDRet, bool* fConsumeCollateralRet) const; + bool IsValidInOuts(CChainState& active_chainstate, const llmq::CInstantSendManager& isman, + const CTxMemPool& mempool, const std::vector& vin, const std::vector& vout, + PoolMessage& nMessageIDRet, bool* fConsumeCollateralRet) const; public: int nSessionDenom{0}; // Users must submit a denom matching this @@ -365,7 +368,8 @@ namespace CoinJoin constexpr CAmount GetMaxPoolAmount() { return COINJOIN_ENTRY_MAX_SIZE * vecStandardDenominations.front(); } /// If the collateral is valid given by a client - bool IsCollateralValid(ChainstateManager& chainman, const CTxMemPool& mempool, const CTransaction& txCollateral); + bool IsCollateralValid(ChainstateManager& chainman, const llmq::CInstantSendManager& isman, + const CTxMemPool& mempool, const CTransaction& txCollateral); } class CDSTXManager diff --git a/src/coinjoin/context.cpp b/src/coinjoin/context.cpp index 8ab6f9e636..0bd9da7c9d 100644 --- a/src/coinjoin/context.cpp +++ b/src/coinjoin/context.cpp @@ -12,17 +12,17 @@ CJContext::CJContext(ChainstateManager& chainman, CConnman& connman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, - std::unique_ptr& peerman, bool relay_txes) : + const llmq::CInstantSendManager& isman, std::unique_ptr& peerman, bool relay_txes) : dstxman{std::make_unique()}, #ifdef ENABLE_WALLET - walletman{std::make_unique(chainman, dmnman, mn_metaman, mempool, mn_sync, queueman, + walletman{std::make_unique(chainman, dmnman, mn_metaman, mempool, mn_sync, isman, queueman, /*is_masternode=*/mn_activeman != nullptr)}, queueman{relay_txes ? std::make_unique(*walletman, dmnman, mn_metaman, mn_sync, /*is_masternode=*/mn_activeman != nullptr) : nullptr}, #endif // ENABLE_WALLET server{std::make_unique(chainman, connman, dmnman, *dstxman, mn_metaman, mempool, mn_activeman, - mn_sync, peerman)} + mn_sync, isman, peerman)} {} CJContext::~CJContext() {} diff --git a/src/coinjoin/context.h b/src/coinjoin/context.h index b4e8c6a47f..0fad302749 100644 --- a/src/coinjoin/context.h +++ b/src/coinjoin/context.h @@ -22,6 +22,9 @@ class CMasternodeMetaMan; class CMasternodeSync; class CTxMemPool; class PeerManager; +namespace llmq { +class CInstantSendManager; +}; #ifdef ENABLE_WALLET class CCoinJoinClientQueueManager; @@ -33,7 +36,8 @@ struct CJContext { CJContext(const CJContext&) = delete; CJContext(ChainstateManager& chainman, CConnman& connman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, - const CMasternodeSync& mn_sync, std::unique_ptr& peerman, bool relay_txes); + const CMasternodeSync& mn_sync, const llmq::CInstantSendManager& isman, + std::unique_ptr& peerman, bool relay_txes); ~CJContext(); const std::unique_ptr dstxman; diff --git a/src/coinjoin/server.cpp b/src/coinjoin/server.cpp index 6e0ee38474..f73ef3fea7 100644 --- a/src/coinjoin/server.cpp +++ b/src/coinjoin/server.cpp @@ -556,7 +556,7 @@ bool CCoinJoinServer::IsInputScriptSigValid(const CTxIn& txin) const txNew.vin[nTxInIndex].scriptSig = txin.scriptSig; LogPrint(BCLog::COINJOIN, "CCoinJoinServer::IsInputScriptSigValid -- verifying scriptSig %s\n", ScriptToAsmStr(txin.scriptSig).substr(0, 24)); // TODO we're using amount=0 here but we should use the correct amount. This works because Dash ignores the amount while signing/verifying (only used in Bitcoin/Segwit) - if (!VerifyScript(txNew.vin[nTxInIndex].scriptSig, sigPubKey, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, MutableTransactionSignatureChecker(&txNew, nTxInIndex, 0))) { + if (!VerifyScript(txNew.vin[nTxInIndex].scriptSig, sigPubKey, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, MutableTransactionSignatureChecker(&txNew, nTxInIndex, 0, MissingDataBehavior::ASSERT_FAIL))) { LogPrint(BCLog::COINJOIN, "CCoinJoinServer::IsInputScriptSigValid -- VerifyScript() failed on input %d\n", nTxInIndex); return false; } @@ -583,7 +583,7 @@ bool CCoinJoinServer::AddEntry(const CCoinJoinEntry& entry, PoolMessage& nMessag return false; } - if (!CoinJoin::IsCollateralValid(m_chainman, mempool, *entry.txCollateral)) { + if (!CoinJoin::IsCollateralValid(m_chainman, m_isman, mempool, *entry.txCollateral)) { LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- ERROR: collateral not valid!\n", __func__); nMessageIDRet = ERR_INVALID_COLLATERAL; return false; @@ -617,7 +617,8 @@ bool CCoinJoinServer::AddEntry(const CCoinJoinEntry& entry, PoolMessage& nMessag } bool fConsumeCollateral{false}; - if (!IsValidInOuts(m_chainman.ActiveChainstate(), mempool, vin, entry.vecTxOut, nMessageIDRet, &fConsumeCollateral)) { + if (!IsValidInOuts(m_chainman.ActiveChainstate(), m_isman, mempool, vin, entry.vecTxOut, nMessageIDRet, + &fConsumeCollateral)) { LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- ERROR! IsValidInOuts() failed: %s\n", __func__, CoinJoin::GetMessageByID(nMessageIDRet).translated); if (fConsumeCollateral) { ConsumeCollateral(entry.txCollateral); @@ -694,7 +695,7 @@ bool CCoinJoinServer::IsAcceptableDSA(const CCoinJoinAccept& dsa, PoolMessage& n } // check collateral - if (!fUnitTest && !CoinJoin::IsCollateralValid(m_chainman, mempool, CTransaction(dsa.txCollateral))) { + if (!fUnitTest && !CoinJoin::IsCollateralValid(m_chainman, m_isman, mempool, CTransaction(dsa.txCollateral))) { LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- collateral not valid!\n", __func__); nMessageIDRet = ERR_INVALID_COLLATERAL; return false; diff --git a/src/coinjoin/server.h b/src/coinjoin/server.h index c33e98fbf8..f7048816ba 100644 --- a/src/coinjoin/server.h +++ b/src/coinjoin/server.h @@ -36,6 +36,7 @@ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager CTxMemPool& mempool; const CActiveMasternodeManager* const m_mn_activeman; const CMasternodeSync& m_mn_sync; + const llmq::CInstantSendManager& m_isman; std::unique_ptr& m_peerman; // Mixing uses collateral transactions to trust parties entering the pool @@ -94,7 +95,7 @@ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager explicit CCoinJoinServer(ChainstateManager& chainman, CConnman& _connman, CDeterministicMNManager& dmnman, CDSTXManager& dstxman, CMasternodeMetaMan& mn_metaman, CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, - std::unique_ptr& peerman) : + const llmq::CInstantSendManager& isman, std::unique_ptr& peerman) : m_chainman(chainman), connman(_connman), m_dmnman(dmnman), @@ -103,6 +104,7 @@ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager mempool(mempool), m_mn_activeman(mn_activeman), m_mn_sync(mn_sync), + m_isman{isman}, m_peerman(peerman), vecSessionCollaterals(), fUnitTest(false) diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 3f412026f8..86965e1380 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -91,7 +91,7 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con #endif // ENABLE_WALLET m_llmq_ctx->isman->UpdatedBlockTip(pindexNew); - m_llmq_ctx->clhandler->UpdatedBlockTip(); + m_llmq_ctx->clhandler->UpdatedBlockTip(*m_llmq_ctx->isman); m_llmq_ctx->qman->UpdatedBlockTip(pindexNew, m_connman, fInitialDownload); m_llmq_ctx->qdkgsman->UpdatedBlockTip(pindexNew, fInitialDownload); diff --git a/src/evo/assetlocktx.h b/src/evo/assetlocktx.h index 531183fd0a..d63ef4092e 100644 --- a/src/evo/assetlocktx.h +++ b/src/evo/assetlocktx.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_EVO_ASSETLOCKTX_H #define BITCOIN_EVO_ASSETLOCKTX_H -#include +#include #include #include #include diff --git a/src/evo/cbtx.cpp b/src/evo/cbtx.cpp index fc08bd5db5..fca6a50403 100644 --- a/src/evo/cbtx.cpp +++ b/src/evo/cbtx.cpp @@ -62,8 +62,8 @@ bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidati // This can only be done after the block has been fully processed, as otherwise we won't have the finished MN list bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, CDeterministicMNManager& dmnman, - const llmq::CQuorumBlockProcessor& quorum_block_processor, BlockValidationState& state, - const CCoinsViewCache& view) + llmq::CQuorumSnapshotManager& qsnapman, const llmq::CQuorumBlockProcessor& quorum_block_processor, + BlockValidationState& state, const CCoinsViewCache& view) { if (block.vtx[0]->nType != TRANSACTION_COINBASE) { return true; @@ -87,7 +87,7 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, CDeter static int64_t nTimeMerkleQuorum = 0; uint256 calculatedMerkleRoot; - if (!CalcCbTxMerkleRootMNList(block, pindex->pprev, calculatedMerkleRoot, dmnman, state, view)) { + if (!CalcCbTxMerkleRootMNList(block, pindex->pprev, calculatedMerkleRoot, state, dmnman, qsnapman, view)) { // pass the state returned by the function above return false; } @@ -117,7 +117,8 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, CDeter } bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev, uint256& merkleRootRet, - CDeterministicMNManager& dmnman, BlockValidationState& state, const CCoinsViewCache& view) + BlockValidationState& state, CDeterministicMNManager& dmnman, + llmq::CQuorumSnapshotManager& qsnapman, const CCoinsViewCache& view) { try { static std::atomic nTimeDMN = 0; @@ -127,7 +128,7 @@ bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev int64_t nTime1 = GetTimeMicros(); CDeterministicMNList tmpMNList; - if (!dmnman.BuildNewListFromBlock(block, pindexPrev, state, view, tmpMNList, false)) { + if (!dmnman.BuildNewListFromBlock(block, pindexPrev, state, view, tmpMNList, qsnapman, false)) { // pass the state returned by the function above return false; } diff --git a/src/evo/cbtx.h b/src/evo/cbtx.h index ad6b74d10f..ae29f2fc70 100644 --- a/src/evo/cbtx.h +++ b/src/evo/cbtx.h @@ -19,8 +19,9 @@ class CDeterministicMNManager; class TxValidationState; namespace llmq { -class CQuorumBlockProcessor; class CChainLocksHandler; +class CQuorumBlockProcessor; +class CQuorumSnapshotManager; }// namespace llmq // Forward declaration from core_io to get rid of circular dependency @@ -87,10 +88,11 @@ template<> struct is_serializable_enum : std::true_type {}; bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state); bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, CDeterministicMNManager& dmnman, - const llmq::CQuorumBlockProcessor& quorum_block_processor, BlockValidationState& state, - const CCoinsViewCache& view); + llmq::CQuorumSnapshotManager& qsnapman, const llmq::CQuorumBlockProcessor& quorum_block_processor, + BlockValidationState& state, const CCoinsViewCache& view); bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev, uint256& merkleRootRet, - CDeterministicMNManager& dmnman, BlockValidationState& state, const CCoinsViewCache& view); + BlockValidationState& state, CDeterministicMNManager& dmnman, + llmq::CQuorumSnapshotManager& qsnapman, const CCoinsViewCache& view); bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPrev, const llmq::CQuorumBlockProcessor& quorum_block_processor, uint256& merkleRootRet, BlockValidationState& state); diff --git a/src/evo/chainhelper.cpp b/src/evo/chainhelper.cpp index 4c6a6ab964..f2a042bd98 100644 --- a/src/evo/chainhelper.cpp +++ b/src/evo/chainhelper.cpp @@ -6,14 +6,55 @@ #include #include +#include +#include #include -CChainstateHelper::CChainstateHelper(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, CMNHFManager& mnhfman, CGovernanceManager& govman, - llmq::CQuorumBlockProcessor& qblockman, const ChainstateManager& chainman, const Consensus::Params& consensus_params, - const CMasternodeSync& mn_sync, const CSporkManager& sporkman, const llmq::CChainLocksHandler& clhandler, - const llmq::CQuorumManager& qman) - : mn_payments{std::make_unique(dmnman, govman, chainman, consensus_params, mn_sync, sporkman)}, - special_tx{std::make_unique(cpoolman, dmnman, mnhfman, qblockman, chainman, consensus_params, clhandler, qman)} +CChainstateHelper::CChainstateHelper(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, + CMNHFManager& mnhfman, CGovernanceManager& govman, llmq::CInstantSendManager& isman, + llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const Consensus::Params& consensus_params, + const CMasternodeSync& mn_sync, const CSporkManager& sporkman, + const llmq::CChainLocksHandler& clhandler, const llmq::CQuorumManager& qman) : + isman{isman}, + clhandler{clhandler}, + mn_payments{std::make_unique(dmnman, govman, chainman, consensus_params, mn_sync, sporkman)}, + special_tx{std::make_unique(cpoolman, dmnman, mnhfman, qblockman, qsnapman, chainman, + consensus_params, clhandler, qman)} {} CChainstateHelper::~CChainstateHelper() = default; + +/** Passthrough functions to CChainLocksHandler */ +bool CChainstateHelper::HasConflictingChainLock(int nHeight, const uint256& blockHash) const +{ + return clhandler.HasConflictingChainLock(nHeight, blockHash); +} + +bool CChainstateHelper::HasChainLock(int nHeight, const uint256& blockHash) const +{ + return clhandler.HasChainLock(nHeight, blockHash); +} + +int32_t CChainstateHelper::GetBestChainLockHeight() const { return clhandler.GetBestChainLock().getHeight(); } + +/** Passthrough functions to CInstantSendManager */ +std::optional> CChainstateHelper::ConflictingISLockIfAny( + const CTransaction& tx) const +{ + const auto islock = isman.GetConflictingLock(tx); + if (!islock) return std::nullopt; + return std::make_pair(::SerializeHash(*islock), islock->txid); +} + +bool CChainstateHelper::IsInstantSendWaitingForTx(const uint256& hash) const { return isman.IsWaitingForTx(hash); } + +bool CChainstateHelper::RemoveConflictingISLockByTx(const CTransaction& tx) +{ + const auto islock = isman.GetConflictingLock(tx); + if (!islock) return false; + isman.RemoveConflictingLock(::SerializeHash(*islock), *islock); + return true; +} + +bool CChainstateHelper::ShouldInstantSendRejectConflicts() const { return isman.RejectConflictingBlocks(); } diff --git a/src/evo/chainhelper.h b/src/evo/chainhelper.h index 73db5b3427..82b6597e3a 100644 --- a/src/evo/chainhelper.h +++ b/src/evo/chainhelper.h @@ -6,6 +6,7 @@ #define BITCOIN_EVO_CHAINHELPER_H #include +#include class CCreditPoolManager; class CDeterministicMNManager; @@ -16,26 +17,47 @@ class CMasternodeSync; class CGovernanceManager; class CSpecialTxProcessor; class CSporkManager; +class CTransaction; +class uint256; namespace Consensus { struct Params; } namespace llmq { class CChainLocksHandler; +class CInstantSendManager; class CQuorumBlockProcessor; class CQuorumManager; +class CQuorumSnapshotManager; } class CChainstateHelper { +private: + llmq::CInstantSendManager& isman; + const llmq::CChainLocksHandler& clhandler; + public: - explicit CChainstateHelper(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, CMNHFManager& mnhfman, CGovernanceManager& govman, - llmq::CQuorumBlockProcessor& qblockman, const ChainstateManager& chainman, const Consensus::Params& consensus_params, - const CMasternodeSync& mn_sync, const CSporkManager& sporkman, const llmq::CChainLocksHandler& clhandler, - const llmq::CQuorumManager& qman); + explicit CChainstateHelper(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, CMNHFManager& mnhfman, + CGovernanceManager& govman, llmq::CInstantSendManager& isman, + llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const Consensus::Params& consensus_params, + const CMasternodeSync& mn_sync, const CSporkManager& sporkman, + const llmq::CChainLocksHandler& clhandler, const llmq::CQuorumManager& qman); ~CChainstateHelper(); CChainstateHelper() = delete; CChainstateHelper(const CChainstateHelper&) = delete; + /** Passthrough functions to CChainLocksHandler */ + bool HasConflictingChainLock(int nHeight, const uint256& blockHash) const; + bool HasChainLock(int nHeight, const uint256& blockHash) const; + int32_t GetBestChainLockHeight() const; + + /** Passthrough functions to CInstantSendManager */ + std::optional> ConflictingISLockIfAny(const CTransaction& tx) const; + bool IsInstantSendWaitingForTx(const uint256& hash) const; + bool RemoveConflictingISLockByTx(const CTransaction& tx); + bool ShouldInstantSendRejectConflicts() const; + public: const std::unique_ptr mn_payments; const std::unique_ptr special_tx; diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 96fbe4c02c..303a88c566 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -180,6 +180,7 @@ CDeterministicMNCPtr CDeterministicMNList::GetMNPayee(gsl::not_nullGetInternalId()); } -bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_null pindex, BlockValidationState& state, const CCoinsViewCache& view, bool fJustCheck, std::optional& updatesRet) +bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_null pindex, + BlockValidationState& state, const CCoinsViewCache& view, + llmq::CQuorumSnapshotManager& qsnapman, bool fJustCheck, + std::optional& updatesRet) { AssertLockHeld(cs_main); @@ -610,7 +614,7 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_nullnHeight; try { - if (!BuildNewListFromBlock(block, pindex->pprev, state, view, newList, true)) { + if (!BuildNewListFromBlock(block, pindex->pprev, state, view, newList, qsnapman, true)) { // pass the state returned by the function above return false; } @@ -700,7 +704,10 @@ void CDeterministicMNManager::UpdatedBlockTip(gsl::not_null tipIndex = pindex; } -bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::not_null pindexPrev, BlockValidationState& state, const CCoinsViewCache& view, CDeterministicMNList& mnListRet, bool debugLogs) +bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::not_null pindexPrev, + BlockValidationState& state, const CCoinsViewCache& view, + CDeterministicMNList& mnListRet, + llmq::CQuorumSnapshotManager& qsnapman, bool debugLogs) { int nHeight = pindexPrev->nHeight + 1; @@ -731,7 +738,6 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no newList.DecreaseScores(); - const bool isV19Active{DeploymentActiveAfter(pindexPrev, Params().GetConsensus(), Consensus::DEPLOYMENT_V19)}; const bool isMNRewardReallocation{DeploymentActiveAfter(pindexPrev, Params().GetConsensus(), Consensus::DEPLOYMENT_MN_RR)}; // we skip the coinbase @@ -750,10 +756,6 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no } auto& proTx = *opt_proTx; - if (proTx.nType == MnType::Evo && !isV19Active) { - return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload"); - } - auto dmn = std::make_shared(newList.GetTotalRegisteredCount(), proTx.nType); dmn->proTxHash = tx.GetHash(); @@ -813,10 +815,6 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload"); } - if (opt_proTx->nType == MnType::Evo && !DeploymentActiveAfter(pindexPrev, Params().GetConsensus(), Consensus::DEPLOYMENT_V19)) { - return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload"); - } - if (newList.HasUniqueProperty(opt_proTx->addr) && newList.GetUniquePropertyMN(opt_proTx->addr)->proTxHash != opt_proTx->proTxHash) { return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-addr"); } @@ -923,7 +921,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-quorum-hash"); } - HandleQuorumCommitment(opt_qc->commitment, pQuorumBaseBlockIndex, newList, debugLogs); + HandleQuorumCommitment(opt_qc->commitment, pQuorumBaseBlockIndex, newList, qsnapman, debugLogs); } } } @@ -995,11 +993,14 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no return true; } -void CDeterministicMNManager::HandleQuorumCommitment(const llmq::CFinalCommitment& qc, gsl::not_null pQuorumBaseBlockIndex, CDeterministicMNList& mnList, bool debugLogs) +void CDeterministicMNManager::HandleQuorumCommitment(const llmq::CFinalCommitment& qc, + gsl::not_null pQuorumBaseBlockIndex, + CDeterministicMNList& mnList, + llmq::CQuorumSnapshotManager& qsnapman, bool debugLogs) { // The commitment has already been validated at this point, so it's safe to use members of it - auto members = llmq::utils::GetAllQuorumMembers(qc.llmqType, *this, pQuorumBaseBlockIndex); + auto members = llmq::utils::GetAllQuorumMembers(qc.llmqType, *this, qsnapman, pQuorumBaseBlockIndex); for (size_t i = 0; i < members.size(); i++) { if (!mnList.HasMN(members[i]->proTxHash)) { @@ -1227,12 +1228,6 @@ bool CDeterministicMNManager::MigrateDBIfNeeded() return true; } - if (DeploymentActiveAt(*m_chainstate.m_chain.Tip(), consensusParams, Consensus::DEPLOYMENT_V19)) { - // too late - LogPrintf("CDeterministicMNManager::%s -- migration is not possible\n", __func__); - return false; - } - // Removing the old EVODB_BEST_BLOCK value early results in older version to crash immediately, even if the upgrade // process is cancelled in-between. But if the new version sees that the old EVODB_BEST_BLOCK is already removed, // then we must assume that the upgrade process was already running before but was interrupted. @@ -1255,6 +1250,13 @@ bool CDeterministicMNManager::MigrateDBIfNeeded() return true; } + if (DeploymentActiveAt(*m_chainstate.m_chain.Tip(), consensusParams, Consensus::DEPLOYMENT_V19)) { + // too late + LogPrintf("CDeterministicMNManager::%s -- migration is not possible\n", __func__); + return false; + } + + CDBBatch batch(m_evoDb.GetRawDB()); for (const auto nHeight : irange::range(Params().GetConsensus().DIP0003Height, m_chainstate.m_chain.Height() + 1)) { @@ -1342,12 +1344,6 @@ bool CDeterministicMNManager::MigrateDBIfNeeded2() return true; } - if (DeploymentActiveAt(*m_chainstate.m_chain.Tip(), consensusParams, Consensus::DEPLOYMENT_V19)) { - // too late - LogPrintf("CDeterministicMNManager::%s -- migration is not possible\n", __func__); - return false; - } - // Removing the old EVODB_BEST_BLOCK value early results in older version to crash immediately, even if the upgrade // process is cancelled in-between. But if the new version sees that the old EVODB_BEST_BLOCK is already removed, // then we must assume that the upgrade process was already running before but was interrupted. @@ -1370,6 +1366,12 @@ bool CDeterministicMNManager::MigrateDBIfNeeded2() return true; } + if (DeploymentActiveAt(*m_chainstate.m_chain.Tip(), consensusParams, Consensus::DEPLOYMENT_V19)) { + // too late + LogPrintf("CDeterministicMNManager::%s -- migration is not possible\n", __func__); + return false; + } + CDBBatch batch(m_evoDb.GetRawDB()); for (const auto nHeight : irange::range(Params().GetConsensus().DIP0003Height, m_chainstate.m_chain.Height() + 1)) { diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index 81621d8bd9..0fde8da19b 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -35,9 +35,9 @@ class TxValidationState; extern RecursiveMutex cs_main; -namespace llmq -{ - class CFinalCommitment; +namespace llmq { +class CFinalCommitment; +class CQuorumSnapshotManager; } // namespace llmq class CDeterministicMN @@ -598,15 +598,18 @@ class CDeterministicMNManager ~CDeterministicMNManager() = default; bool ProcessBlock(const CBlock& block, gsl::not_null pindex, BlockValidationState& state, - const CCoinsViewCache& view, bool fJustCheck, std::optional& updatesRet) EXCLUSIVE_LOCKS_REQUIRED(!cs, cs_main); + const CCoinsViewCache& view, llmq::CQuorumSnapshotManager& qsnapman, bool fJustCheck, + std::optional& updatesRet) EXCLUSIVE_LOCKS_REQUIRED(!cs, cs_main); bool UndoBlock(gsl::not_null pindex, std::optional& updatesRet) EXCLUSIVE_LOCKS_REQUIRED(!cs); void UpdatedBlockTip(gsl::not_null pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs); // the returned list will not contain the correct block hash (we can't know it yet as the coinbase TX is not updated yet) - bool BuildNewListFromBlock(const CBlock& block, gsl::not_null pindexPrev, BlockValidationState& state, const CCoinsViewCache& view, - CDeterministicMNList& mnListRet, bool debugLogs) EXCLUSIVE_LOCKS_REQUIRED(!cs); - void HandleQuorumCommitment(const llmq::CFinalCommitment& qc, gsl::not_null pQuorumBaseBlockIndex, CDeterministicMNList& mnList, bool debugLogs); + bool BuildNewListFromBlock(const CBlock& block, gsl::not_null pindexPrev, + BlockValidationState& state, const CCoinsViewCache& view, CDeterministicMNList& mnListRet, + llmq::CQuorumSnapshotManager& qsnapman, bool debugLogs) EXCLUSIVE_LOCKS_REQUIRED(!cs); + void HandleQuorumCommitment(const llmq::CFinalCommitment& qc, gsl::not_null pQuorumBaseBlockIndex, + CDeterministicMNList& mnList, llmq::CQuorumSnapshotManager& qsnapman, bool debugLogs); CDeterministicMNList GetListForBlock(gsl::not_null pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs) { LOCK(cs); diff --git a/src/evo/mnauth.cpp b/src/evo/mnauth.cpp index 36c6c17524..7eb2e18ce5 100644 --- a/src/evo/mnauth.cpp +++ b/src/evo/mnauth.cpp @@ -51,7 +51,8 @@ void CMNAuth::PushMNAUTH(CNode& peer, CConnman& connman, const CActiveMasternode mnauth.proRegTxHash = mn_activeman.GetProTxHash(); - mnauth.sig = mn_activeman.Sign(signHash); + // all clients uses basic BLS + mnauth.sig = mn_activeman.Sign(signHash, false); LogPrint(BCLog::NET_NETCONN, "CMNAuth::%s -- Sending MNAUTH, peer=%d\n", __func__, peer.GetId()); connman.PushMessage(&peer, CNetMsgMaker(peer.GetCommonVersion()).Make(NetMsgType::MNAUTH, mnauth)); @@ -86,7 +87,8 @@ PeerMsgRet CMNAuth::ProcessMessage(CNode& peer, ServiceFlags node_services, CCon } if (!mnauth.sig.IsValid()) { - LogPrint(BCLog::NET_NETCONN, "CMNAuth::ProcessMessage -- invalid mnauth for protx=%s with sig=%s\n", mnauth.proRegTxHash.ToString(), mnauth.sig.ToString()); + LogPrint(BCLog::NET_NETCONN, "CMNAuth::ProcessMessage -- invalid mnauth for protx=%s with sig=%s\n", + mnauth.proRegTxHash.ToString(), mnauth.sig.ToString(false)); return tl::unexpected{MisbehavingError{100, "invalid mnauth signature"}}; } @@ -112,7 +114,7 @@ PeerMsgRet CMNAuth::ProcessMessage(CNode& peer, ServiceFlags node_services, CCon } LogPrint(BCLog::NET_NETCONN, "CMNAuth::%s -- constructed signHash for nVersion %d, peer=%d\n", __func__, peer.nVersion, peer.GetId()); - if (!mnauth.sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator.Get(), signHash)) { + if (!mnauth.sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator.Get(), signHash, false)) { // Same as above, MN seems to not know its fate yet, so give it a chance to update. If this is a // malicious node (DoSing us), it'll get banned soon. return tl::unexpected{MisbehavingError{10, "mnauth signature verification failed"}}; diff --git a/src/evo/providertx.h b/src/evo/providertx.h index 5734ead944..73ec27ba61 100644 --- a/src/evo/providertx.h +++ b/src/evo/providertx.h @@ -112,7 +112,7 @@ class CProRegTx return obj; } - bool IsTriviallyValid(bool is_bls_legacy_scheme, TxValidationState& state) const; + bool IsTriviallyValid(bool is_basic_scheme_active, TxValidationState& state) const; }; class CProUpServTx @@ -192,7 +192,7 @@ class CProUpServTx return obj; } - bool IsTriviallyValid(bool is_bls_legacy_scheme, TxValidationState& state) const; + bool IsTriviallyValid(bool is_basic_scheme_active, TxValidationState& state) const; }; class CProUpRegTx @@ -257,7 +257,7 @@ class CProUpRegTx return obj; } - bool IsTriviallyValid(bool is_bls_legacy_scheme, TxValidationState& state) const; + bool IsTriviallyValid(bool is_basic_scheme_active, TxValidationState& state) const; }; class CProUpRevTx @@ -321,7 +321,7 @@ class CProUpRevTx return obj; } - bool IsTriviallyValid(bool is_bls_legacy_scheme, TxValidationState& state) const; + bool IsTriviallyValid(bool is_basic_scheme_active, TxValidationState& state) const; }; template diff --git a/src/evo/specialtxman.cpp b/src/evo/specialtxman.cpp index 969efa2703..1a6ee5f6eb 100644 --- a/src/evo/specialtxman.cpp +++ b/src/evo/specialtxman.cpp @@ -19,10 +19,11 @@ #include #include -static bool CheckSpecialTxInner(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, - const llmq::CQuorumManager& qman, const CTransaction& tx, const CBlockIndex* pindexPrev, - const CCoinsViewCache& view, const std::optional& indexes, bool check_sigs, - TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) +static bool CheckSpecialTxInner(CDeterministicMNManager& dmnman, llmq::CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const llmq::CQuorumManager& qman, + const CTransaction& tx, const CBlockIndex* pindexPrev, const CCoinsViewCache& view, + const std::optional& indexes, bool check_sigs, TxValidationState& state) + EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { AssertLockHeld(cs_main); @@ -47,7 +48,7 @@ static bool CheckSpecialTxInner(CDeterministicMNManager& dmnman, const Chainstat case TRANSACTION_COINBASE: return CheckCbTx(tx, pindexPrev, state); case TRANSACTION_QUORUM_COMMITMENT: - return llmq::CheckLLMQCommitment(dmnman, chainman, tx, pindexPrev, state); + return llmq::CheckLLMQCommitment(dmnman, qsnapman, chainman, tx, pindexPrev, state); case TRANSACTION_MNHF_SIGNAL: return CheckMNHFTx(chainman, qman, tx, pindexPrev, state); case TRANSACTION_ASSET_LOCK: @@ -66,7 +67,8 @@ static bool CheckSpecialTxInner(CDeterministicMNManager& dmnman, const Chainstat bool CSpecialTxProcessor::CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, const CCoinsViewCache& view, bool check_sigs, TxValidationState& state) { AssertLockHeld(cs_main); - return CheckSpecialTxInner(m_dmnman, m_chainman, m_qman, tx, pindexPrev, view, std::nullopt, check_sigs, state); + return CheckSpecialTxInner(m_dmnman, m_qsnapman, m_chainman, m_qman, tx, pindexPrev, view, std::nullopt, check_sigs, + state); } [[nodiscard]] bool CSpecialTxProcessor::ProcessSpecialTx(const CTransaction& tx, const CBlockIndex* pindex, TxValidationState& state) @@ -145,7 +147,8 @@ bool CSpecialTxProcessor::ProcessSpecialTxsInBlock(const CBlock& block, const CB TxValidationState tx_state; // At this moment CheckSpecialTx() and ProcessSpecialTx() may fail by 2 possible ways: // consensus failures and "TX_BAD_SPECIAL" - if (!CheckSpecialTxInner(m_dmnman, m_chainman, m_qman, *ptr_tx, pindex->pprev, view, creditPool.indexes, fCheckCbTxMerkleRoots, tx_state)) { + if (!CheckSpecialTxInner(m_dmnman, m_qsnapman, m_chainman, m_qman, *ptr_tx, pindex->pprev, view, + creditPool.indexes, fCheckCbTxMerkleRoots, tx_state)) { assert(tx_state.GetResult() == TxValidationResult::TX_CONSENSUS || tx_state.GetResult() == TxValidationResult::TX_BAD_SPECIAL); return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, tx_state.GetRejectReason(), strprintf("Special Transaction check failed (tx hash %s) %s", ptr_tx->GetHash().ToString(), tx_state.GetDebugMessage())); @@ -170,7 +173,7 @@ bool CSpecialTxProcessor::ProcessSpecialTxsInBlock(const CBlock& block, const CB nTimeQuorum += nTime3 - nTime2; LogPrint(BCLog::BENCHMARK, " - m_qblockman: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeQuorum * 0.000001); - if (!m_dmnman.ProcessBlock(block, pindex, state, view, fJustCheck, updatesRet)) { + if (!m_dmnman.ProcessBlock(block, pindex, state, view, m_qsnapman, fJustCheck, updatesRet)) { // pass the state returned by the function above return false; } @@ -179,7 +182,7 @@ bool CSpecialTxProcessor::ProcessSpecialTxsInBlock(const CBlock& block, const CB nTimeDMN += nTime4 - nTime3; LogPrint(BCLog::BENCHMARK, " - m_dmnman: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeDMN * 0.000001); - if (fCheckCbTxMerkleRoots && !CheckCbTxMerkleRoots(block, pindex, m_dmnman, m_qblockman, state, view)) { + if (fCheckCbTxMerkleRoots && !CheckCbTxMerkleRoots(block, pindex, m_dmnman, m_qsnapman, m_qblockman, state, view)) { // pass the state returned by the function above return false; } @@ -206,7 +209,7 @@ bool CSpecialTxProcessor::ProcessSpecialTxsInBlock(const CBlock& block, const CB nTimeMnehf += nTime7 - nTime6; LogPrint(BCLog::BENCHMARK, " - m_mnhfman: %.2fms [%.2fs]\n", 0.001 * (nTime7 - nTime6), nTimeMnehf * 0.000001); - if (Params().GetConsensus().V19Height == pindex->nHeight + 1) { + if (DeploymentActiveAfter(pindex, m_consensus_params, Consensus::DEPLOYMENT_V19) && bls::bls_legacy_scheme.load()) { // NOTE: The block next to the activation is the one that is using new rules. // V19 activated just activated, so we must switch to the new rules here. bls::bls_legacy_scheme.store(false); @@ -227,7 +230,7 @@ bool CSpecialTxProcessor::UndoSpecialTxsInBlock(const CBlock& block, const CBloc auto bls_legacy_scheme = bls::bls_legacy_scheme.load(); try { - if (Params().GetConsensus().V19Height == pindex->nHeight + 1) { + if (!DeploymentActiveAt(*pindex, m_consensus_params, Consensus::DEPLOYMENT_V19) && !bls_legacy_scheme) { // NOTE: The block next to the activation is the one that is using new rules. // Removing the activation block here, so we must switch back to the old rules. bls::bls_legacy_scheme.store(true); diff --git a/src/evo/specialtxman.h b/src/evo/specialtxman.h index c2148942a4..47dc319cb4 100644 --- a/src/evo/specialtxman.h +++ b/src/evo/specialtxman.h @@ -25,9 +25,10 @@ struct MNListUpdates; namespace Consensus { struct Params; } namespace llmq { +class CChainLocksHandler; class CQuorumBlockProcessor; class CQuorumManager; -class CChainLocksHandler; +class CQuorumSnapshotManager; } // namespace llmq extern RecursiveMutex cs_main; @@ -39,6 +40,7 @@ class CSpecialTxProcessor CDeterministicMNManager& m_dmnman; CMNHFManager& m_mnhfman; llmq::CQuorumBlockProcessor& m_qblockman; + llmq::CQuorumSnapshotManager& m_qsnapman; const ChainstateManager& m_chainman; const Consensus::Params& m_consensus_params; const llmq::CChainLocksHandler& m_clhandler; @@ -50,10 +52,20 @@ class CSpecialTxProcessor public: explicit CSpecialTxProcessor(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, CMNHFManager& mnhfman, - llmq::CQuorumBlockProcessor& qblockman, const ChainstateManager& chainman, const Consensus::Params& consensus_params, + llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const Consensus::Params& consensus_params, const llmq::CChainLocksHandler& clhandler, const llmq::CQuorumManager& qman) : - m_cpoolman(cpoolman), m_dmnman{dmnman}, m_mnhfman{mnhfman}, m_qblockman{qblockman}, m_chainman(chainman), m_consensus_params{consensus_params}, - m_clhandler{clhandler}, m_qman{qman} {} + m_cpoolman(cpoolman), + m_dmnman{dmnman}, + m_mnhfman{mnhfman}, + m_qblockman{qblockman}, + m_qsnapman{qsnapman}, + m_chainman(chainman), + m_consensus_params{consensus_params}, + m_clhandler{clhandler}, + m_qman{qman} + { + } bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, const CCoinsViewCache& view, bool check_sigs, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main); diff --git a/src/init.cpp b/src/init.cpp index 24bef37c05..1369903bd3 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -71,46 +71,37 @@ #include #include #include - #include +#include -#include +#include #include #include -#ifdef ENABLE_WALLET -#include -#include -#endif // ENABLE_WALLET #include #include +#include +#include +#include #include #include +#include +#include +#include +#include #include +#include #include #include #include #include #include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include +#ifdef ENABLE_WALLET +#include +#include +#endif // ENABLE_WALLET + #include #include #include @@ -124,8 +115,6 @@ #include #include -#include - #ifndef WIN32 #include #include @@ -335,8 +324,8 @@ void PrepareShutdown(NodeContext& node) chainstate->ResetCoinsViews(); } } - DashChainstateSetupClose(node.chain_helper, node.cpoolman, node.dmnman, node.mnhf_manager, - llmq::quorumSnapshotManager, node.llmq_ctx, Assert(node.mempool.get())); + DashChainstateSetupClose(node.chain_helper, node.cpoolman, node.dmnman, node.mnhf_manager, node.llmq_ctx, + Assert(node.mempool.get())); node.mnhf_manager.reset(); node.evodb.reset(); } @@ -716,7 +705,7 @@ void SetupServerArgs(ArgsManager& argsman) argsman.AddArg("-sporkkey=", "Set the private key to be used for signing spork messages.", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::DEBUG_TEST); argsman.AddArg("-uacomment=", "Append comment to the user agent string", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); - SetupChainParamsBaseOptions(argsman); + SetupChainParamsOptions(argsman); argsman.AddArg("-llmq-data-recovery=", strprintf("Enable automated quorum data recovery (default: %u)", llmq::DEFAULT_ENABLE_QUORUM_DATA_RECOVERY), ArgsManager::ALLOW_ANY, OptionsCategory::MASTERNODE); argsman.AddArg("-llmq-qvvec-sync=:", strprintf("Defines from which LLMQ type the masternode should sync quorum verification vectors. Can be used multiple times with different LLMQ types. : %d (sync always from all quorums of the type defined by ), %d (sync from all quorums of the type defined by if a member of any of the quorums)", (int32_t)llmq::QvvecSyncMode::Always, (int32_t)llmq::QvvecSyncMode::OnlyIfTypeMember), ArgsManager::ALLOW_ANY, OptionsCategory::MASTERNODE); @@ -1858,9 +1847,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) node.dmnman, node.evodb, node.mnhf_manager, - llmq::chainLocksHandler, - llmq::quorumInstantSendManager, - llmq::quorumSnapshotManager, node.llmq_ctx, Assert(node.mempool.get()), fPruneMode, @@ -2035,7 +2021,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) // ********************************************************* Step 7c: Setup CoinJoin node.cj_ctx = std::make_unique(chainman, *node.connman, *node.dmnman, *node.mn_metaman, *node.mempool, - node.mn_activeman.get(), *node.mn_sync, node.peerman, !ignores_incoming_txs); + node.mn_activeman.get(), *node.mn_sync, *node.llmq_ctx->isman, node.peerman, + !ignores_incoming_txs); #ifdef ENABLE_WALLET node.coinjoin_loader = interfaces::MakeCoinJoinLoader(*node.cj_ctx->walletman); diff --git a/src/llmq/blockprocessor.cpp b/src/llmq/blockprocessor.cpp index b11ab32f81..bc752d806d 100644 --- a/src/llmq/blockprocessor.cpp +++ b/src/llmq/blockprocessor.cpp @@ -26,11 +26,12 @@ #include -static void PreComputeQuorumMembers(CDeterministicMNManager& dmnman, const CBlockIndex* pindex, bool reset_cache = false) +static void PreComputeQuorumMembers(CDeterministicMNManager& dmnman, llmq::CQuorumSnapshotManager& qsnapman, + const CBlockIndex* pindex, bool reset_cache) { for (const Consensus::LLMQParams& params : llmq::GetEnabledQuorumParams(pindex->pprev)) { if (llmq::IsQuorumRotationEnabled(params, pindex) && (pindex->nHeight % params.dkgInterval == 0)) { - llmq::utils::GetAllQuorumMembers(params.type, dmnman, pindex, reset_cache); + llmq::utils::GetAllQuorumMembers(params.type, dmnman, qsnapman, pindex, reset_cache); } } } @@ -43,10 +44,12 @@ static const std::string DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT_Q_INDEXED = "q_m static const std::string DB_BEST_BLOCK_UPGRADE = "q_bbu2"; -CQuorumBlockProcessor::CQuorumBlockProcessor(CChainState& chainstate, CDeterministicMNManager& dmnman, CEvoDB& evoDb) : +CQuorumBlockProcessor::CQuorumBlockProcessor(CChainState& chainstate, CDeterministicMNManager& dmnman, CEvoDB& evoDb, + CQuorumSnapshotManager& qsnapman) : m_chainstate(chainstate), m_dmnman(dmnman), - m_evoDb(evoDb) + m_evoDb(evoDb), + m_qsnapman(qsnapman) { utils::InitQuorumsCache(mapHasMinedCommitmentCache); } @@ -133,7 +136,7 @@ MessageProcessingResult CQuorumBlockProcessor::ProcessMessage(const CNode& peer, } } - if (!qc.Verify(m_dmnman, pQuorumBaseBlockIndex, true)) { + if (!qc.Verify(m_dmnman, m_qsnapman, pQuorumBaseBlockIndex, /*checkSigs=*/true)) { LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- commitment for quorum %s:%d is not valid quorumIndex[%d] nversion[%d], peer=%d\n", __func__, qc.quorumHash.ToString(), ToUnderlying(qc.llmqType), qc.quorumIndex, qc.nVersion, peer.GetId()); @@ -159,7 +162,7 @@ bool CQuorumBlockProcessor::ProcessBlock(const CBlock& block, gsl::not_null qcs; if (!GetCommitmentsFromBlock(block, pindex, qcs, state)) { @@ -270,7 +273,7 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH const auto* pQuorumBaseBlockIndex = m_chainstate.m_blockman.LookupBlockIndex(qc.quorumHash); - if (!qc.Verify(m_dmnman, pQuorumBaseBlockIndex, fBLSChecks)) { + if (!qc.Verify(m_dmnman, m_qsnapman, pQuorumBaseBlockIndex, /*checkSigs=*/fBLSChecks)) { LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s height=%d, type=%d, quorumIndex=%d, quorumHash=%s, signers=%s, validMembers=%d, quorumPublicKey=%s qc verify failed.\n", __func__, nHeight, ToUnderlying(qc.llmqType), qc.quorumIndex, quorumHash.ToString(), qc.CountSigners(), qc.CountValidMembers(), qc.quorumPublicKey.ToString()); return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-invalid"); @@ -314,7 +317,7 @@ bool CQuorumBlockProcessor::UndoBlock(const CBlock& block, gsl::not_null qcs; if (BlockValidationState dummy; !GetCommitmentsFromBlock(block, pindex, qcs, dummy)) { diff --git a/src/llmq/blockprocessor.h b/src/llmq/blockprocessor.h index da5dea17fb..b4723674eb 100644 --- a/src/llmq/blockprocessor.h +++ b/src/llmq/blockprocessor.h @@ -30,8 +30,9 @@ extern RecursiveMutex cs_main; namespace llmq { - class CFinalCommitment; +class CQuorumSnapshotManager; + using CFinalCommitmentPtr = std::unique_ptr; class CQuorumBlockProcessor @@ -40,6 +41,7 @@ class CQuorumBlockProcessor CChainState& m_chainstate; CDeterministicMNManager& m_dmnman; CEvoDB& m_evoDb; + CQuorumSnapshotManager& m_qsnapman; mutable Mutex minableCommitmentsCs; std::map, uint256> minableCommitmentsByQuorum GUARDED_BY(minableCommitmentsCs); @@ -48,7 +50,8 @@ class CQuorumBlockProcessor mutable std::map> mapHasMinedCommitmentCache GUARDED_BY(minableCommitmentsCs); public: - explicit CQuorumBlockProcessor(CChainState& chainstate, CDeterministicMNManager& dmnman, CEvoDB& evoDb); + explicit CQuorumBlockProcessor(CChainState& chainstate, CDeterministicMNManager& dmnman, CEvoDB& evoDb, + CQuorumSnapshotManager& qsnapman); MessageProcessingResult ProcessMessage(const CNode& peer, std::string_view msg_type, CDataStream& vRecv); diff --git a/src/llmq/chainlocks.cpp b/src/llmq/chainlocks.cpp index 1b6f56f5c8..a8abd6f951 100644 --- a/src/llmq/chainlocks.cpp +++ b/src/llmq/chainlocks.cpp @@ -29,8 +29,6 @@ static bool ChainLocksSigningEnabled(const CSporkManager& sporkman) namespace llmq { -std::unique_ptr chainLocksHandler; - CChainLocksHandler::CChainLocksHandler(CChainState& chainstate, CQuorumManager& _qman, CSigningManager& _sigman, CSigSharesManager& _shareman, CSporkManager& sporkman, CTxMemPool& _mempool, const CMasternodeSync& mn_sync, bool is_masternode) : @@ -54,14 +52,14 @@ CChainLocksHandler::~CChainLocksHandler() scheduler_thread->join(); } -void CChainLocksHandler::Start() +void CChainLocksHandler::Start(const llmq::CInstantSendManager& isman) { sigman.RegisterRecoveredSigsListener(this); scheduler->scheduleEvery([&]() { CheckActiveState(); EnforceBestChainLock(); // regularly retry signing the current chaintip as it might have failed before due to missing islocks - TrySignChainTip(); + TrySignChainTip(isman); }, std::chrono::seconds{5}); } @@ -185,7 +183,7 @@ void CChainLocksHandler::AcceptedBlockHeader(gsl::not_null p } } -void CChainLocksHandler::UpdatedBlockTip() +void CChainLocksHandler::UpdatedBlockTip(const llmq::CInstantSendManager& isman) { // don't call TrySignChainTip directly but instead let the scheduler call it. This way we ensure that cs_main is // never locked and TrySignChainTip is not called twice in parallel. Also avoids recursive calls due to @@ -195,7 +193,7 @@ void CChainLocksHandler::UpdatedBlockTip() scheduler->scheduleFromNow([&]() { CheckActiveState(); EnforceBestChainLock(); - TrySignChainTip(); + TrySignChainTip(isman); tryLockChainTipScheduled = false; }, std::chrono::seconds{0}); } @@ -217,7 +215,7 @@ void CChainLocksHandler::CheckActiveState() } } -void CChainLocksHandler::TrySignChainTip() +void CChainLocksHandler::TrySignChainTip(const llmq::CInstantSendManager& isman) { Cleanup(); @@ -274,7 +272,7 @@ void CChainLocksHandler::TrySignChainTip() // considered safe when it is islocked or at least known since 10 minutes (from mempool or block). These checks are // performed for the tip (which we try to sign) and the previous 5 blocks. If a ChainLocked block is found on the // way down, we consider all TXs to be safe. - if (quorumInstantSendManager->IsInstantSendEnabled() && quorumInstantSendManager->RejectConflictingBlocks()) { + if (isman.IsInstantSendEnabled() && isman.RejectConflictingBlocks()) { const auto* pindexWalk = pindex; while (pindexWalk != nullptr) { if (pindex->nHeight - pindexWalk->nHeight > 5) { @@ -305,7 +303,7 @@ void CChainLocksHandler::TrySignChainTip() } } - if (txAge < WAIT_FOR_ISLOCK_TIMEOUT && !quorumInstantSendManager->IsLocked(txid)) { + if (txAge < WAIT_FOR_ISLOCK_TIMEOUT && !isman.IsLocked(txid)) { LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- not signing block %s due to TX %s not being islocked and not old enough. age=%d\n", __func__, pindexWalk->GetBlockHash().ToString(), txid.ToString(), txAge); return; diff --git a/src/llmq/chainlocks.h b/src/llmq/chainlocks.h index 04c080453b..3ceb11b1bf 100644 --- a/src/llmq/chainlocks.h +++ b/src/llmq/chainlocks.h @@ -31,6 +31,7 @@ class CTxMemPool; namespace llmq { +class CInstantSendManager; class CSigningManager; class CSigSharesManager; enum class VerifyRecSigStatus; @@ -89,7 +90,7 @@ class CChainLocksHandler : public CRecoveredSigsListener const CMasternodeSync& mn_sync, bool is_masternode); ~CChainLocksHandler(); - void Start(); + void Start(const llmq::CInstantSendManager& isman); void Stop(); bool AlreadyHave(const CInv& inv) const EXCLUSIVE_LOCKS_REQUIRED(!cs); @@ -100,12 +101,12 @@ class CChainLocksHandler : public CRecoveredSigsListener const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(!cs); void AcceptedBlockHeader(gsl::not_null pindexNew) EXCLUSIVE_LOCKS_REQUIRED(!cs); - void UpdatedBlockTip(); + void UpdatedBlockTip(const llmq::CInstantSendManager& isman); void TransactionAddedToMempool(const CTransactionRef& tx, int64_t nAcceptTime) EXCLUSIVE_LOCKS_REQUIRED(!cs); void BlockConnected(const std::shared_ptr& pblock, gsl::not_null pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs); void BlockDisconnected(const std::shared_ptr& pblock, gsl::not_null pindexDisconnected) EXCLUSIVE_LOCKS_REQUIRED(!cs); void CheckActiveState() EXCLUSIVE_LOCKS_REQUIRED(!cs); - void TrySignChainTip() EXCLUSIVE_LOCKS_REQUIRED(!cs); + void TrySignChainTip(const llmq::CInstantSendManager& isman) EXCLUSIVE_LOCKS_REQUIRED(!cs); void EnforceBestChainLock() EXCLUSIVE_LOCKS_REQUIRED(!cs); [[nodiscard]] MessageProcessingResult HandleNewRecoveredSig(const CRecoveredSig& recoveredSig) override EXCLUSIVE_LOCKS_REQUIRED(!cs); @@ -126,8 +127,6 @@ class CChainLocksHandler : public CRecoveredSigsListener void Cleanup() EXCLUSIVE_LOCKS_REQUIRED(!cs); }; -extern std::unique_ptr chainLocksHandler; - bool AreChainLocksEnabled(const CSporkManager& sporkman); } // namespace llmq diff --git a/src/llmq/commitment.cpp b/src/llmq/commitment.cpp index 607be69f1b..4727fa2533 100644 --- a/src/llmq/commitment.cpp +++ b/src/llmq/commitment.cpp @@ -27,7 +27,8 @@ CFinalCommitment::CFinalCommitment(const Consensus::LLMQParams& params, const ui { } -bool CFinalCommitment::Verify(CDeterministicMNManager& dmnman, gsl::not_null pQuorumBaseBlockIndex, bool checkSigs) const +bool CFinalCommitment::Verify(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + gsl::not_null pQuorumBaseBlockIndex, bool checkSigs) const { const auto& llmq_params_opt = Params().GetLLMQ(llmqType); if (!llmq_params_opt.has_value()) { @@ -81,7 +82,7 @@ bool CFinalCommitment::Verify(CDeterministicMNManager& dmnman, gsl::not_null pindexPrev, TxValidationState& state) +bool CheckLLMQCommitment(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const CTransaction& tx, + gsl::not_null pindexPrev, TxValidationState& state) { const auto opt_qcTx = GetTxPayload(tx); if (!opt_qcTx) { @@ -219,7 +222,7 @@ bool CheckLLMQCommitment(CDeterministicMNManager& dmnman, const ChainstateManage return true; } - if (!qcTx.commitment.Verify(dmnman, pQuorumBaseBlockIndex, false)) { + if (!qcTx.commitment.Verify(dmnman, qsnapman, pQuorumBaseBlockIndex, false)) { LogPrint(BCLog::LLMQ, "CFinalCommitment -- h[%d] invalid qcTx.commitment[%s] Verify failed\n", pindexPrev->nHeight, qcTx.commitment.quorumHash.ToString()); return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-qc-invalid"); } diff --git a/src/llmq/commitment.h b/src/llmq/commitment.h index 3cb02b93b5..6adbdcbb4c 100644 --- a/src/llmq/commitment.h +++ b/src/llmq/commitment.h @@ -27,6 +27,7 @@ class TxValidationState; namespace llmq { +class CQuorumSnapshotManager; // This message is an aggregation of all received premature commitments and only valid if // enough (>=threshold) premature commitments were aggregated @@ -65,7 +66,8 @@ class CFinalCommitment return int(std::count(validMembers.begin(), validMembers.end(), true)); } - bool Verify(CDeterministicMNManager& dmnman, gsl::not_null pQuorumBaseBlockIndex, bool checkSigs) const; + bool Verify(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + gsl::not_null pQuorumBaseBlockIndex, bool checkSigs) const; bool VerifyNull() const; bool VerifySizes(const Consensus::LLMQParams& params) const; @@ -175,7 +177,9 @@ class CFinalCommitmentTxPayload } }; -bool CheckLLMQCommitment(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, const CTransaction& tx, gsl::not_null pindexPrev, TxValidationState& state); +bool CheckLLMQCommitment(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const CTransaction& tx, + gsl::not_null pindexPrev, TxValidationState& state); uint256 BuildCommitmentHash(Consensus::LLMQType llmqType, const uint256& blockHash, const std::vector& validMembers, const CBLSPublicKey& pubKey, const uint256& vvecHash); diff --git a/src/llmq/context.cpp b/src/llmq/context.cpp index 8e8307b5c5..876c38334f 100644 --- a/src/llmq/context.cpp +++ b/src/llmq/context.cpp @@ -17,6 +17,7 @@ #include #include #include +#include LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CEvoDB& evo_db, CMasternodeMetaMan& mn_metaman, CMNHFManager& mnhfman, CSporkManager& sporkman, @@ -25,31 +26,21 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& d is_masternode{mn_activeman != nullptr}, bls_worker{std::make_shared()}, dkg_debugman{std::make_unique()}, - quorum_block_processor{std::make_unique(chainman.ActiveChainstate(), dmnman, evo_db)}, + qsnapman{std::make_unique(evo_db)}, + quorum_block_processor{ + std::make_unique(chainman.ActiveChainstate(), dmnman, evo_db, *qsnapman)}, qdkgsman{std::make_unique(*bls_worker, chainman.ActiveChainstate(), dmnman, *dkg_debugman, - mn_metaman, *quorum_block_processor, mn_activeman, sporkman, - unit_tests, wipe)}, + mn_metaman, *quorum_block_processor, *qsnapman, mn_activeman, + sporkman, unit_tests, wipe)}, qman{std::make_unique(*bls_worker, chainman.ActiveChainstate(), dmnman, *qdkgsman, evo_db, - *quorum_block_processor, mn_activeman, mn_sync, sporkman, unit_tests, - wipe)}, + *quorum_block_processor, *qsnapman, mn_activeman, mn_sync, sporkman, + unit_tests, wipe)}, sigman{std::make_unique(mn_activeman, chainman.ActiveChainstate(), *qman, unit_tests, wipe)}, shareman{std::make_unique(*sigman, mn_activeman, *qman, sporkman)}, - clhandler{[&]() -> llmq::CChainLocksHandler* const { - assert(llmq::chainLocksHandler == nullptr); - llmq::chainLocksHandler = std::make_unique(chainman.ActiveChainstate(), *qman, - *sigman, *shareman, sporkman, mempool, - mn_sync, is_masternode); - return llmq::chainLocksHandler.get(); - }()}, - isman{[&]() -> llmq::CInstantSendManager* const { - assert(llmq::quorumInstantSendManager == nullptr); - llmq::quorumInstantSendManager = std::make_unique(*llmq::chainLocksHandler, - chainman.ActiveChainstate(), *qman, - *sigman, *shareman, sporkman, - mempool, mn_sync, is_masternode, - unit_tests, wipe); - return llmq::quorumInstantSendManager.get(); - }()}, + clhandler{std::make_unique(chainman.ActiveChainstate(), *qman, *sigman, *shareman, + sporkman, mempool, mn_sync, is_masternode)}, + isman{std::make_unique(*clhandler, chainman.ActiveChainstate(), *qman, *sigman, *shareman, + sporkman, mempool, mn_sync, is_masternode, unit_tests, wipe)}, ehfSignalsHandler{std::make_unique(chainman, mnhfman, *sigman, *shareman, *qman)} { // Have to start it early to let VerifyDB check ChainLock signatures in coinbase @@ -58,44 +49,30 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& d LLMQContext::~LLMQContext() { bls_worker->Stop(); - - // LLMQContext doesn't own these objects, but still need to care of them for consistency: - llmq::quorumInstantSendManager.reset(); - llmq::chainLocksHandler.reset(); } void LLMQContext::Interrupt() { - sigman->InterruptWorkerThread(); + isman->InterruptWorkerThread(); shareman->InterruptWorkerThread(); - - assert(isman == llmq::quorumInstantSendManager.get()); - llmq::quorumInstantSendManager->InterruptWorkerThread(); + sigman->InterruptWorkerThread(); } void LLMQContext::Start(CConnman& connman, PeerManager& peerman) { - assert(clhandler == llmq::chainLocksHandler.get()); - assert(isman == llmq::quorumInstantSendManager.get()); - if (is_masternode) { qdkgsman->StartThreads(connman, peerman); } qman->Start(); + sigman->StartWorkerThread(peerman); shareman->RegisterAsRecoveredSigsListener(); shareman->StartWorkerThread(connman, peerman); - sigman->StartWorkerThread(peerman); - - llmq::chainLocksHandler->Start(); - llmq::quorumInstantSendManager->Start(peerman); + clhandler->Start(*isman); + isman->Start(peerman); } void LLMQContext::Stop() { - assert(clhandler == llmq::chainLocksHandler.get()); - assert(isman == llmq::quorumInstantSendManager.get()); - - llmq::quorumInstantSendManager->Stop(); - llmq::chainLocksHandler->Stop(); - + isman->Stop(); + clhandler->Stop(); shareman->StopWorkerThread(); shareman->UnregisterAsRecoveredSigsListener(); sigman->StopWorkerThread(); diff --git a/src/llmq/context.h b/src/llmq/context.h index 0e92e6a90f..deb395dce3 100644 --- a/src/llmq/context.h +++ b/src/llmq/context.h @@ -28,6 +28,7 @@ class CEHFSignalsHandler; class CInstantSendManager; class CQuorumBlockProcessor; class CQuorumManager; +class CQuorumSnapshotManager; class CSigSharesManager; class CSigningManager; } @@ -61,13 +62,14 @@ struct LLMQContext { */ const std::shared_ptr bls_worker; const std::unique_ptr dkg_debugman; + const std::unique_ptr qsnapman; const std::unique_ptr quorum_block_processor; const std::unique_ptr qdkgsman; const std::unique_ptr qman; const std::unique_ptr sigman; const std::unique_ptr shareman; - llmq::CChainLocksHandler* const clhandler; - llmq::CInstantSendManager* const isman; + const std::unique_ptr clhandler; + const std::unique_ptr isman; // TODO: split CInstantSendManager and CInstantSendLock to 2 files const std::unique_ptr ehfSignalsHandler; }; diff --git a/src/llmq/debug.cpp b/src/llmq/debug.cpp index c042fd0c98..9e70b3bff3 100644 --- a/src/llmq/debug.cpp +++ b/src/llmq/debug.cpp @@ -15,8 +15,8 @@ namespace llmq { -UniValue CDKGDebugSessionStatus::ToJson(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, - int quorumIndex, int detailLevel) const +UniValue CDKGDebugSessionStatus::ToJson(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, int quorumIndex, int detailLevel) const { UniValue ret(UniValue::VOBJ); @@ -28,7 +28,7 @@ UniValue CDKGDebugSessionStatus::ToJson(CDeterministicMNManager& dmnman, const C if (detailLevel == 2) { const CBlockIndex* pindex = WITH_LOCK(cs_main, return chainman.m_blockman.LookupBlockIndex(quorumHash)); if (pindex != nullptr) { - dmnMembers = utils::GetAllQuorumMembers(llmqType, dmnman, pindex); + dmnMembers = utils::GetAllQuorumMembers(llmqType, dmnman, qsnapman, pindex); } } @@ -109,8 +109,8 @@ UniValue CDKGDebugSessionStatus::ToJson(CDeterministicMNManager& dmnman, const C CDKGDebugManager::CDKGDebugManager() = default; -UniValue CDKGDebugStatus::ToJson(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, - int detailLevel) const +UniValue CDKGDebugStatus::ToJson(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, int detailLevel) const { UniValue ret(UniValue::VOBJ); @@ -127,7 +127,7 @@ UniValue CDKGDebugStatus::ToJson(CDeterministicMNManager& dmnman, const Chainsta UniValue s(UniValue::VOBJ); s.pushKV("llmqType", std::string(llmq_params_opt->name)); s.pushKV("quorumIndex", p.first.second); - s.pushKV("status", p.second.ToJson(dmnman, chainman, p.first.second, detailLevel)); + s.pushKV("status", p.second.ToJson(dmnman, qsnapman, chainman, p.first.second, detailLevel)); sessionsArrJson.push_back(s); } diff --git a/src/llmq/debug.h b/src/llmq/debug.h index 7498a281ab..337ce82de1 100644 --- a/src/llmq/debug.h +++ b/src/llmq/debug.h @@ -20,6 +20,7 @@ class CScheduler; namespace llmq { +class CQuorumSnapshotManager; enum class QuorumPhase; @@ -76,8 +77,8 @@ class CDKGDebugSessionStatus public: CDKGDebugSessionStatus() : statusBitset(0) {} - UniValue ToJson(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, - int quorumIndex, int detailLevel) const; + UniValue ToJson(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, int quorumIndex, int detailLevel) const; }; class CDKGDebugStatus @@ -89,8 +90,8 @@ class CDKGDebugStatus //std::map sessions; public: - UniValue ToJson(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, - int detailLevel) const; + UniValue ToJson(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, int detailLevel) const; }; class CDKGDebugManager diff --git a/src/llmq/dkgsession.cpp b/src/llmq/dkgsession.cpp index b63ebf45a4..2ccc85a0f4 100644 --- a/src/llmq/dkgsession.cpp +++ b/src/llmq/dkgsession.cpp @@ -74,7 +74,8 @@ CDKGMember::CDKGMember(const CDeterministicMNCPtr& _dmn, size_t _idx) : CDKGSession::CDKGSession(const CBlockIndex* pQuorumBaseBlockIndex, const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, CDKGDebugManager& _dkgDebugManager, CMasternodeMetaMan& mn_metaman, - const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman) : + CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, + const CSporkManager& sporkman) : params(_params), blsWorker(_blsWorker), cache(_blsWorker), @@ -82,15 +83,17 @@ CDKGSession::CDKGSession(const CBlockIndex* pQuorumBaseBlockIndex, const Consens dkgManager(_dkgManager), dkgDebugManager(_dkgDebugManager), m_mn_metaman(mn_metaman), + m_qsnapman(qsnapman), m_mn_activeman(mn_activeman), m_sporkman(sporkman), - m_quorum_base_block_index{pQuorumBaseBlockIndex} + m_quorum_base_block_index{pQuorumBaseBlockIndex}, + m_use_legacy_bls{!DeploymentActiveAfter(m_quorum_base_block_index, Params().GetConsensus(), Consensus::DEPLOYMENT_V19)} { } bool CDKGSession::Init(const uint256& _myProTxHash, int _quorumIndex) { - const auto mns = utils::GetAllQuorumMembers(params.type, m_dmnman, m_quorum_base_block_index); + const auto mns = utils::GetAllQuorumMembers(params.type, m_dmnman, m_qsnapman, m_quorum_base_block_index); quorumIndex = _quorumIndex; members.resize(mns.size()); memberIds.resize(members.size()); @@ -135,7 +138,8 @@ bool CDKGSession::Init(const uint256& _myProTxHash, int _quorumIndex) if (!myProTxHash.IsNull()) { dkgDebugManager.InitLocalSessionStatus(params, quorumIndex, m_quorum_base_block_index->GetBlockHash(), m_quorum_base_block_index->nHeight); - relayMembers = utils::GetQuorumRelayMembers(params, m_dmnman, m_quorum_base_block_index, myProTxHash, true); + relayMembers = utils::GetQuorumRelayMembers(params, m_dmnman, m_qsnapman, m_quorum_base_block_index, + myProTxHash, true); if (LogAcceptDebug(BCLog::LLMQ)) { std::stringstream ss; for (const auto& r : relayMembers) { @@ -215,7 +219,7 @@ void CDKGSession::SendContributions(CDKGPendingMessages& pendingMessages, PeerMa logger.Batch("encrypted contributions. time=%d", t1.count()); - qc.sig = m_mn_activeman->Sign(qc.GetSignHash()); + qc.sig = m_mn_activeman->Sign(qc.GetSignHash(), m_use_legacy_bls); logger.Flush(); @@ -527,7 +531,7 @@ void CDKGSession::SendComplaint(CDKGPendingMessages& pendingMessages, PeerManage logger.Batch("sending complaint. badCount=%d, complaintCount=%d", badCount, complaintCount); - qc.sig = m_mn_activeman->Sign(qc.GetSignHash()); + qc.sig = m_mn_activeman->Sign(qc.GetSignHash(), m_use_legacy_bls); logger.Flush(); @@ -721,7 +725,7 @@ void CDKGSession::SendJustification(CDKGPendingMessages& pendingMessages, PeerMa return; } - qj.sig = m_mn_activeman->Sign(qj.GetSignHash()); + qj.sig = m_mn_activeman->Sign(qj.GetSignHash(), m_use_legacy_bls); logger.Flush(); @@ -1011,19 +1015,17 @@ void CDKGSession::SendCommitment(CDKGPendingMessages& pendingMessages, PeerManag (*commitmentHash.begin())++; } - qc.sig = m_mn_activeman->Sign(commitmentHash); - qc.quorumSig = skShare.Sign(commitmentHash); + qc.sig = m_mn_activeman->Sign(commitmentHash, m_use_legacy_bls); + qc.quorumSig = skShare.Sign(commitmentHash, m_use_legacy_bls); if (lieType == 3) { - const bool is_bls_legacy = bls::bls_legacy_scheme.load(); - std::vector buf = qc.sig.ToByteVector(is_bls_legacy); + std::vector buf = qc.sig.ToByteVector(m_use_legacy_bls); buf[5]++; - qc.sig.SetByteVector(buf, is_bls_legacy); + qc.sig.SetByteVector(buf, m_use_legacy_bls); } else if (lieType == 4) { - const bool is_bls_legacy = bls::bls_legacy_scheme.load(); - std::vector buf = qc.quorumSig.ToByteVector(is_bls_legacy); + std::vector buf = qc.quorumSig.ToByteVector(m_use_legacy_bls); buf[5]++; - qc.quorumSig.SetByteVector(buf, is_bls_legacy); + qc.quorumSig.SetByteVector(buf, m_use_legacy_bls); } t3.stop(); @@ -1272,7 +1274,7 @@ std::vector CDKGSession::FinalizeCommitments() t2.stop(); cxxtimer::Timer t3(true); - if (!fqc.Verify(m_dmnman, m_quorum_base_block_index, true)) { + if (!fqc.Verify(m_dmnman, m_qsnapman, m_quorum_base_block_index, true)) { logger.Batch("failed to verify final commitment"); continue; } diff --git a/src/llmq/dkgsession.h b/src/llmq/dkgsession.h index b1897482fc..af52b81f8d 100644 --- a/src/llmq/dkgsession.h +++ b/src/llmq/dkgsession.h @@ -36,6 +36,7 @@ class CDKGDebugManager; class CDKGSession; class CDKGSessionManager; class CDKGPendingMessages; +class CQuorumSnapshotManager; class CDKGContribution { @@ -286,10 +287,12 @@ class CDKGSession CDKGSessionManager& dkgManager; CDKGDebugManager& dkgDebugManager; CMasternodeMetaMan& m_mn_metaman; + CQuorumSnapshotManager& m_qsnapman; const CActiveMasternodeManager* const m_mn_activeman; const CSporkManager& m_sporkman; const CBlockIndex* const m_quorum_base_block_index; + bool m_use_legacy_bls; int quorumIndex{0}; private: @@ -329,8 +332,8 @@ class CDKGSession public: CDKGSession(const CBlockIndex* pQuorumBaseBlockIndex, const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, CDKGDebugManager& _dkgDebugManager, - CMasternodeMetaMan& mn_metaman, const CActiveMasternodeManager* const mn_activeman, - const CSporkManager& sporkman); + CMasternodeMetaMan& mn_metaman, CQuorumSnapshotManager& qsnapman, + const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman); // TODO: remove Init completely bool Init(const uint256& _myProTxHash, int _quorumIndex); diff --git a/src/llmq/dkgsessionhandler.cpp b/src/llmq/dkgsessionhandler.cpp index 107bbf98af..95b1c0fd33 100644 --- a/src/llmq/dkgsessionhandler.cpp +++ b/src/llmq/dkgsessionhandler.cpp @@ -27,6 +27,7 @@ namespace llmq CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chainstate, CDeterministicMNManager& dmnman, CDKGDebugManager& _dkgDebugManager, CDKGSessionManager& _dkgManager, CMasternodeMetaMan& mn_metaman, CQuorumBlockProcessor& _quorumBlockProcessor, + CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman, const Consensus::LLMQParams& _params, int _quorumIndex) : blsWorker(_blsWorker), @@ -36,12 +37,13 @@ CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chai dkgManager(_dkgManager), m_mn_metaman(mn_metaman), quorumBlockProcessor(_quorumBlockProcessor), + m_qsnapman(qsnapman), m_mn_activeman(mn_activeman), m_sporkman(sporkman), params(_params), quorumIndex(_quorumIndex), curSession(std::make_unique(nullptr, _params, _blsWorker, dmnman, _dkgManager, _dkgDebugManager, - m_mn_metaman, m_mn_activeman, sporkman)), + m_mn_metaman, m_qsnapman, m_mn_activeman, sporkman)), pendingContributions( (size_t)_params.size * 2, MSG_QUORUM_CONTRIB), // we allow size*2 messages as we need to make sure we see bad behavior (double messages) @@ -189,7 +191,7 @@ bool CDKGSessionHandler::InitNewQuorum(const CBlockIndex* pQuorumBaseBlockIndex) } curSession = std::make_unique(pQuorumBaseBlockIndex, params, blsWorker, m_dmnman, dkgManager, - dkgDebugManager, m_mn_metaman, m_mn_activeman, m_sporkman); + dkgDebugManager, m_mn_metaman, m_qsnapman, m_mn_activeman, m_sporkman); if (!curSession->Init(m_mn_activeman->GetProTxHash(), quorumIndex)) { LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization failed for %s qi[%d]\n", __func__, @@ -548,9 +550,11 @@ void CDKGSessionHandler::HandleDKGRound(CConnman& connman, PeerManager& peerman) }); const auto tip_mn_list = m_dmnman.GetListAtChainTip(); - utils::EnsureQuorumConnections(params, connman, m_dmnman, m_sporkman, tip_mn_list, pQuorumBaseBlockIndex, curSession->myProTxHash, /* is_masternode = */ m_mn_activeman != nullptr); + utils::EnsureQuorumConnections(params, connman, m_dmnman, m_sporkman, m_qsnapman, tip_mn_list, pQuorumBaseBlockIndex, + curSession->myProTxHash, /* is_masternode = */ m_mn_activeman != nullptr); if (curSession->AreWeMember()) { - utils::AddQuorumProbeConnections(params, connman, m_dmnman, m_mn_metaman, m_sporkman, tip_mn_list, pQuorumBaseBlockIndex, curSession->myProTxHash); + utils::AddQuorumProbeConnections(params, connman, m_dmnman, m_mn_metaman, m_qsnapman, m_sporkman, tip_mn_list, + pQuorumBaseBlockIndex, curSession->myProTxHash); } WaitForNextPhase(QuorumPhase::Initialized, QuorumPhase::Contribute, curQuorumHash); diff --git a/src/llmq/dkgsessionhandler.h b/src/llmq/dkgsessionhandler.h index b28ae87e44..6f320894a5 100644 --- a/src/llmq/dkgsessionhandler.h +++ b/src/llmq/dkgsessionhandler.h @@ -38,6 +38,7 @@ class CDKGDebugManager; class CDKGSession; class CDKGSessionManager; class CQuorumBlockProcessor; +class CQuorumSnapshotManager; enum class QuorumPhase { Initialized = 1, @@ -134,6 +135,7 @@ class CDKGSessionHandler CDKGSessionManager& dkgManager; CMasternodeMetaMan& m_mn_metaman; CQuorumBlockProcessor& quorumBlockProcessor; + CQuorumSnapshotManager& m_qsnapman; const CActiveMasternodeManager* const m_mn_activeman; const CSporkManager& m_sporkman; const Consensus::LLMQParams params; @@ -156,8 +158,9 @@ class CDKGSessionHandler public: CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chainstate, CDeterministicMNManager& dmnman, - CDKGDebugManager& _dkgDebugManager, CDKGSessionManager& _dkgManager, CMasternodeMetaMan& mn_metaman, - CQuorumBlockProcessor& _quorumBlockProcessor, const CActiveMasternodeManager* const mn_activeman, + CDKGDebugManager& _dkgDebugManager, CDKGSessionManager& _dkgManager, + CMasternodeMetaMan& mn_metaman, CQuorumBlockProcessor& _quorumBlockProcessor, + CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman, const Consensus::LLMQParams& _params, int _quorumIndex); ~CDKGSessionHandler(); diff --git a/src/llmq/dkgsessionmgr.cpp b/src/llmq/dkgsessionmgr.cpp index d6fb0715c1..581f8932b2 100644 --- a/src/llmq/dkgsessionmgr.cpp +++ b/src/llmq/dkgsessionmgr.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -31,7 +32,7 @@ static const std::string DB_ENC_CONTRIB = "qdkg_E"; CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chainstate, CDeterministicMNManager& dmnman, CDKGDebugManager& _dkgDebugManager, CMasternodeMetaMan& mn_metaman, - CQuorumBlockProcessor& _quorumBlockProcessor, + CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman, bool unitTests, bool fWipe) : db(std::make_unique(unitTests ? "" : (gArgs.GetDataDirNet() / "llmq/dkgdb"), 1 << 20, unitTests, fWipe)), @@ -40,6 +41,7 @@ CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chai m_dmnman(dmnman), dkgDebugManager(_dkgDebugManager), quorumBlockProcessor(_quorumBlockProcessor), + m_qsnapman(qsnapman), spork_manager(sporkman) { if (mn_activeman == nullptr && !IsWatchQuorumsEnabled()) { @@ -53,7 +55,7 @@ CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chai for (const auto i : irange::range(session_count)) { dkgSessionHandlers.emplace(std::piecewise_construct, std::forward_as_tuple(params.type, i), std::forward_as_tuple(blsWorker, m_chainstate, dmnman, dkgDebugManager, *this, - mn_metaman, quorumBlockProcessor, mn_activeman, + mn_metaman, quorumBlockProcessor, m_qsnapman, mn_activeman, spork_manager, params, i)); } } @@ -297,7 +299,7 @@ void CDKGSessionManager::WriteEncryptedContributions(Consensus::LLMQType llmqTyp bool CDKGSessionManager::GetVerifiedContributions(Consensus::LLMQType llmqType, const CBlockIndex* pQuorumBaseBlockIndex, const std::vector& validMembers, std::vector& memberIndexesRet, std::vector& vvecsRet, std::vector& skContributionsRet) const { - auto members = utils::GetAllQuorumMembers(llmqType, m_dmnman, pQuorumBaseBlockIndex); + auto members = utils::GetAllQuorumMembers(llmqType, m_dmnman, m_qsnapman, pQuorumBaseBlockIndex); memberIndexesRet.clear(); vvecsRet.clear(); @@ -343,7 +345,7 @@ bool CDKGSessionManager::GetVerifiedContributions(Consensus::LLMQType llmqType, bool CDKGSessionManager::GetEncryptedContributions(Consensus::LLMQType llmqType, const CBlockIndex* pQuorumBaseBlockIndex, const std::vector& validMembers, const uint256& nProTxHash, std::vector>& vecRet) const { - auto members = utils::GetAllQuorumMembers(llmqType, m_dmnman, pQuorumBaseBlockIndex); + auto members = utils::GetAllQuorumMembers(llmqType, m_dmnman, m_qsnapman, pQuorumBaseBlockIndex); vecRet.clear(); vecRet.reserve(members.size()); diff --git a/src/llmq/dkgsessionmgr.h b/src/llmq/dkgsessionmgr.h index eaa5dc79de..ad6a38bf0b 100644 --- a/src/llmq/dkgsessionmgr.h +++ b/src/llmq/dkgsessionmgr.h @@ -6,7 +6,6 @@ #define BITCOIN_LLMQ_DKGSESSIONMGR_H #include -#include #include #include #include @@ -14,6 +13,11 @@ #include #include +template +class CBLSIESMultiRecipientObjects; +template +class CBLSIESEncryptedObject; + class CActiveMasternodeManager; class CBlockIndex; class CChainState; @@ -32,6 +36,7 @@ class UniValue; namespace llmq { +class CQuorumSnapshotManager; class CDKGSessionManager { @@ -45,6 +50,7 @@ class CDKGSessionManager CDeterministicMNManager& m_dmnman; CDKGDebugManager& dkgDebugManager; CQuorumBlockProcessor& quorumBlockProcessor; + CQuorumSnapshotManager& m_qsnapman; const CSporkManager& spork_manager; //TODO name struct instead of std::pair @@ -72,8 +78,9 @@ class CDKGSessionManager public: CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chainstate, CDeterministicMNManager& dmnman, CDKGDebugManager& _dkgDebugManager, CMasternodeMetaMan& mn_metaman, - CQuorumBlockProcessor& _quorumBlockProcessor, const CActiveMasternodeManager* const mn_activeman, - const CSporkManager& sporkman, bool unitTests, bool fWipe); + CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, + const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman, + bool unitTests, bool fWipe); ~CDKGSessionManager(); void StartThreads(CConnman& connman, PeerManager& peerman); diff --git a/src/llmq/instantsend.cpp b/src/llmq/instantsend.cpp index f5d9a9299b..7e4e8c4056 100644 --- a/src/llmq/instantsend.cpp +++ b/src/llmq/instantsend.cpp @@ -41,8 +41,6 @@ static const std::string_view DB_ARCHIVED_BY_HASH = "is_a2"; static const std::string_view DB_VERSION = "is_v"; -std::unique_ptr quorumInstantSendManager; - uint256 CInstantSendLock::GetRequestId() const { CHashWriter hw(SER_GETHASH, 0); diff --git a/src/llmq/instantsend.h b/src/llmq/instantsend.h index 158ce1b699..6ccc8eaaa6 100644 --- a/src/llmq/instantsend.h +++ b/src/llmq/instantsend.h @@ -365,9 +365,6 @@ class CInstantSendManager : public CRecoveredSigsListener bool IsInstantSendMempoolSigningEnabled() const; bool RejectConflictingBlocks() const; }; -// TODO: split CInstantSendManager and CInstantSendLock to 2 files -extern std::unique_ptr quorumInstantSendManager; - } // namespace llmq #endif // BITCOIN_LLMQ_INSTANTSEND_H diff --git a/src/llmq/params.h b/src/llmq/params.h index b9d44818f8..107b54487b 100644 --- a/src/llmq/params.h +++ b/src/llmq/params.h @@ -54,7 +54,7 @@ struct LLMQParams { // the size of the quorum, e.g. 50 or 400 int size; - // The minimum number of valid members after the DKK. If less members are determined valid, no commitment can be + // The minimum number of valid members after the DKG. If less members are determined valid, no commitment can be // created. Should be higher then the threshold to allow some room for failing nodes, otherwise quorum might end up // not being able to ever created a recovered signature if more nodes fail after the DKG int minSize; diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index a27fa04494..062bde54f1 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -212,7 +212,7 @@ bool CQuorum::ReadContributions(const CDBWrapper& db) CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, CEvoDB& _evoDb, - CQuorumBlockProcessor& _quorumBlockProcessor, + CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, const CSporkManager& sporkman, bool unit_tests, bool wipe) : db(std::make_unique(unit_tests ? "" : (gArgs.GetDataDirNet() / "llmq" / "quorumdb"), 1 << 20, @@ -222,6 +222,7 @@ CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, m_dmnman(dmnman), dkgManager(_dkgManager), quorumBlockProcessor(_quorumBlockProcessor), + m_qsnapman(qsnapman), m_mn_activeman(mn_activeman), m_mn_sync(mn_sync), m_sporkman(sporkman) @@ -365,7 +366,9 @@ void CQuorumManager::CheckQuorumConnections(CConnman& connman, const Consensus:: }); for (const auto& quorum : lastQuorums) { - if (utils::EnsureQuorumConnections(llmqParams, connman, m_dmnman, m_sporkman, m_dmnman.GetListAtChainTip(), quorum->m_quorum_base_block_index, myProTxHash, /* is_masternode = */ m_mn_activeman != nullptr)) { + if (utils::EnsureQuorumConnections(llmqParams, connman, m_dmnman, m_sporkman, m_qsnapman, + m_dmnman.GetListAtChainTip(), quorum->m_quorum_base_block_index, myProTxHash, + /* is_masternode = */ m_mn_activeman != nullptr)) { if (connmanQuorumsToDelete.erase(quorum->qc->quorumHash) > 0) { LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- llmqType[%d] h[%d] keeping mn quorum connections for quorum: [%d:%s]\n", __func__, ToUnderlying(llmqParams.type), pindexNew->nHeight, quorum->m_quorum_base_block_index->nHeight, quorum->m_quorum_base_block_index->GetBlockHash().ToString()); } @@ -407,7 +410,7 @@ CQuorumPtr CQuorumManager::BuildQuorumFromCommitment(const Consensus::LLMQType l const auto& llmq_params_opt = Params().GetLLMQ(llmqType); assert(llmq_params_opt.has_value()); auto quorum = std::make_shared(llmq_params_opt.value(), blsWorker); - auto members = utils::GetAllQuorumMembers(qc->llmqType, m_dmnman, pQuorumBaseBlockIndex); + auto members = utils::GetAllQuorumMembers(qc->llmqType, m_dmnman, m_qsnapman, pQuorumBaseBlockIndex); quorum->Init(std::move(qc), pQuorumBaseBlockIndex, minedBlockHash, members); @@ -635,7 +638,7 @@ CQuorumCPtr CQuorumManager::GetQuorum(Consensus::LLMQType llmqType, const uint25 const CBlockIndex* pQuorumBaseBlockIndex = [&]() { // Lock contention may still be high here; consider using a shared lock // We cannot hold cs_quorumBaseBlockIndexCache the whole time as that creates lock-order inversion with cs_main; - // We cannot aquire cs_main if we have cs_quorumBaseBlockIndexCache held + // We cannot acquire cs_main if we have cs_quorumBaseBlockIndexCache held const CBlockIndex* pindex; if (!WITH_LOCK(cs_quorumBaseBlockIndexCache, return quorumBaseBlockIndexCache.get(quorumHash, pindex))) { pindex = WITH_LOCK(cs_main, return m_chainstate.m_blockman.LookupBlockIndex(quorumHash)); diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index 645802efa6..56924940ce 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -48,6 +48,7 @@ enum class VerifyRecSigStatus class CDKGSessionManager; class CQuorumBlockProcessor; +class CQuorumSnapshotManager; /** * Object used as a key to store CQuorumDataRequest @@ -241,6 +242,7 @@ class CQuorumManager CDeterministicMNManager& m_dmnman; CDKGSessionManager& dkgManager; CQuorumBlockProcessor& quorumBlockProcessor; + CQuorumSnapshotManager& m_qsnapman; const CActiveMasternodeManager* const m_mn_activeman; const CMasternodeSync& m_mn_sync; const CSporkManager& m_sporkman; @@ -262,8 +264,8 @@ class CQuorumManager public: CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, - const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, - const CSporkManager& sporkman, bool unit_tests, bool wipe); + CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, + const CMasternodeSync& mn_sync, const CSporkManager& sporkman, bool unit_tests, bool wipe); ~CQuorumManager(); void Start(); diff --git a/src/llmq/signing_shares.cpp b/src/llmq/signing_shares.cpp index f77d9cedec..ed5105651f 100644 --- a/src/llmq/signing_shares.cpp +++ b/src/llmq/signing_shares.cpp @@ -1539,7 +1539,7 @@ std::optional CSigSharesManager::CreateSigShare(const CQuorumCPtr& qu CSigShare sigShare(quorum->params.type, quorum->qc->quorumHash, id, msgHash, uint16_t(memberIdx), {}); uint256 signHash = sigShare.buildSignHash(); - sigShare.sigShare.Set(skShare.Sign(signHash), bls::bls_legacy_scheme.load()); + sigShare.sigShare.Set(skShare.Sign(signHash, bls::bls_legacy_scheme.load()), bls::bls_legacy_scheme.load()); if (!sigShare.sigShare.Get().IsValid()) { LogPrintf("CSigSharesManager::%s -- failed to sign sigShare. signHash=%s, id=%s, msgHash=%s, time=%s\n", __func__, signHash.ToString(), sigShare.getId().ToString(), sigShare.getMsgHash().ToString(), t.count()); diff --git a/src/llmq/snapshot.cpp b/src/llmq/snapshot.cpp index 7b349fb31d..932139f844 100644 --- a/src/llmq/snapshot.cpp +++ b/src/llmq/snapshot.cpp @@ -21,8 +21,6 @@ namespace llmq { static const std::string DB_QUORUM_SNAPSHOT = "llmq_S"; -std::unique_ptr quorumSnapshotManager; - UniValue CQuorumSnapshot::ToJson() const { UniValue obj; @@ -86,7 +84,8 @@ UniValue CQuorumRotationInfo::ToJson() const return obj; } -bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, const CQuorumManager& qman, +bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const CQuorumManager& qman, const CQuorumBlockProcessor& qblockman, const CGetQuorumRotationInfo& request, CQuorumRotationInfo& response, std::string& errorRet) { @@ -207,7 +206,7 @@ bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateMa return false; } - auto snapshotHMinusC = quorumSnapshotManager->GetSnapshotForBlock(llmqType, pBlockHMinusCIndex); + auto snapshotHMinusC = qsnapman.GetSnapshotForBlock(llmqType, pBlockHMinusCIndex); if (!snapshotHMinusC.has_value()) { errorRet = strprintf("Can not find quorum snapshot at H-C"); return false; @@ -219,7 +218,7 @@ bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateMa return false; } - auto snapshotHMinus2C = quorumSnapshotManager->GetSnapshotForBlock(llmqType, pBlockHMinus2CIndex); + auto snapshotHMinus2C = qsnapman.GetSnapshotForBlock(llmqType, pBlockHMinus2CIndex); if (!snapshotHMinus2C.has_value()) { errorRet = strprintf("Can not find quorum snapshot at H-2C"); return false; @@ -231,7 +230,7 @@ bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateMa return false; } - auto snapshotHMinus3C = quorumSnapshotManager->GetSnapshotForBlock(llmqType, pBlockHMinus3CIndex); + auto snapshotHMinus3C = qsnapman.GetSnapshotForBlock(llmqType, pBlockHMinus3CIndex); if (!snapshotHMinus3C.has_value()) { errorRet = strprintf("Can not find quorum snapshot at H-3C"); return false; @@ -247,7 +246,7 @@ bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateMa return false; } - auto snapshotHMinus4C = quorumSnapshotManager->GetSnapshotForBlock(llmqType, pBlockHMinus4CIndex); + auto snapshotHMinus4C = qsnapman.GetSnapshotForBlock(llmqType, pBlockHMinus4CIndex); if (!snapshotHMinus4C.has_value()) { errorRet = strprintf("Can not find quorum snapshot at H-4C"); return false; @@ -303,7 +302,7 @@ bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateMa return false; } - auto snapshotNeededH = quorumSnapshotManager->GetSnapshotForBlock(llmqType, pNeededBlockIndex); + auto snapshotNeededH = qsnapman.GetSnapshotForBlock(llmqType, pNeededBlockIndex); if (!snapshotNeededH.has_value()) { errorRet = strprintf("Can not find quorum snapshot at H(%d)", h); return false; diff --git a/src/llmq/snapshot.h b/src/llmq/snapshot.h index e1e32751c5..b268c6db6e 100644 --- a/src/llmq/snapshot.h +++ b/src/llmq/snapshot.h @@ -207,7 +207,8 @@ class CQuorumRotationInfo [[nodiscard]] UniValue ToJson() const; }; -bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, const CQuorumManager& qman, +bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const ChainstateManager& chainman, const CQuorumManager& qman, const CQuorumBlockProcessor& qblockman, const CGetQuorumRotationInfo& request, CQuorumRotationInfo& response, std::string& errorRet) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); uint256 GetLastBaseBlockHash(Span baseBlockIndexes, const CBlockIndex* blockIndex); @@ -228,9 +229,6 @@ class CQuorumSnapshotManager std::optional GetSnapshotForBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex); void StoreSnapshotForBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex, const CQuorumSnapshot& snapshot); }; - -extern std::unique_ptr quorumSnapshotManager; - } // namespace llmq #endif // BITCOIN_LLMQ_SNAPSHOT_H diff --git a/src/llmq/utils.cpp b/src/llmq/utils.cpp index a9bb1e3c81..7efdad91db 100644 --- a/src/llmq/utils.cpp +++ b/src/llmq/utils.cpp @@ -24,12 +24,11 @@ #include class CBLSSignature; -namespace llmq -{ +namespace llmq { class CQuorum; using CQuorumPtr = std::shared_ptr; using CQuorumCPtr = std::shared_ptr; -} +} // namespace llmq /** * Forward declarations @@ -46,13 +45,9 @@ static bool IsV20Active(gsl::not_null pindexPrev) return DeploymentActiveAfter(pindexPrev, Params().GetConsensus(), Consensus::DEPLOYMENT_V20); } -namespace llmq -{ - -namespace utils - -{ -//QuorumMembers per quorumIndex at heights H-Cycle, H-2Cycles, H-3Cycles +namespace llmq { +namespace utils { +// QuorumMembers per quorumIndex at heights H-Cycle, H-2Cycles, H-3Cycles struct PreviousQuorumQuarters { std::vector> quarterHMinusC; std::vector> quarterHMinus2C; @@ -62,16 +57,33 @@ struct PreviousQuorumQuarters { }; // Forward declarations -static std::vector ComputeQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, const CBlockIndex* pQuorumBaseBlockIndex); -static std::vector> ComputeQuorumMembersByQuarterRotation(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CBlockIndex* pCycleQuorumBaseBlockIndex); - -static std::vector> BuildNewQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CBlockIndex* pCycleQuorumBaseBlockIndex, const PreviousQuorumQuarters& quarters); - -static PreviousQuorumQuarters GetPreviousQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CBlockIndex* pBlockHMinusCIndex, const CBlockIndex* pBlockHMinus2CIndex, const CBlockIndex* pBlockHMinus3CIndex, int nHeight); -static std::vector> GetQuorumQuarterMembersBySnapshot(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CBlockIndex* pCycleQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeights); -static std::pair GetMNUsageBySnapshot(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CBlockIndex* pCycleQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight); - -static void BuildQuorumSnapshot(const Consensus::LLMQParams& llmqParams, const CDeterministicMNList& allMns, const CDeterministicMNList& mnUsedAtH, std::vector& sortedCombinedMns, CQuorumSnapshot& quorumSnapshot, int nHeight, std::vector& skipList, const CBlockIndex* pCycleQuorumBaseBlockIndex); +static std::vector ComputeQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, + const CBlockIndex* pQuorumBaseBlockIndex); +static std::vector> ComputeQuorumMembersByQuarterRotation( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const CBlockIndex* pCycleQuorumBaseBlockIndex); + +static std::vector> BuildNewQuorumQuarterMembers( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const CBlockIndex* pCycleQuorumBaseBlockIndex, const PreviousQuorumQuarters& previousQuarters); + +static PreviousQuorumQuarters GetPreviousQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams, + CDeterministicMNManager& dmnman, + CQuorumSnapshotManager& qsnapman, + const CBlockIndex* pBlockHMinusCIndex, + const CBlockIndex* pBlockHMinus2CIndex, + const CBlockIndex* pBlockHMinus3CIndex, int nHeight); +static std::vector> GetQuorumQuarterMembersBySnapshot( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, + const CBlockIndex* pCycleQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight); +static std::pair GetMNUsageBySnapshot( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, + const CBlockIndex* pCycleQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight); + +static void BuildQuorumSnapshot(const Consensus::LLMQParams& llmqParams, const CDeterministicMNList& allMns, + const CDeterministicMNList& mnUsedAtH, + std::vector& sortedCombinedMns, CQuorumSnapshot& quorumSnapshot, + int nHeight, std::vector& skipList, const CBlockIndex* pCycleQuorumBaseBlockIndex); static uint256 GetHashModifier(const Consensus::LLMQParams& llmqParams, gsl::not_null pCycleQuorumBaseBlockIndex) { @@ -97,7 +109,10 @@ static uint256 GetHashModifier(const Consensus::LLMQParams& llmqParams, gsl::not return ::SerializeHash(std::make_pair(llmqParams.type, pCycleQuorumBaseBlockIndex->GetBlockHash())); } -std::vector GetAllQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, gsl::not_null pQuorumBaseBlockIndex, bool reset_cache) +std::vector GetAllQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, + CQuorumSnapshotManager& qsnapman, + gsl::not_null pQuorumBaseBlockIndex, + bool reset_cache) { static RecursiveMutex cs_members; static std::map, StaticSaltedHasher>> mapQuorumMembers GUARDED_BY(cs_members); @@ -156,7 +171,7 @@ std::vector GetAllQuorumMembers(Consensus::LLMQType llmqTy return quorumMembers; } - auto q = ComputeQuorumMembersByQuarterRotation(llmq_params, dmnman, pCycleQuorumBaseBlockIndex); + auto q = ComputeQuorumMembersByQuarterRotation(llmq_params, dmnman, qsnapman, pCycleQuorumBaseBlockIndex); LOCK(cs_indexed_members); for (const size_t i : irange::range(q.size())) { mapIndexedQuorumMembers[llmqType].insert(std::make_pair(pCycleQuorumBaseBlockIndex->GetBlockHash(), i), q[i]); @@ -172,7 +187,8 @@ std::vector GetAllQuorumMembers(Consensus::LLMQType llmqTy return quorumMembers; } -std::vector ComputeQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, const CBlockIndex* pQuorumBaseBlockIndex) +std::vector ComputeQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, + const CBlockIndex* pQuorumBaseBlockIndex) { bool EvoOnly = (Params().GetConsensus().llmqTypePlatform == llmqType) && IsV19Active(pQuorumBaseBlockIndex); const auto& llmq_params_opt = Params().GetLLMQ(llmqType); @@ -190,7 +206,9 @@ std::vector ComputeQuorumMembers(Consensus::LLMQType llmqT return allMns.CalculateQuorum(llmq_params_opt->size, modifier, EvoOnly); } -std::vector> ComputeQuorumMembersByQuarterRotation(const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CBlockIndex* pCycleQuorumBaseBlockIndex) +std::vector> ComputeQuorumMembersByQuarterRotation( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const CBlockIndex* pCycleQuorumBaseBlockIndex) { const Consensus::LLMQType llmqType = llmqParams.type; @@ -207,12 +225,16 @@ std::vector> ComputeQuorumMembersByQuarterRota auto allMns = dmnman.GetListForBlock(pWorkBlockIndex); LogPrint(BCLog::LLMQ, "ComputeQuorumMembersByQuarterRotation llmqType[%d] nHeight[%d] allMns[%d]\n", ToUnderlying(llmqType), pCycleQuorumBaseBlockIndex->nHeight, allMns.GetValidMNsCount()); - PreviousQuorumQuarters previousQuarters = GetPreviousQuorumQuarterMembers(llmqParams, dmnman, pBlockHMinusCIndex, pBlockHMinus2CIndex, pBlockHMinus3CIndex, pCycleQuorumBaseBlockIndex->nHeight); + PreviousQuorumQuarters previousQuarters = GetPreviousQuorumQuarterMembers(llmqParams, dmnman, qsnapman, + pBlockHMinusCIndex, pBlockHMinus2CIndex, + pBlockHMinus3CIndex, + pCycleQuorumBaseBlockIndex->nHeight); size_t nQuorums = static_cast(llmqParams.signingActiveQuorumCount); std::vector> quorumMembers{nQuorums}; - auto newQuarterMembers = BuildNewQuorumQuarterMembers(llmqParams, dmnman, pCycleQuorumBaseBlockIndex, previousQuarters); + auto newQuarterMembers = BuildNewQuorumQuarterMembers(llmqParams, dmnman, qsnapman, pCycleQuorumBaseBlockIndex, + previousQuarters); //TODO Check if it is triggered from outside (P2P, block validation). Throwing an exception is probably a wiser choice //assert (!newQuarterMembers.empty()); @@ -265,28 +287,30 @@ std::vector> ComputeQuorumMembersByQuarterRota } PreviousQuorumQuarters GetPreviousQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams, - CDeterministicMNManager& dmnman, + CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, const CBlockIndex* pBlockHMinusCIndex, const CBlockIndex* pBlockHMinus2CIndex, - const CBlockIndex* pBlockHMinus3CIndex, - int nHeight) + const CBlockIndex* pBlockHMinus3CIndex, int nHeight) { size_t nQuorums = static_cast(llmqParams.signingActiveQuorumCount); PreviousQuorumQuarters quarters{nQuorums}; - std::optional quSnapshotHMinusC = quorumSnapshotManager->GetSnapshotForBlock(llmqParams.type, pBlockHMinusCIndex); + std::optional quSnapshotHMinusC = qsnapman.GetSnapshotForBlock(llmqParams.type, + pBlockHMinusCIndex); if (quSnapshotHMinusC.has_value()) { quarters.quarterHMinusC = GetQuorumQuarterMembersBySnapshot(llmqParams, dmnman, pBlockHMinusCIndex, quSnapshotHMinusC.value(), nHeight); //TODO Check if it is triggered from outside (P2P, block validation). Throwing an exception is probably a wiser choice //assert (!quarterHMinusC.empty()); - std::optional quSnapshotHMinus2C = quorumSnapshotManager->GetSnapshotForBlock(llmqParams.type, pBlockHMinus2CIndex); + std::optional quSnapshotHMinus2C = qsnapman.GetSnapshotForBlock(llmqParams.type, + pBlockHMinus2CIndex); if (quSnapshotHMinus2C.has_value()) { quarters.quarterHMinus2C = GetQuorumQuarterMembersBySnapshot(llmqParams, dmnman, pBlockHMinus2CIndex, quSnapshotHMinus2C.value(), nHeight); //TODO Check if it is triggered from outside (P2P, block validation). Throwing an exception is probably a wiser choice //assert (!quarterHMinusC.empty()); - std::optional quSnapshotHMinus3C = quorumSnapshotManager->GetSnapshotForBlock(llmqParams.type, pBlockHMinus3CIndex); + std::optional quSnapshotHMinus3C = qsnapman.GetSnapshotForBlock(llmqParams.type, + pBlockHMinus3CIndex); if (quSnapshotHMinus3C.has_value()) { quarters.quarterHMinus3C = GetQuorumQuarterMembersBySnapshot(llmqParams, dmnman, pBlockHMinus3CIndex, quSnapshotHMinus3C.value(), nHeight); //TODO Check if it is triggered from outside (P2P, block validation). Throwing an exception is probably a wiser choice @@ -298,10 +322,9 @@ PreviousQuorumQuarters GetPreviousQuorumQuarterMembers(const Consensus::LLMQPara return quarters; } -std::vector> BuildNewQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams, - CDeterministicMNManager& dmnman, - const CBlockIndex* pCycleQuorumBaseBlockIndex, - const PreviousQuorumQuarters& previousQuarters) +std::vector> BuildNewQuorumQuarterMembers( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const CBlockIndex* pCycleQuorumBaseBlockIndex, const PreviousQuorumQuarters& previousQuarters) { if (!llmqParams.useRotation || pCycleQuorumBaseBlockIndex->nHeight % llmqParams.dkgInterval != 0) { ASSERT_IF_DEBUG(false); @@ -454,14 +477,15 @@ std::vector> BuildNewQuorumQuarterMembers(cons BuildQuorumSnapshot(llmqParams, allMns, MnsUsedAtH, sortedCombinedMnsList, quorumSnapshot, pCycleQuorumBaseBlockIndex->nHeight, skipList, pCycleQuorumBaseBlockIndex); - quorumSnapshotManager->StoreSnapshotForBlock(llmqParams.type, pCycleQuorumBaseBlockIndex, quorumSnapshot); + qsnapman.StoreSnapshotForBlock(llmqParams.type, pCycleQuorumBaseBlockIndex, quorumSnapshot); return quarterQuorumMembers; } void BuildQuorumSnapshot(const Consensus::LLMQParams& llmqParams, const CDeterministicMNList& allMns, const CDeterministicMNList& mnUsedAtH, std::vector& sortedCombinedMns, - CQuorumSnapshot& quorumSnapshot, int nHeight, std::vector& skipList, const CBlockIndex* pCycleQuorumBaseBlockIndex) + CQuorumSnapshot& quorumSnapshot, int nHeight, std::vector& skipList, + const CBlockIndex* pCycleQuorumBaseBlockIndex) { if (!llmqParams.useRotation || pCycleQuorumBaseBlockIndex->nHeight % llmqParams.dkgInterval != 0) { ASSERT_IF_DEBUG(false); @@ -494,11 +518,9 @@ void BuildQuorumSnapshot(const Consensus::LLMQParams& llmqParams, const CDetermi } } -std::vector> GetQuorumQuarterMembersBySnapshot(const Consensus::LLMQParams& llmqParams, - CDeterministicMNManager& dmnman, - const CBlockIndex* pCycleQuorumBaseBlockIndex, - const llmq::CQuorumSnapshot& snapshot, - int nHeight) +std::vector> GetQuorumQuarterMembersBySnapshot( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, + const CBlockIndex* pCycleQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight) { if (!llmqParams.useRotation || pCycleQuorumBaseBlockIndex->nHeight % llmqParams.dkgInterval != 0) { ASSERT_IF_DEBUG(false); @@ -654,11 +676,12 @@ uint256 DeterministicOutboundConnection(const uint256& proTxHash1, const uint256 } std::unordered_set GetQuorumConnections( - const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CSporkManager& sporkman, - gsl::not_null pQuorumBaseBlockIndex, const uint256& forMember, bool onlyOutbound) + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const CSporkManager& sporkman, gsl::not_null pQuorumBaseBlockIndex, const uint256& forMember, + bool onlyOutbound) { if (IsAllMembersConnectedEnabled(llmqParams.type, sporkman)) { - auto mns = GetAllQuorumMembers(llmqParams.type, dmnman, pQuorumBaseBlockIndex); + auto mns = GetAllQuorumMembers(llmqParams.type, dmnman, qsnapman, pQuorumBaseBlockIndex); std::unordered_set result; for (const auto& dmn : mns) { @@ -675,15 +698,14 @@ std::unordered_set GetQuorumConnections( } return result; } - return GetQuorumRelayMembers(llmqParams, dmnman, pQuorumBaseBlockIndex, forMember, onlyOutbound); + return GetQuorumRelayMembers(llmqParams, dmnman, qsnapman, pQuorumBaseBlockIndex, forMember, onlyOutbound); } -std::unordered_set GetQuorumRelayMembers(const Consensus::LLMQParams& llmqParams, - CDeterministicMNManager& dmnman, - gsl::not_null pQuorumBaseBlockIndex, - const uint256& forMember, bool onlyOutbound) +std::unordered_set GetQuorumRelayMembers( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + gsl::not_null pQuorumBaseBlockIndex, const uint256& forMember, bool onlyOutbound) { - auto mns = GetAllQuorumMembers(llmqParams.type, dmnman, pQuorumBaseBlockIndex); + auto mns = GetAllQuorumMembers(llmqParams.type, dmnman, qsnapman, pQuorumBaseBlockIndex); std::unordered_set result; auto calcOutbound = [&](size_t i, const uint256& proTxHash) { @@ -756,15 +778,17 @@ std::set CalcDeterministicWatchConnections(Consensus::LLMQType llmqType, return result; } -bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& connman, CDeterministicMNManager& dmnman, const CSporkManager& sporkman, - const CDeterministicMNList& tip_mn_list, gsl::not_null pQuorumBaseBlockIndex, - const uint256& myProTxHash, bool is_masternode) +bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& connman, + CDeterministicMNManager& dmnman, const CSporkManager& sporkman, + CQuorumSnapshotManager& qsnapman, const CDeterministicMNList& tip_mn_list, + gsl::not_null pQuorumBaseBlockIndex, const uint256& myProTxHash, + bool is_masternode) { if (!is_masternode && !IsWatchQuorumsEnabled()) { return false; } - auto members = GetAllQuorumMembers(llmqParams.type, dmnman, pQuorumBaseBlockIndex); + auto members = GetAllQuorumMembers(llmqParams.type, dmnman, qsnapman, pQuorumBaseBlockIndex); if (members.empty()) { return false; } @@ -781,8 +805,9 @@ bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& std::unordered_set connections; std::unordered_set relayMembers; if (isMember) { - connections = GetQuorumConnections(llmqParams, dmnman, sporkman, pQuorumBaseBlockIndex, myProTxHash, true); - relayMembers = GetQuorumRelayMembers(llmqParams, dmnman, pQuorumBaseBlockIndex, myProTxHash, true); + connections = GetQuorumConnections(llmqParams, dmnman, qsnapman, sporkman, pQuorumBaseBlockIndex, myProTxHash, + true); + relayMembers = GetQuorumRelayMembers(llmqParams, dmnman, qsnapman, pQuorumBaseBlockIndex, myProTxHash, true); } else { auto cindexes = CalcDeterministicWatchConnections(llmqParams.type, pQuorumBaseBlockIndex, members.size(), 1); for (auto idx : cindexes) { @@ -813,8 +838,9 @@ bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& } void AddQuorumProbeConnections(const Consensus::LLMQParams& llmqParams, CConnman& connman, CDeterministicMNManager& dmnman, - CMasternodeMetaMan& mn_metaman, const CSporkManager& sporkman, const CDeterministicMNList& tip_mn_list, - gsl::not_null pQuorumBaseBlockIndex, const uint256 &myProTxHash) + CMasternodeMetaMan& mn_metaman, CQuorumSnapshotManager& qsnapman, + const CSporkManager& sporkman, const CDeterministicMNList& tip_mn_list, + gsl::not_null pQuorumBaseBlockIndex, const uint256& myProTxHash) { assert(mn_metaman.IsValid()); @@ -822,7 +848,7 @@ void AddQuorumProbeConnections(const Consensus::LLMQParams& llmqParams, CConnman return; } - auto members = GetAllQuorumMembers(llmqParams.type, dmnman, pQuorumBaseBlockIndex); + auto members = GetAllQuorumMembers(llmqParams.type, dmnman, qsnapman, pQuorumBaseBlockIndex); auto curTime = GetTime().count(); std::set probeConnections; @@ -868,7 +894,5 @@ template void InitQuorumsCache, StaticSaltedHasher, 0ul, 0ul>, std::less, std::allocator, StaticSaltedHasher, 0ul, 0ul>>>>>(std::map, StaticSaltedHasher, 0ul, 0ul>, std::less, std::allocator, StaticSaltedHasher, 0ul, 0ul>>>>&cache, bool limit_by_connections); template void InitQuorumsCache>>(std::map>& cache, bool limit_by_connections); template void InitQuorumsCache>>(std::map>& cache, bool limit_by_connections); - } // namespace utils - } // namespace llmq diff --git a/src/llmq/utils.h b/src/llmq/utils.h index 2795db58dc..01ed90c77d 100644 --- a/src/llmq/utils.h +++ b/src/llmq/utils.h @@ -26,37 +26,39 @@ class CSporkManager; using CDeterministicMNCPtr = std::shared_ptr; -namespace llmq -{ - -namespace utils -{ +namespace llmq { +class CQuorumSnapshotManager; +namespace utils { // includes members which failed DKG -std::vector GetAllQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, gsl::not_null pQuorumBaseBlockIndex, bool reset_cache = false); +std::vector GetAllQuorumMembers(Consensus::LLMQType llmqType, CDeterministicMNManager& dmnman, + CQuorumSnapshotManager& qsnapman, + gsl::not_null pQuorumBaseBlockIndex, + bool reset_cache = false); uint256 DeterministicOutboundConnection(const uint256& proTxHash1, const uint256& proTxHash2); std::unordered_set GetQuorumConnections( - const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, const CSporkManager& sporkman, + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, + const CSporkManager& sporkman, gsl::not_null pQuorumBaseBlockIndex, const uint256& forMember, + bool onlyOutbound); +std::unordered_set GetQuorumRelayMembers( + const Consensus::LLMQParams& llmqParams, CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, gsl::not_null pQuorumBaseBlockIndex, const uint256& forMember, bool onlyOutbound); -std::unordered_set GetQuorumRelayMembers(const Consensus::LLMQParams& llmqParams, - CDeterministicMNManager& dmnman, - gsl::not_null pQuorumBaseBlockIndex, - const uint256& forMember, bool onlyOutbound); std::set CalcDeterministicWatchConnections(Consensus::LLMQType llmqType, gsl::not_null pQuorumBaseBlockIndex, size_t memberCount, size_t connectionCount); -bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& connman, CDeterministicMNManager& dmnman, const CSporkManager& sporkman, - const CDeterministicMNList& tip_mn_list, gsl::not_null pQuorumBaseBlockIndex, - const uint256& myProTxHash, bool is_masternode); +bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& connman, + CDeterministicMNManager& dmnman, const CSporkManager& sporkman, + CQuorumSnapshotManager& qsnapman, const CDeterministicMNList& tip_mn_list, + gsl::not_null pQuorumBaseBlockIndex, const uint256& myProTxHash, + bool is_masternode); void AddQuorumProbeConnections(const Consensus::LLMQParams& llmqParams, CConnman& connman, CDeterministicMNManager& dmnman, - CMasternodeMetaMan& mn_metaman, const CSporkManager& sporkman, const CDeterministicMNList& tip_mn_list, + CMasternodeMetaMan& mn_metaman, CQuorumSnapshotManager& qsnapman, + const CSporkManager& sporkman, const CDeterministicMNList& tip_mn_list, gsl::not_null pQuorumBaseBlockIndex, const uint256& myProTxHash); template void InitQuorumsCache(CacheType& cache, bool limit_by_connections = true); - } // namespace utils - } // namespace llmq #endif // BITCOIN_LLMQ_UTILS_H diff --git a/src/masternode/node.cpp b/src/masternode/node.cpp index 0a0b51deef..ecf1d8f75a 100644 --- a/src/masternode/node.cpp +++ b/src/masternode/node.cpp @@ -174,7 +174,6 @@ void CActiveMasternodeManager::InitInternal(const CBlockIndex* pindex) m_info.proTxHash = dmn->proTxHash; m_info.outpoint = dmn->collateralOutpoint; - m_info.legacy = dmn->pdmnState->nVersion == CProRegTx::LEGACY_BLS_VERSION; m_state = MasternodeState::READY; } @@ -276,12 +275,6 @@ template bool CActiveMasternodeManager::Decrypt(const CBLSIESEncryptedObject& obj, size_t idx, CBLSSecretKey& ret_obj, int version) const; -[[nodiscard]] CBLSSignature CActiveMasternodeManager::Sign(const uint256& hash) const -{ - AssertLockNotHeld(cs); - return WITH_READ_LOCK(cs, return m_info.blsKeyOperator.Sign(hash)); -} - [[nodiscard]] CBLSSignature CActiveMasternodeManager::Sign(const uint256& hash, const bool is_legacy) const { AssertLockNotHeld(cs); diff --git a/src/masternode/node.h b/src/masternode/node.h index 713161ee06..f1a54ed2cc 100644 --- a/src/masternode/node.h +++ b/src/masternode/node.h @@ -22,7 +22,6 @@ struct CActiveMasternodeInfo { uint256 proTxHash; COutPoint outpoint; CService service; - bool legacy{true}; CActiveMasternodeInfo(const CBLSSecretKey& blsKeyOperator, const CBLSPublicKey& blsPubKeyOperator) : blsKeyOperator(blsKeyOperator), blsPubKeyOperator(blsPubKeyOperator) {}; @@ -66,7 +65,6 @@ class CActiveMasternodeManager final : public CValidationInterface template