Merge bitcoin/bitcoin#31130: Drop miniupnp dependency

40e5f26a3f mapport: remove dead code in DispatchMapPort (Antoine Poinsot)
38fdf7c1fb mapport: drop outdated comments (Antoine Poinsot)
b7b2435290 doc: add release note for #31130 (Antoine Poinsot)
1b6dec98da depends: drop miniupnpc (Antoine Poinsot)
953533d021 doc: remove mentions of UPnP (Antoine Poinsot)
94ad614482 ci: remove UPnP options (Antoine Poinsot)
a9598e5eaa build: drop miniupnpc dependency (Antoine Poinsot)
a5fcfb7385 interfaces: remove now unused 'use_upnp' arg from 'mapPort' (Antoine Poinsot)
038bbe7b20 daemon: remove UPnP support (Antoine Poinsot)
844770b05e qt: remove UPnP settings (Antoine Poinsot)

Pull request description:

  This PR removes UPnP IGD support and drops our [miniupnp](https://github.com/miniupnp/miniupnp) dependency.

  Miniupnpc is a C library (somewhat) maintained by a single person which had several vulnerabilities in the past (a couple dozens are listed [here](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=miniupnp)), some of which directly affected our software ([RCE in 2015](https://bitcoincore.org/en/2024/07/03/disclose_upnp_rce/), [OOM in 2020](https://bitcoincore.org/en/2024/07/31/disclose-upnp-oom/)).

  The main purpose of this functionality is to have more (non-data-center) reachable nodes on the network. For a non-technical user running Bitcoin Core at home, the software would automatically open a port on their router to receive incoming connections. This way, users not able to manually open a port on their router would still provide the network with more resources and enhance its diversity.

  However, due to past vulnerabilities (and a worry about unknown future ones) in miniupnpc this feature was disabled by default in https://github.com/bitcoin/bitcoin/pull/6795. Having it disabled by default kills (most of?) the purpose of having this functionality in the first place: someone technical enough to understand the `-upnp` startup option or the "enable UPnP" setting is most likely able to open a port on his box in the first place.

  In addition, laanwj implemented PCP with a NAT-PMP fallback directly in Bitcoin Core in https://github.com/bitcoin/bitcoin/pull/30043. If we ever want to re-enable automatic NAT traversal by default in Bitcoin Core, this is the best option (and in my opinion the only sane one). The NAT-PMP fallback makes it so compatibility shouldn't be (much of) an issue.

  On balance, i believe that keeping this functionality and this barely maintained C dependency has higher costs than benefits. Therefore i propose that we get rid of it.

ACKs for top commit:
  jarolrod:
    ACK 40e5f26a3f
  1440000bytes:
    Code Review ACK 40e5f26a3f
  laanwj:
    Code review ACK 40e5f26a3f
  i-am-yuvi:
    Tested ACK 40e5f26a3f

Tree-SHA512: 9ea48662775510f5ec6de7af65790f7c8d211603398e9d8c634a86387be81b28081419a95b4d6680d3d7fe6a9f16cec99f16516548201dc7e49781909899a657
pull/31171/head
merge-script 1 week ago
commit 6e21dedbf2
No known key found for this signature in database
GPG Key ID: 2EEB9F5CC09526C1

@ -67,12 +67,12 @@ jobs:
echo "TEST_BASE=$(git rev-list -n$((${{ env.MAX_COUNT }} + 1)) --reverse HEAD $EXCLUDE_MERGE_BASE_ANCESTORS | head -1)" >> "$GITHUB_ENV" echo "TEST_BASE=$(git rev-list -n$((${{ env.MAX_COUNT }} + 1)) --reverse HEAD $EXCLUDE_MERGE_BASE_ANCESTORS | head -1)" >> "$GITHUB_ENV"
- run: | - run: |
sudo apt-get update sudo apt-get update
sudo apt-get install clang ccache build-essential cmake pkg-config python3-zmq libevent-dev libboost-dev libsqlite3-dev libdb++-dev systemtap-sdt-dev libminiupnpc-dev libzmq3-dev qtbase5-dev qttools5-dev qttools5-dev-tools qtwayland5 libqrencode-dev -y sudo apt-get install clang ccache build-essential cmake pkg-config python3-zmq libevent-dev libboost-dev libsqlite3-dev libdb++-dev systemtap-sdt-dev libzmq3-dev qtbase5-dev qttools5-dev qttools5-dev-tools qtwayland5 libqrencode-dev -y
- name: Compile and run tests - name: Compile and run tests
run: | run: |
# Run tests on commits after the last merge commit and before the PR head commit # Run tests on commits after the last merge commit and before the PR head commit
# Use clang++, because it is a bit faster and uses less memory than g++ # Use clang++, because it is a bit faster and uses less memory than g++
git rebase --exec "echo Running test-one-commit on \$( git log -1 ) && CC=clang CXX=clang++ cmake -B build -DWERROR=ON -DWITH_ZMQ=ON -DBUILD_GUI=ON -DBUILD_BENCH=ON -DBUILD_FUZZ_BINARY=ON -DWITH_BDB=ON -DWITH_MINIUPNPC=ON -DWITH_USDT=ON && cmake --build build -j $(nproc) && ctest --output-on-failure --test-dir build -j $(nproc) && ./build/test/functional/test_runner.py -j $(( $(nproc) * 2 ))" ${{ env.TEST_BASE }} git rebase --exec "echo Running test-one-commit on \$( git log -1 ) && CC=clang CXX=clang++ cmake -B build -DWERROR=ON -DWITH_ZMQ=ON -DBUILD_GUI=ON -DBUILD_BENCH=ON -DBUILD_FUZZ_BINARY=ON -DWITH_BDB=ON -DWITH_USDT=ON && cmake --build build -j $(nproc) && ctest --output-on-failure --test-dir build -j $(nproc) && ./build/test/functional/test_runner.py -j $(( $(nproc) * 2 ))" ${{ env.TEST_BASE }}
macos-native-arm64: macos-native-arm64:
name: 'macOS 14 native, arm64, no depends, sqlite only, gui' name: 'macOS 14 native, arm64, no depends, sqlite only, gui'
@ -105,7 +105,7 @@ jobs:
run: | run: |
# A workaround for "The `brew link` step did not complete successfully" error. # A workaround for "The `brew link` step did not complete successfully" error.
brew install --quiet python@3 || brew link --overwrite python@3 brew install --quiet python@3 || brew link --overwrite python@3
brew install --quiet coreutils ninja pkg-config gnu-getopt ccache boost libevent miniupnpc zeromq qt@5 qrencode brew install --quiet coreutils ninja pkg-config gnu-getopt ccache boost libevent zeromq qt@5 qrencode
- name: Set Ccache directory - name: Set Ccache directory
run: echo "CCACHE_DIR=${RUNNER_TEMP}/ccache_dir" >> "$GITHUB_ENV" run: echo "CCACHE_DIR=${RUNNER_TEMP}/ccache_dir" >> "$GITHUB_ENV"
@ -182,7 +182,7 @@ jobs:
- name: Generate build system - name: Generate build system
run: | run: |
cmake -B build --preset vs2022-static -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT\scripts\buildsystems\vcpkg.cmake" -DBUILD_GUI=ON -DWITH_BDB=ON -DWITH_MINIUPNPC=ON -DWITH_ZMQ=ON -DBUILD_BENCH=ON -DBUILD_FUZZ_BINARY=ON -DWERROR=ON cmake -B build --preset vs2022-static -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT\scripts\buildsystems\vcpkg.cmake" -DBUILD_GUI=ON -DWITH_BDB=ON -DWITH_ZMQ=ON -DBUILD_BENCH=ON -DBUILD_FUZZ_BINARY=ON -DWERROR=ON
- name: Save vcpkg binary cache - name: Save vcpkg binary cache
uses: actions/cache/save@v4 uses: actions/cache/save@v4

@ -121,11 +121,6 @@ option(REDUCE_EXPORTS "Attempt to reduce exported symbols in the resulting execu
option(WERROR "Treat compiler warnings as errors." OFF) option(WERROR "Treat compiler warnings as errors." OFF)
option(WITH_CCACHE "Attempt to use ccache for compiling." ON) option(WITH_CCACHE "Attempt to use ccache for compiling." ON)
option(WITH_MINIUPNPC "Enable UPnP." OFF)
if(WITH_MINIUPNPC)
find_package(MiniUPnPc MODULE REQUIRED)
endif()
option(WITH_ZMQ "Enable ZMQ notifications." OFF) option(WITH_ZMQ "Enable ZMQ notifications." OFF)
if(WITH_ZMQ) if(WITH_ZMQ)
if(VCPKG_TARGET_TRIPLET) if(VCPKG_TARGET_TRIPLET)
@ -234,7 +229,6 @@ if(BUILD_FOR_FUZZING)
set(BUILD_WALLET_TOOL OFF) set(BUILD_WALLET_TOOL OFF)
set(BUILD_GUI OFF) set(BUILD_GUI OFF)
set(ENABLE_EXTERNAL_SIGNER OFF) set(ENABLE_EXTERNAL_SIGNER OFF)
set(WITH_MINIUPNPC OFF)
set(WITH_ZMQ OFF) set(WITH_ZMQ OFF)
set(BUILD_TESTS OFF) set(BUILD_TESTS OFF)
set(BUILD_GUI_TESTS OFF) set(BUILD_GUI_TESTS OFF)
@ -612,7 +606,6 @@ if(ENABLE_WALLET)
message(" - legacy wallets (Berkeley DB) ..... ${WITH_BDB}") message(" - legacy wallets (Berkeley DB) ..... ${WITH_BDB}")
endif() endif()
message(" external signer ..................... ${ENABLE_EXTERNAL_SIGNER}") message(" external signer ..................... ${ENABLE_EXTERNAL_SIGNER}")
message(" port mapping using UPnP ............. ${WITH_MINIUPNPC}")
message(" ZeroMQ .............................. ${WITH_ZMQ}") message(" ZeroMQ .............................. ${WITH_ZMQ}")
message(" USDT tracing ........................ ${WITH_USDT}") message(" USDT tracing ........................ ${WITH_USDT}")
message(" QR code (GUI) ....................... ${WITH_QRENCODE}") message(" QR code (GUI) ....................... ${WITH_QRENCODE}")

@ -84,7 +84,6 @@
"ENABLE_WALLET": "ON", "ENABLE_WALLET": "ON",
"WARN_INCOMPATIBLE_BDB": "OFF", "WARN_INCOMPATIBLE_BDB": "OFF",
"WITH_BDB": "ON", "WITH_BDB": "ON",
"WITH_MINIUPNPC": "ON",
"WITH_MULTIPROCESS": "ON", "WITH_MULTIPROCESS": "ON",
"WITH_QRENCODE": "ON", "WITH_QRENCODE": "ON",
"WITH_SQLITE": "ON", "WITH_SQLITE": "ON",

@ -11,7 +11,7 @@ export LC_ALL=C.UTF-8
export PIP_PACKAGES="--break-system-packages zmq" export PIP_PACKAGES="--break-system-packages zmq"
export GOAL="install" export GOAL="install"
export CMAKE_GENERATOR="Ninja" export CMAKE_GENERATOR="Ninja"
export BITCOIN_CONFIG="-DBUILD_GUI=ON -DWITH_ZMQ=ON -DWITH_MINIUPNPC=ON -DREDUCE_EXPORTS=ON" export BITCOIN_CONFIG="-DBUILD_GUI=ON -DWITH_ZMQ=ON -DREDUCE_EXPORTS=ON"
export CI_OS_NAME="macos" export CI_OS_NAME="macos"
export NO_DEPENDS=1 export NO_DEPENDS=1
export OSX_SDK="" export OSX_SDK=""

@ -19,7 +19,7 @@ else
fi fi
export CONTAINER_NAME=ci_native_asan export CONTAINER_NAME=ci_native_asan
export PACKAGES="systemtap-sdt-dev clang-18 llvm-18 libclang-rt-18-dev python3-zmq qtbase5-dev qttools5-dev qttools5-dev-tools libevent-dev libboost-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev libsqlite3-dev ${BPFCC_PACKAGE}" export PACKAGES="systemtap-sdt-dev clang-18 llvm-18 libclang-rt-18-dev python3-zmq qtbase5-dev qttools5-dev qttools5-dev-tools libevent-dev libboost-dev libdb5.3++-dev libzmq3-dev libqrencode-dev libsqlite3-dev ${BPFCC_PACKAGE}"
export NO_DEPENDS=1 export NO_DEPENDS=1
export GOAL="install" export GOAL="install"
export BITCOIN_CONFIG="\ export BITCOIN_CONFIG="\

@ -10,7 +10,7 @@ export CONTAINER_NAME=ci_native_previous_releases
export CI_IMAGE_NAME_TAG="docker.io/ubuntu:22.04" export CI_IMAGE_NAME_TAG="docker.io/ubuntu:22.04"
# Use minimum supported python3.10 and gcc-11, see doc/dependencies.md # Use minimum supported python3.10 and gcc-11, see doc/dependencies.md
export PACKAGES="gcc-11 g++-11 python3-zmq" export PACKAGES="gcc-11 g++-11 python3-zmq"
export DEP_OPTS="NO_UPNP=1 DEBUG=1 CC=gcc-11 CXX=g++-11" export DEP_OPTS="DEBUG=1 CC=gcc-11 CXX=g++-11"
export TEST_RUNNER_EXTRA="--previous-releases --coverage --extended --exclude feature_dbcrash" # Run extended tests so that coverage does not fail, but exclude the very slow dbcrash export TEST_RUNNER_EXTRA="--previous-releases --coverage --extended --exclude feature_dbcrash" # Run extended tests so that coverage does not fail, but exclude the very slow dbcrash
export RUN_UNIT_TESTS_SEQUENTIAL="true" export RUN_UNIT_TESTS_SEQUENTIAL="true"
export RUN_UNIT_TESTS="false" export RUN_UNIT_TESTS="false"

@ -9,7 +9,7 @@ export LC_ALL=C.UTF-8
export CI_IMAGE_NAME_TAG="docker.io/ubuntu:24.04" export CI_IMAGE_NAME_TAG="docker.io/ubuntu:24.04"
export CONTAINER_NAME=ci_native_tidy export CONTAINER_NAME=ci_native_tidy
export TIDY_LLVM_V="18" export TIDY_LLVM_V="18"
export PACKAGES="clang-${TIDY_LLVM_V} libclang-${TIDY_LLVM_V}-dev llvm-${TIDY_LLVM_V}-dev libomp-${TIDY_LLVM_V}-dev clang-tidy-${TIDY_LLVM_V} jq libevent-dev libboost-dev libminiupnpc-dev libzmq3-dev systemtap-sdt-dev qtbase5-dev qttools5-dev qttools5-dev-tools libqrencode-dev libsqlite3-dev libdb++-dev" export PACKAGES="clang-${TIDY_LLVM_V} libclang-${TIDY_LLVM_V}-dev llvm-${TIDY_LLVM_V}-dev libomp-${TIDY_LLVM_V}-dev clang-tidy-${TIDY_LLVM_V} jq libevent-dev libboost-dev libzmq3-dev systemtap-sdt-dev qtbase5-dev qttools5-dev qttools5-dev-tools libqrencode-dev libsqlite3-dev libdb++-dev"
export NO_DEPENDS=1 export NO_DEPENDS=1
export RUN_UNIT_TESTS=false export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false export RUN_FUNCTIONAL_TESTS=false
@ -18,7 +18,7 @@ export RUN_CHECK_DEPS=true
export RUN_TIDY=true export RUN_TIDY=true
export GOAL="install" export GOAL="install"
export BITCOIN_CONFIG="\ export BITCOIN_CONFIG="\
-DWITH_ZMQ=ON -DBUILD_GUI=ON -DBUILD_BENCH=ON -DWITH_MINIUPNPC=ON -DWITH_USDT=ON -DWITH_BDB=ON -DWARN_INCOMPATIBLE_BDB=OFF \ -DWITH_ZMQ=ON -DBUILD_GUI=ON -DBUILD_BENCH=ON -DWITH_USDT=ON -DWITH_BDB=ON -DWARN_INCOMPATIBLE_BDB=OFF \
-DENABLE_HARDENING=OFF \ -DENABLE_HARDENING=OFF \
-DCMAKE_C_COMPILER=clang-${TIDY_LLVM_V} \ -DCMAKE_C_COMPILER=clang-${TIDY_LLVM_V} \
-DCMAKE_CXX_COMPILER=clang++-${TIDY_LLVM_V} \ -DCMAKE_CXX_COMPILER=clang++-${TIDY_LLVM_V} \

@ -8,14 +8,14 @@ export LC_ALL=C.UTF-8
export CI_IMAGE_NAME_TAG="docker.io/ubuntu:24.04" export CI_IMAGE_NAME_TAG="docker.io/ubuntu:24.04"
export CONTAINER_NAME=ci_native_valgrind export CONTAINER_NAME=ci_native_valgrind
export PACKAGES="valgrind clang-16 llvm-16 libclang-rt-16-dev python3-zmq libevent-dev libboost-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libsqlite3-dev" export PACKAGES="valgrind clang-16 llvm-16 libclang-rt-16-dev python3-zmq libevent-dev libboost-dev libdb5.3++-dev libzmq3-dev libsqlite3-dev"
export USE_VALGRIND=1 export USE_VALGRIND=1
export NO_DEPENDS=1 export NO_DEPENDS=1
export TEST_RUNNER_EXTRA="--exclude feature_init,rpc_bind,feature_bind_extra" # feature_init excluded for now, see https://github.com/bitcoin/bitcoin/issues/30011 ; bind tests excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547 export TEST_RUNNER_EXTRA="--exclude feature_init,rpc_bind,feature_bind_extra" # feature_init excluded for now, see https://github.com/bitcoin/bitcoin/issues/30011 ; bind tests excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547
export GOAL="install" export GOAL="install"
# TODO enable GUI # TODO enable GUI
export BITCOIN_CONFIG="\ export BITCOIN_CONFIG="\
-DWITH_ZMQ=ON -DWITH_BDB=ON -DWITH_MINIUPNPC=ON -DWARN_INCOMPATIBLE_BDB=OFF -DBUILD_GUI=OFF \ -DWITH_ZMQ=ON -DWITH_BDB=ON -DWARN_INCOMPATIBLE_BDB=OFF -DBUILD_GUI=OFF \
-DCMAKE_C_COMPILER=clang-16 \ -DCMAKE_C_COMPILER=clang-16 \
-DCMAKE_CXX_COMPILER=clang++-16 \ -DCMAKE_CXX_COMPILER=clang++-16 \
" "

@ -1,84 +0,0 @@
# Copyright (c) 2023-present The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://opensource.org/license/mit/.
if(NOT MSVC)
find_package(PkgConfig REQUIRED)
pkg_check_modules(PC_MiniUPnPc QUIET miniupnpc)
endif()
find_path(MiniUPnPc_INCLUDE_DIR
NAMES miniupnpc/miniupnpc.h
PATHS ${PC_MiniUPnPc_INCLUDE_DIRS}
)
if(MiniUPnPc_INCLUDE_DIR)
file(
STRINGS "${MiniUPnPc_INCLUDE_DIR}/miniupnpc/miniupnpc.h" version_strings
REGEX "^#define[\t ]+MINIUPNPC_API_VERSION[\t ]+[0-9]+"
)
string(REGEX REPLACE "^#define[\t ]+MINIUPNPC_API_VERSION[\t ]+([0-9]+)" "\\1" MiniUPnPc_API_VERSION "${version_strings}")
# The minimum supported miniUPnPc API version is set to 17. This excludes
# versions with known vulnerabilities.
if(MiniUPnPc_API_VERSION GREATER_EQUAL 17)
set(MiniUPnPc_API_VERSION_OK TRUE)
endif()
endif()
if(MSVC)
cmake_path(GET MiniUPnPc_INCLUDE_DIR PARENT_PATH MiniUPnPc_IMPORTED_PATH)
find_library(MiniUPnPc_LIBRARY_DEBUG
NAMES miniupnpc PATHS ${MiniUPnPc_IMPORTED_PATH}/debug/lib
NO_DEFAULT_PATH
)
find_library(MiniUPnPc_LIBRARY_RELEASE
NAMES miniupnpc PATHS ${MiniUPnPc_IMPORTED_PATH}/lib
NO_DEFAULT_PATH
)
set(MiniUPnPc_required MiniUPnPc_IMPORTED_PATH)
else()
find_library(MiniUPnPc_LIBRARY
NAMES miniupnpc
PATHS ${PC_MiniUPnPc_LIBRARY_DIRS}
)
set(MiniUPnPc_required MiniUPnPc_LIBRARY)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MiniUPnPc
REQUIRED_VARS ${MiniUPnPc_required} MiniUPnPc_INCLUDE_DIR MiniUPnPc_API_VERSION_OK
)
if(MiniUPnPc_FOUND AND NOT TARGET MiniUPnPc::MiniUPnPc)
add_library(MiniUPnPc::MiniUPnPc UNKNOWN IMPORTED)
set_target_properties(MiniUPnPc::MiniUPnPc PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${MiniUPnPc_INCLUDE_DIR}"
)
if(MSVC)
if(MiniUPnPc_LIBRARY_DEBUG)
set_property(TARGET MiniUPnPc::MiniUPnPc APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(MiniUPnPc::MiniUPnPc PROPERTIES
IMPORTED_LOCATION_DEBUG "${MiniUPnPc_LIBRARY_DEBUG}"
)
endif()
if(MiniUPnPc_LIBRARY_RELEASE)
set_property(TARGET MiniUPnPc::MiniUPnPc APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(MiniUPnPc::MiniUPnPc PROPERTIES
IMPORTED_LOCATION_RELEASE "${MiniUPnPc_LIBRARY_RELEASE}"
)
endif()
else()
set_target_properties(MiniUPnPc::MiniUPnPc PROPERTIES
IMPORTED_LOCATION "${MiniUPnPc_LIBRARY}"
)
endif()
set_property(TARGET MiniUPnPc::MiniUPnPc PROPERTY
INTERFACE_COMPILE_DEFINITIONS USE_UPNP=1 $<$<PLATFORM_ID:Windows>:MINIUPNP_STATICLIB>
)
endif()
mark_as_advanced(
MiniUPnPc_INCLUDE_DIR
MiniUPnPc_LIBRARY
)

@ -40,7 +40,6 @@ NO_BDB ?=
NO_SQLITE ?= NO_SQLITE ?=
NO_WALLET ?= NO_WALLET ?=
NO_ZMQ ?= NO_ZMQ ?=
NO_UPNP ?=
NO_USDT ?= NO_USDT ?=
MULTIPROCESS ?= MULTIPROCESS ?=
LTO ?= LTO ?=
@ -157,13 +156,11 @@ bdb_packages_$(NO_BDB) = $(bdb_packages)
sqlite_packages_$(NO_SQLITE) = $(sqlite_packages) sqlite_packages_$(NO_SQLITE) = $(sqlite_packages)
wallet_packages_$(NO_WALLET) = $(bdb_packages_) $(sqlite_packages_) wallet_packages_$(NO_WALLET) = $(bdb_packages_) $(sqlite_packages_)
upnp_packages_$(NO_UPNP) = $(upnp_packages)
zmq_packages_$(NO_ZMQ) = $(zmq_packages) zmq_packages_$(NO_ZMQ) = $(zmq_packages)
multiprocess_packages_$(MULTIPROCESS) = $(multiprocess_packages) multiprocess_packages_$(MULTIPROCESS) = $(multiprocess_packages)
usdt_packages_$(NO_USDT) = $(usdt_$(host_os)_packages) usdt_packages_$(NO_USDT) = $(usdt_$(host_os)_packages)
packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(boost_packages_) $(libevent_packages_) $(qt_packages_) $(wallet_packages_) $(upnp_packages_) $(usdt_packages_) packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(boost_packages_) $(libevent_packages_) $(qt_packages_) $(wallet_packages_) $(usdt_packages_)
native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages) native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages)
ifneq ($(zmq_packages_),) ifneq ($(zmq_packages_),)
@ -231,7 +228,6 @@ $(host_prefix)/toolchain.cmake : toolchain.cmake.in $(host_prefix)/.stamp_$(fina
-e 's|@wallet_packages@|$(wallet_packages_)|' \ -e 's|@wallet_packages@|$(wallet_packages_)|' \
-e 's|@bdb_packages@|$(bdb_packages_)|' \ -e 's|@bdb_packages@|$(bdb_packages_)|' \
-e 's|@sqlite_packages@|$(sqlite_packages_)|' \ -e 's|@sqlite_packages@|$(sqlite_packages_)|' \
-e 's|@upnp_packages@|$(upnp_packages_)|' \
-e 's|@usdt_packages@|$(usdt_packages_)|' \ -e 's|@usdt_packages@|$(usdt_packages_)|' \
-e 's|@no_harden@|$(NO_HARDEN)|' \ -e 's|@no_harden@|$(NO_HARDEN)|' \
-e 's|@multiprocess@|$(MULTIPROCESS)|' \ -e 's|@multiprocess@|$(MULTIPROCESS)|' \

@ -112,7 +112,6 @@ The following can be set when running make: `make FOO=bar`
- `NO_WALLET`: Don't download/build/cache libs needed to enable the wallet - `NO_WALLET`: Don't download/build/cache libs needed to enable the wallet
- `NO_BDB`: Don't download/build/cache BerkeleyDB - `NO_BDB`: Don't download/build/cache BerkeleyDB
- `NO_SQLITE`: Don't download/build/cache SQLite - `NO_SQLITE`: Don't download/build/cache SQLite
- `NO_UPNP`: Don't download/build/cache packages needed for enabling UPnP
- `NO_USDT`: Don't download/build/cache packages needed for enabling USDT tracepoints - `NO_USDT`: Don't download/build/cache packages needed for enabling USDT tracepoints
- `MULTIPROCESS`: Build libmultiprocess (experimental) - `MULTIPROCESS`: Build libmultiprocess (experimental)
- `DEBUG`: Disable some optimizations and enable more runtime checking - `DEBUG`: Disable some optimizations and enable more runtime checking

@ -1,36 +0,0 @@
package=miniupnpc
$(package)_version=2.2.7
$(package)_download_path=https://miniupnp.tuxfamily.org/files/
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=b0c3a27056840fd0ec9328a5a9bac3dc5e0ec6d2e8733349cf577b0aa1e70ac1
$(package)_patches=dont_leak_info.patch cmake_get_src_addr.patch fix_windows_snprintf.patch
$(package)_build_subdir=build
define $(package)_set_vars
$(package)_config_opts = -DUPNPC_BUILD_SAMPLE=OFF -DUPNPC_BUILD_SHARED=OFF
$(package)_config_opts += -DUPNPC_BUILD_STATIC=ON -DUPNPC_BUILD_TESTS=OFF
$(package)_config_opts_mingw32 += -DMINIUPNPC_TARGET_WINDOWS_VERSION=0x0601
endef
define $(package)_preprocess_cmds
patch -p1 < $($(package)_patch_dir)/dont_leak_info.patch && \
patch -p1 < $($(package)_patch_dir)/cmake_get_src_addr.patch && \
patch -p1 < $($(package)_patch_dir)/fix_windows_snprintf.patch
endef
define $(package)_config_cmds
$($(package)_cmake) -S .. -B .
endef
define $(package)_build_cmds
$(MAKE)
endef
define $(package)_stage_cmds
cmake --install . --prefix $($(package)_staging_prefix_dir)
endef
define $(package)_postprocess_cmds
rm -rf bin && \
rm -rf share
endef

@ -17,8 +17,6 @@ sqlite_packages=sqlite
zmq_packages=zeromq zmq_packages=zeromq
upnp_packages=miniupnpc
multiprocess_packages = libmultiprocess capnp multiprocess_packages = libmultiprocess capnp
multiprocess_native_packages = native_libmultiprocess native_capnp multiprocess_native_packages = native_libmultiprocess native_capnp

@ -1,22 +0,0 @@
commit cb2026239c2a3aff393952ccb0ee1c448189402d
Author: fanquake <fanquake@gmail.com>
Date: Fri Mar 22 14:03:54 2024 +0000
build: add MINIUPNPC_GET_SRC_ADDR to CMake build
This mirrors the autotools build.
See https://github.com/miniupnp/miniupnp/pull/721.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1aa95a8..0cacf3e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -31,6 +31,7 @@ endif ()
if (NOT WIN32)
target_compile_definitions(miniupnpc-private INTERFACE
MINIUPNPC_SET_SOCKET_TIMEOUT
+ MINIUPNPC_GET_SRC_ADDR
_BSD_SOURCE _DEFAULT_SOURCE)
if (NOT APPLE AND NOT CMAKE_SYSTEM_NAME MATCHES ".*BSD" AND NOT CMAKE_SYSTEM_NAME STREQUAL "SunOS")
# add_definitions (-D_POSIX_C_SOURCE=200112L)

@ -1,32 +0,0 @@
commit 51f6dd991c29af66fb4f64c6feb2787cce23a1a7
Author: fanquake <fanquake@gmail.com>
Date: Mon Jan 8 11:21:40 2024 +0000
Don't leak OS and miniupnpc version info in User-Agent
diff --git a/src/minisoap.c b/src/minisoap.c
index 903ac5f..046e0ea 100644
--- a/src/minisoap.c
+++ b/src/minisoap.c
@@ -90,7 +90,7 @@ int soapPostSubmit(SOCKET fd,
headerssize = snprintf(headerbuf, sizeof(headerbuf),
"POST %s HTTP/%s\r\n"
"Host: %s%s\r\n"
- "User-Agent: " OS_STRING " " UPNP_VERSION_STRING " MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
+ "User-Agent: " UPNP_VERSION_STRING "\r\n"
"Content-Length: %d\r\n"
#if (UPNP_VERSION_MAJOR == 1) && (UPNP_VERSION_MINOR == 0)
"Content-Type: text/xml\r\n"
diff --git a/src/miniwget.c b/src/miniwget.c
index e76a5e5..0cc36fe 100644
--- a/src/miniwget.c
+++ b/src/miniwget.c
@@ -444,7 +444,7 @@ miniwget3(const char * host,
"GET %s HTTP/%s\r\n"
"Host: %s:%d\r\n"
"Connection: Close\r\n"
- "User-Agent: " OS_STRING " " UPNP_VERSION_STRING " MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
+ "User-Agent: " UPNP_VERSION_STRING "\r\n"
"\r\n",
path, httpversion, host, port);

@ -1,25 +0,0 @@
commit a1e9de80ab99b4c956a6a4e21d3e0de6f7a1014d
Author: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com>
Date: Sat Apr 20 15:14:47 2024 +0100
Fix macro expression that guards `snprintf` for Windows
Otherwise, the `snprintf` is still wrongly emulated for the following
cases:
- mingw-w64 6.0.0 or new with ucrt
- mingw-w64 8.0.0 or new with iso c ext
--- a/src/win32_snprintf.h
+++ b/src/win32_snprintf.h
@@ -23,9 +23,9 @@
(defined(_MSC_VER) && _MSC_VER < 1900) /* Visual Studio older than 2015 */ || \
(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) && defined(__NO_ISOCEXT)) /* mingw32 without iso c ext */ || \
(defined(__MINGW64_VERSION_MAJOR) && /* mingw-w64 not ... */ !( \
- (defined (__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO != 0)) /* ... with ansi stdio */ || \
+ (defined (__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO != 0) /* ... with ansi stdio */ || \
(__MINGW64_VERSION_MAJOR >= 6 && defined(_UCRT)) /* ... at least 6.0.0 with ucrt */ || \
- (__MINGW64_VERSION_MAJOR >= 8 && !defined(__NO_ISOCEXT)) /* ... at least 8.0.0 with iso c ext */ || \
+ (__MINGW64_VERSION_MAJOR >= 8 && !defined(__NO_ISOCEXT))) /* ... at least 8.0.0 with iso c ext */ || \
0) || \
0)

@ -139,13 +139,6 @@ else()
set(WITH_SQLITE ON CACHE BOOL "") set(WITH_SQLITE ON CACHE BOOL "")
endif() endif()
set(upnp_packages @upnp_packages@)
if("${upnp_packages}" STREQUAL "")
set(WITH_MINIUPNPC OFF CACHE BOOL "")
else()
set(WITH_MINIUPNPC ON CACHE BOOL "")
endif()
set(usdt_packages @usdt_packages@) set(usdt_packages @usdt_packages@)
if("${usdt_packages}" STREQUAL "") if("${usdt_packages}" STREQUAL "")
set(WITH_USDT OFF CACHE BOOL "") set(WITH_USDT OFF CACHE BOOL "")

@ -42,7 +42,7 @@ from ports. However, you can build DB 4.8 yourself [using depends](/depends).
```bash ```bash
pkg install gmake pkg install gmake
gmake -C depends NO_BOOST=1 NO_LIBEVENT=1 NO_QT=1 NO_SQLITE=1 NO_UPNP=1 NO_ZMQ=1 NO_USDT=1 gmake -C depends NO_BOOST=1 NO_LIBEVENT=1 NO_QT=1 NO_SQLITE=1 NO_ZMQ=1 NO_USDT=1
``` ```
When the build is complete, the Berkeley DB installation location will be displayed: When the build is complete, the Berkeley DB installation location will be displayed:

@ -44,7 +44,7 @@ from ports. However you can build it yourself, [using depends](/depends).
Refer to [depends/README.md](/depends/README.md) for detailed instructions. Refer to [depends/README.md](/depends/README.md) for detailed instructions.
```bash ```bash
gmake -C depends NO_BOOST=1 NO_LIBEVENT=1 NO_QT=1 NO_SQLITE=1 NO_UPNP=1 NO_ZMQ=1 NO_USDT=1 gmake -C depends NO_BOOST=1 NO_LIBEVENT=1 NO_QT=1 NO_SQLITE=1 NO_ZMQ=1 NO_USDT=1
... ...
to: /path/to/bitcoin/depends/*-unknown-openbsd* to: /path/to/bitcoin/depends/*-unknown-openbsd*
``` ```

@ -110,19 +110,6 @@ Otherwise, if you don't need QR encoding support, you can pass `-DWITH_QRENCODE=
--- ---
#### Port Mapping Dependencies
###### miniupnpc
miniupnpc may be used for UPnP port mapping.
Skip if you do not need this functionality.
``` bash
brew install miniupnpc
```
---
#### ZMQ Dependencies #### ZMQ Dependencies
Support for ZMQ notifications requires the following dependency. Support for ZMQ notifications requires the following dependency.

@ -60,10 +60,6 @@ executables, which are based on BerkeleyDB 4.8. Otherwise, you can build Berkele
To build Bitcoin Core without wallet, see [*Disable-wallet mode*](#disable-wallet-mode) To build Bitcoin Core without wallet, see [*Disable-wallet mode*](#disable-wallet-mode)
Optional port mapping library (see: `-DWITH_MINIUPNPC=ON`):
sudo apt install libminiupnpc-dev
ZMQ dependencies (provides ZMQ API): ZMQ dependencies (provides ZMQ API):
sudo apt-get install libzmq3-dev sudo apt-get install libzmq3-dev
@ -112,10 +108,6 @@ are based on Berkeley DB 4.8. Otherwise, you can build Berkeley DB [yourself](#b
To build Bitcoin Core without wallet, see [*Disable-wallet mode*](#disable-wallet-mode) To build Bitcoin Core without wallet, see [*Disable-wallet mode*](#disable-wallet-mode)
Optional port mapping library (see: `-DWITH_MINIUPNPC=ON`):
sudo dnf install miniupnpc-devel
ZMQ dependencies (provides ZMQ API): ZMQ dependencies (provides ZMQ API):
sudo dnf install zeromq-devel sudo dnf install zeromq-devel
@ -153,7 +145,7 @@ The legacy wallet uses Berkeley DB. To ensure backwards compatibility it is
recommended to use Berkeley DB 4.8. If you have to build it yourself, and don't recommended to use Berkeley DB 4.8. If you have to build it yourself, and don't
want to use any other libraries built in depends, you can do: want to use any other libraries built in depends, you can do:
```bash ```bash
make -C depends NO_BOOST=1 NO_LIBEVENT=1 NO_QT=1 NO_SQLITE=1 NO_UPNP=1 NO_ZMQ=1 NO_USDT=1 make -C depends NO_BOOST=1 NO_LIBEVENT=1 NO_QT=1 NO_SQLITE=1 NO_ZMQ=1 NO_USDT=1
... ...
to: /path/to/bitcoin/depends/x86_64-pc-linux-gnu to: /path/to/bitcoin/depends/x86_64-pc-linux-gnu
``` ```

@ -31,11 +31,6 @@ You can find installation instructions in the `build-*.md` file for your platfor
| [qrencode](../depends/packages/qrencode.mk) | [link](https://fukuchi.org/works/qrencode/) | [4.1.1](https://github.com/bitcoin/bitcoin/pull/27312) | | No | | [qrencode](../depends/packages/qrencode.mk) | [link](https://fukuchi.org/works/qrencode/) | [4.1.1](https://github.com/bitcoin/bitcoin/pull/27312) | | No |
| [Qt](../depends/packages/qt.mk) | [link](https://download.qt.io/official_releases/qt/) | [5.15.14](https://github.com/bitcoin/bitcoin/pull/30198) | [5.11.3](https://github.com/bitcoin/bitcoin/pull/24132) | No | | [Qt](../depends/packages/qt.mk) | [link](https://download.qt.io/official_releases/qt/) | [5.15.14](https://github.com/bitcoin/bitcoin/pull/30198) | [5.11.3](https://github.com/bitcoin/bitcoin/pull/24132) | No |
### Networking
| Dependency | Releases | Version used | Minimum required | Runtime |
| --- | --- | --- | --- | --- |
| [MiniUPnPc](../depends/packages/miniupnpc.mk) | [link](https://miniupnp.tuxfamily.org/) | [2.2.7](https://github.com/bitcoin/bitcoin/pull/29707) | 2.1 | No |
### Notifications ### Notifications
| Dependency | Releases | Version used | Minimum required | Runtime | | Dependency | Releases | Version used | Minimum required | Runtime |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |

@ -0,0 +1,10 @@
P2P and network changes
-----------------------
Support for UPnP was dropped. If you want to open a port automatically, consider using the `-natpmp`
option instead, which uses PCP or NAT-PMP depending on router support.
Updated settings
------
- Setting `-upnp` will now return an error. Consider using `-natpmp` instead.

@ -200,7 +200,7 @@ as well, use `discover` instead:
./bitcoind ... -discover ./bitcoind ... -discover
and open port 8333 on your firewall (or use port mapping, i.e., `-upnp` or `-natpmp`). and open port 8333 on your firewall (or use port mapping, i.e., `-natpmp`).
If you only want to use Tor to reach .onion addresses, but not use it as a proxy If you only want to use Tor to reach .onion addresses, but not use it as a proxy
for normal IPv4/IPv6 communication, use: for normal IPv4/IPv6 communication, use:

@ -294,7 +294,6 @@ target_link_libraries(bitcoin_node
Boost::headers Boost::headers
$<TARGET_NAME_IF_EXISTS:libevent::libevent> $<TARGET_NAME_IF_EXISTS:libevent::libevent>
$<TARGET_NAME_IF_EXISTS:libevent::pthreads> $<TARGET_NAME_IF_EXISTS:libevent::pthreads>
$<TARGET_NAME_IF_EXISTS:MiniUPnPc::MiniUPnPc>
$<TARGET_NAME_IF_EXISTS:bitcoin_zmq> $<TARGET_NAME_IF_EXISTS:bitcoin_zmq>
$<TARGET_NAME_IF_EXISTS:USDT::headers> $<TARGET_NAME_IF_EXISTS:USDT::headers>
) )

@ -561,11 +561,8 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
argsman.AddArg("-peertimeout=<n>", strprintf("Specify a p2p connection timeout delay in seconds. After connecting to a peer, wait this amount of time before considering disconnection based on inactivity (minimum: 1, default: %d)", DEFAULT_PEER_CONNECT_TIMEOUT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION); argsman.AddArg("-peertimeout=<n>", strprintf("Specify a p2p connection timeout delay in seconds. After connecting to a peer, wait this amount of time before considering disconnection based on inactivity (minimum: 1, default: %d)", DEFAULT_PEER_CONNECT_TIMEOUT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION);
argsman.AddArg("-torcontrol=<ip>:<port>", strprintf("Tor control host and port to use if onion listening enabled (default: %s). If no port is specified, the default port of %i will be used.", DEFAULT_TOR_CONTROL, DEFAULT_TOR_CONTROL_PORT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-torcontrol=<ip>:<port>", strprintf("Tor control host and port to use if onion listening enabled (default: %s). If no port is specified, the default port of %i will be used.", DEFAULT_TOR_CONTROL, DEFAULT_TOR_CONTROL_PORT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-torpassword=<pass>", "Tor control port password (default: empty)", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::CONNECTION); argsman.AddArg("-torpassword=<pass>", "Tor control port password (default: empty)", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::CONNECTION);
#ifdef USE_UPNP // UPnP support was dropped. We keep `-upnp` as a hidden arg to display a more user friendly error when set. TODO: remove (here and below) for 30.0.
argsman.AddArg("-upnp", strprintf("Use UPnP to map the listening port (default: %u)", DEFAULT_UPNP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-upnp", "", ArgsManager::ALLOW_ANY, OptionsCategory::HIDDEN);
#else
hidden_args.emplace_back("-upnp");
#endif
argsman.AddArg("-natpmp", strprintf("Use PCP or NAT-PMP to map the listening port (default: %u)", DEFAULT_NATPMP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-natpmp", strprintf("Use PCP or NAT-PMP to map the listening port (default: %u)", DEFAULT_NATPMP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-whitebind=<[permissions@]addr>", "Bind to the given address and add permission flags to the peers connecting to it. " argsman.AddArg("-whitebind=<[permissions@]addr>", "Bind to the given address and add permission flags to the peers connecting to it. "
"Use [host]:port notation for IPv6. Allowed permissions: " + Join(NET_PERMISSIONS_DOC, ", ") + ". " "Use [host]:port notation for IPv6. Allowed permissions: " + Join(NET_PERMISSIONS_DOC, ", ") + ". "
@ -740,8 +737,6 @@ void InitParameterInteraction(ArgsManager& args)
LogInfo("parameter interaction: -proxy set -> setting -listen=0\n"); LogInfo("parameter interaction: -proxy set -> setting -listen=0\n");
// to protect privacy, do not map ports when a proxy is set. The user may still specify -listen=1 // to protect privacy, do not map ports when a proxy is set. The user may still specify -listen=1
// to listen locally, so don't rely on this happening through -listen below. // to listen locally, so don't rely on this happening through -listen below.
if (args.SoftSetBoolArg("-upnp", false))
LogInfo("parameter interaction: -proxy set -> setting -upnp=0\n");
if (args.SoftSetBoolArg("-natpmp", false)) { if (args.SoftSetBoolArg("-natpmp", false)) {
LogInfo("parameter interaction: -proxy set -> setting -natpmp=0\n"); LogInfo("parameter interaction: -proxy set -> setting -natpmp=0\n");
} }
@ -752,8 +747,6 @@ void InitParameterInteraction(ArgsManager& args)
if (!args.GetBoolArg("-listen", DEFAULT_LISTEN)) { if (!args.GetBoolArg("-listen", DEFAULT_LISTEN)) {
// do not map ports or try to retrieve public IP when not listening (pointless) // do not map ports or try to retrieve public IP when not listening (pointless)
if (args.SoftSetBoolArg("-upnp", false))
LogInfo("parameter interaction: -listen=0 -> setting -upnp=0\n");
if (args.SoftSetBoolArg("-natpmp", false)) { if (args.SoftSetBoolArg("-natpmp", false)) {
LogInfo("parameter interaction: -listen=0 -> setting -natpmp=0\n"); LogInfo("parameter interaction: -listen=0 -> setting -natpmp=0\n");
} }
@ -877,6 +870,12 @@ bool AppInitParameterInteraction(const ArgsManager& args)
// also see: InitParameterInteraction() // also see: InitParameterInteraction()
// We drop UPnP support but kept the arg as hidden for now to display a friendlier error to user who have the
// option in their config. TODO: remove (here and above) for version 30.0.
if (args.IsArgSet("-upnp")) {
return InitError(_("UPnP support was dropped in version 29.0. Consider using '-natpmp' instead."));
}
// Error if network-specific options (-addnode, -connect, etc) are // Error if network-specific options (-addnode, -connect, etc) are
// specified in default section of config file, but not overridden // specified in default section of config file, but not overridden
// on the command line or in this chain's section of the config file. // on the command line or in this chain's section of the config file.
@ -1827,8 +1826,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
LogPrintf("nBestHeight = %d\n", chain_active_height); LogPrintf("nBestHeight = %d\n", chain_active_height);
if (node.peerman) node.peerman->SetBestBlock(chain_active_height, std::chrono::seconds{best_block_time}); if (node.peerman) node.peerman->SetBestBlock(chain_active_height, std::chrono::seconds{best_block_time});
// Map ports with UPnP or NAT-PMP // Map ports with NAT-PMP
StartMapPort(args.GetBoolArg("-upnp", DEFAULT_UPNP), args.GetBoolArg("-natpmp", DEFAULT_NATPMP)); StartMapPort(args.GetBoolArg("-natpmp", DEFAULT_NATPMP));
CConnman::Options connOptions; CConnman::Options connOptions;
connOptions.m_local_services = g_local_services; connOptions.m_local_services = g_local_services;

@ -121,7 +121,7 @@ public:
virtual void resetSettings() = 0; virtual void resetSettings() = 0;
//! Map port. //! Map port.
virtual void mapPort(bool use_upnp, bool use_pcp) = 0; virtual void mapPort(bool use_pcp) = 0;
//! Get proxy. //! Get proxy.
virtual bool getProxy(Network net, Proxy& proxy_info) = 0; virtual bool getProxy(Network net, Proxy& proxy_info) = 0;

@ -2,8 +2,6 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bitcoin-build-config.h> // IWYU pragma: keep
#include <mapport.h> #include <mapport.h>
#include <clientversion.h> #include <clientversion.h>
@ -18,15 +16,6 @@
#include <util/thread.h> #include <util/thread.h>
#include <util/threadinterrupt.h> #include <util/threadinterrupt.h>
#ifdef USE_UPNP
#include <miniupnpc/miniupnpc.h>
#include <miniupnpc/upnpcommands.h>
#include <miniupnpc/upnperrors.h>
// The minimum supported miniUPnPc API version is set to 17. This excludes
// versions with known vulnerabilities.
static_assert(MINIUPNPC_API_VERSION >= 17, "miniUPnPc API version >= 17 assumed");
#endif // USE_UPNP
#include <atomic> #include <atomic>
#include <cassert> #include <cassert>
#include <chrono> #include <chrono>
@ -134,100 +123,18 @@ static bool ProcessPCP()
return ret; return ret;
} }
#ifdef USE_UPNP
static bool ProcessUpnp()
{
bool ret = false;
std::string port = strprintf("%u", GetListenPort());
const char * multicastif = nullptr;
const char * minissdpdpath = nullptr;
struct UPNPDev * devlist = nullptr;
char lanaddr[64];
int error = 0;
devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error);
struct UPNPUrls urls;
struct IGDdatas data;
int r;
#if MINIUPNPC_API_VERSION <= 17
r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
#else
r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), nullptr, 0);
#endif
if (r == 1)
{
if (fDiscover) {
char externalIPAddress[40];
r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
if (r != UPNPCOMMAND_SUCCESS) {
LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r);
} else {
if (externalIPAddress[0]) {
std::optional<CNetAddr> resolved{LookupHost(externalIPAddress, false)};
if (resolved.has_value()) {
LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved->ToStringAddr());
AddLocal(resolved.value(), LOCAL_MAPPED);
}
} else {
LogPrintf("UPnP: GetExternalIPAddress failed.\n");
}
}
}
std::string strDesc = PACKAGE_NAME " " + FormatFullVersion();
do {
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", nullptr, "0");
if (r != UPNPCOMMAND_SUCCESS) {
ret = false;
LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", port, port, lanaddr, r, strupnperror(r));
break;
} else {
ret = true;
LogPrintf("UPnP Port Mapping successful.\n");
}
} while (g_mapport_interrupt.sleep_for(PORT_MAPPING_REANNOUNCE_PERIOD));
g_mapport_interrupt.reset();
r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", nullptr);
LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r);
freeUPNPDevlist(devlist); devlist = nullptr;
FreeUPNPUrls(&urls);
} else {
LogPrintf("No valid UPnP IGDs found\n");
freeUPNPDevlist(devlist); devlist = nullptr;
if (r != 0)
FreeUPNPUrls(&urls);
}
return ret;
}
#endif // USE_UPNP
static void ThreadMapPort() static void ThreadMapPort()
{ {
bool ok; bool ok;
do { do {
ok = false; ok = false;
// High priority protocol.
if (g_mapport_enabled_protos & MapPortProtoFlag::PCP) { if (g_mapport_enabled_protos & MapPortProtoFlag::PCP) {
g_mapport_current_proto = MapPortProtoFlag::PCP; g_mapport_current_proto = MapPortProtoFlag::PCP;
ok = ProcessPCP(); ok = ProcessPCP();
if (ok) continue; if (ok) continue;
} }
#ifdef USE_UPNP
// Low priority protocol.
if (g_mapport_enabled_protos & MapPortProtoFlag::UPNP) {
g_mapport_current_proto = MapPortProtoFlag::UPNP;
ok = ProcessUpnp();
if (ok) continue;
}
#endif // USE_UPNP
g_mapport_current_proto = MapPortProtoFlag::NONE; g_mapport_current_proto = MapPortProtoFlag::NONE;
if (g_mapport_enabled_protos == MapPortProtoFlag::NONE) { if (g_mapport_enabled_protos == MapPortProtoFlag::NONE) {
return; return;
@ -262,15 +169,8 @@ static void DispatchMapPort()
} }
if (g_mapport_enabled_protos & g_mapport_current_proto) { if (g_mapport_enabled_protos & g_mapport_current_proto) {
// Enabling another protocol does not cause switching from the currently used one.
return; return;
} }
assert(g_mapport_thread.joinable());
assert(!g_mapport_interrupt);
// Interrupt a protocol-specific loop in the ThreadUpnp() or in the ThreadPCP()
// to force trying the next protocol in the ThreadMapPort() loop.
g_mapport_interrupt();
} }
static void MapPortProtoSetEnabled(MapPortProtoFlag proto, bool enabled) static void MapPortProtoSetEnabled(MapPortProtoFlag proto, bool enabled)
@ -282,9 +182,8 @@ static void MapPortProtoSetEnabled(MapPortProtoFlag proto, bool enabled)
} }
} }
void StartMapPort(bool use_upnp, bool use_pcp) void StartMapPort(bool use_pcp)
{ {
MapPortProtoSetEnabled(MapPortProtoFlag::UPNP, use_upnp);
MapPortProtoSetEnabled(MapPortProtoFlag::PCP, use_pcp); MapPortProtoSetEnabled(MapPortProtoFlag::PCP, use_pcp);
DispatchMapPort(); DispatchMapPort();
} }

@ -5,17 +5,15 @@
#ifndef BITCOIN_MAPPORT_H #ifndef BITCOIN_MAPPORT_H
#define BITCOIN_MAPPORT_H #define BITCOIN_MAPPORT_H
static constexpr bool DEFAULT_UPNP = false;
static constexpr bool DEFAULT_NATPMP = false; static constexpr bool DEFAULT_NATPMP = false;
enum MapPortProtoFlag : unsigned int { enum MapPortProtoFlag : unsigned int {
NONE = 0x00, NONE = 0x00,
UPNP = 0x01, // 0x01 was for UPnP, for which we dropped support.
PCP = 0x02, // PCP with NAT-PMP fallback. PCP = 0x02, // PCP with NAT-PMP fallback.
}; };
void StartMapPort(bool use_upnp, bool use_pcp); void StartMapPort(bool use_pcp);
void InterruptMapPort(); void InterruptMapPort();
void StopMapPort(); void StopMapPort();

@ -148,7 +148,7 @@ enum
LOCAL_NONE, // unknown LOCAL_NONE, // unknown
LOCAL_IF, // address a local interface listens on LOCAL_IF, // address a local interface listens on
LOCAL_BIND, // address explicit bound to LOCAL_BIND, // address explicit bound to
LOCAL_MAPPED, // address reported by UPnP or PCP LOCAL_MAPPED, // address reported by PCP
LOCAL_MANUAL, // address explicitly specified (-externalip=) LOCAL_MANUAL, // address explicitly specified (-externalip=)
LOCAL_MAX LOCAL_MAX

@ -187,7 +187,7 @@ public:
}); });
args().WriteSettingsFile(); args().WriteSettingsFile();
} }
void mapPort(bool use_upnp, bool use_pcp) override { StartMapPort(use_upnp, use_pcp); } void mapPort(bool use_pcp) override { StartMapPort(use_pcp); }
bool getProxy(Network net, Proxy& proxy_info) override { return GetProxy(net, proxy_info); } bool getProxy(Network net, Proxy& proxy_info) override { return GetProxy(net, proxy_info); }
size_t getNodeCount(ConnectionDirection flags) override size_t getNodeCount(ConnectionDirection flags) override
{ {

@ -133,7 +133,6 @@ target_link_libraries(bitcoinqt
bitcoin_cli bitcoin_cli
leveldb leveldb
Boost::headers Boost::headers
$<TARGET_NAME_IF_EXISTS:MiniUPnPc::MiniUPnPc>
$<TARGET_NAME_IF_EXISTS:PkgConfig::libqrencode> $<TARGET_NAME_IF_EXISTS:PkgConfig::libqrencode>
$<$<PLATFORM_ID:Darwin>:-framework\ AppKit> $<$<PLATFORM_ID:Darwin>:-framework\ AppKit>
$<$<CXX_COMPILER_ID:MSVC>:shlwapi> $<$<CXX_COMPILER_ID:MSVC>:shlwapi>

@ -315,16 +315,6 @@
<string>&amp;Network</string> <string>&amp;Network</string>
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_Network"> <layout class="QVBoxLayout" name="verticalLayout_Network">
<item>
<widget class="QCheckBox" name="mapPortUpnp">
<property name="toolTip">
<string>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</string>
</property>
<property name="text">
<string>Map port using &amp;UPnP</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QCheckBox" name="mapPortNatpmp"> <widget class="QCheckBox" name="mapPortNatpmp">
<property name="toolTip"> <property name="toolTip">

@ -105,10 +105,6 @@ OptionsDialog::OptionsDialog(QWidget* parent, bool enableWallet)
connect(ui->prune, &QPushButton::toggled, ui->pruneSize, &QWidget::setEnabled); connect(ui->prune, &QPushButton::toggled, ui->pruneSize, &QWidget::setEnabled);
/* Network elements init */ /* Network elements init */
#ifndef USE_UPNP
ui->mapPortUpnp->setEnabled(false);
#endif
ui->proxyIp->setEnabled(false); ui->proxyIp->setEnabled(false);
ui->proxyPort->setEnabled(false); ui->proxyPort->setEnabled(false);
ui->proxyPort->setValidator(new QIntValidator(1, 65535, this)); ui->proxyPort->setValidator(new QIntValidator(1, 65535, this));
@ -300,7 +296,6 @@ void OptionsDialog::setMapper()
mapper->addMapping(ui->m_enable_psbt_controls, OptionsModel::EnablePSBTControls); mapper->addMapping(ui->m_enable_psbt_controls, OptionsModel::EnablePSBTControls);
/* Network */ /* Network */
mapper->addMapping(ui->mapPortUpnp, OptionsModel::MapPortUPnP);
mapper->addMapping(ui->mapPortNatpmp, OptionsModel::MapPortNatpmp); mapper->addMapping(ui->mapPortNatpmp, OptionsModel::MapPortNatpmp);
mapper->addMapping(ui->allowIncoming, OptionsModel::Listen); mapper->addMapping(ui->allowIncoming, OptionsModel::Listen);
mapper->addMapping(ui->enableServer, OptionsModel::Server); mapper->addMapping(ui->enableServer, OptionsModel::Server);

@ -41,7 +41,6 @@ static const char* SettingName(OptionsModel::OptionID option)
case OptionsModel::ThreadsScriptVerif: return "par"; case OptionsModel::ThreadsScriptVerif: return "par";
case OptionsModel::SpendZeroConfChange: return "spendzeroconfchange"; case OptionsModel::SpendZeroConfChange: return "spendzeroconfchange";
case OptionsModel::ExternalSignerPath: return "signer"; case OptionsModel::ExternalSignerPath: return "signer";
case OptionsModel::MapPortUPnP: return "upnp";
case OptionsModel::MapPortNatpmp: return "natpmp"; case OptionsModel::MapPortNatpmp: return "natpmp";
case OptionsModel::Listen: return "listen"; case OptionsModel::Listen: return "listen";
case OptionsModel::Server: return "server"; case OptionsModel::Server: return "server";
@ -215,7 +214,7 @@ bool OptionsModel::Init(bilingual_str& error)
// These are shared with the core or have a command-line parameter // These are shared with the core or have a command-line parameter
// and we want command-line parameters to overwrite the GUI settings. // and we want command-line parameters to overwrite the GUI settings.
for (OptionID option : {DatabaseCache, ThreadsScriptVerif, SpendZeroConfChange, ExternalSignerPath, MapPortUPnP, for (OptionID option : {DatabaseCache, ThreadsScriptVerif, SpendZeroConfChange, ExternalSignerPath,
MapPortNatpmp, Listen, Server, Prune, ProxyUse, ProxyUseTor, Language}) { MapPortNatpmp, Listen, Server, Prune, ProxyUse, ProxyUseTor, Language}) {
std::string setting = SettingName(option); std::string setting = SettingName(option);
if (node().isSettingIgnored(setting)) addOverriddenOption("-" + setting); if (node().isSettingIgnored(setting)) addOverriddenOption("-" + setting);
@ -412,12 +411,6 @@ QVariant OptionsModel::getOption(OptionID option, const std::string& suffix) con
return m_show_tray_icon; return m_show_tray_icon;
case MinimizeToTray: case MinimizeToTray:
return fMinimizeToTray; return fMinimizeToTray;
case MapPortUPnP:
#ifdef USE_UPNP
return SettingToBool(setting(), DEFAULT_UPNP);
#else
return false;
#endif // USE_UPNP
case MapPortNatpmp: case MapPortNatpmp:
return SettingToBool(setting(), DEFAULT_NATPMP); return SettingToBool(setting(), DEFAULT_NATPMP);
case MinimizeOnClose: case MinimizeOnClose:
@ -530,16 +523,10 @@ bool OptionsModel::setOption(OptionID option, const QVariant& value, const std::
fMinimizeToTray = value.toBool(); fMinimizeToTray = value.toBool();
settings.setValue("fMinimizeToTray", fMinimizeToTray); settings.setValue("fMinimizeToTray", fMinimizeToTray);
break; break;
case MapPortUPnP: // core option - can be changed on-the-fly
if (changed()) {
update(value.toBool());
node().mapPort(value.toBool(), getOption(MapPortNatpmp).toBool());
}
break;
case MapPortNatpmp: // core option - can be changed on-the-fly case MapPortNatpmp: // core option - can be changed on-the-fly
if (changed()) { if (changed()) {
update(value.toBool()); update(value.toBool());
node().mapPort(getOption(MapPortUPnP).toBool(), value.toBool()); node().mapPort(value.toBool());
} }
break; break;
case MinimizeOnClose: case MinimizeOnClose:
@ -789,7 +776,6 @@ void OptionsModel::checkAndMigrate()
migrate_setting(SpendZeroConfChange, "bSpendZeroConfChange"); migrate_setting(SpendZeroConfChange, "bSpendZeroConfChange");
migrate_setting(ExternalSignerPath, "external_signer_path"); migrate_setting(ExternalSignerPath, "external_signer_path");
#endif #endif
migrate_setting(MapPortUPnP, "fUseUPnP");
migrate_setting(MapPortNatpmp, "fUseNatpmp"); migrate_setting(MapPortNatpmp, "fUseNatpmp");
migrate_setting(Listen, "fListen"); migrate_setting(Listen, "fListen");
migrate_setting(Server, "server"); migrate_setting(Server, "server");
@ -803,7 +789,7 @@ void OptionsModel::checkAndMigrate()
// In case migrating QSettings caused any settings value to change, rerun // In case migrating QSettings caused any settings value to change, rerun
// parameter interaction code to update other settings. This is particularly // parameter interaction code to update other settings. This is particularly
// important for the -listen setting, which should cause -listenonion, -upnp, // important for the -listen setting, which should cause -listenonion
// and other settings to default to false if it was set to false. // and other settings to default to false if it was set to false.
// (https://github.com/bitcoin-core/gui/issues/567). // (https://github.com/bitcoin-core/gui/issues/567).
node().initParameterInteraction(); node().initParameterInteraction();

@ -50,7 +50,6 @@ public:
StartAtStartup, // bool StartAtStartup, // bool
ShowTrayIcon, // bool ShowTrayIcon, // bool
MinimizeToTray, // bool MinimizeToTray, // bool
MapPortUPnP, // bool
MapPortNatpmp, // bool MapPortNatpmp, // bool
MinimizeOnClose, // bool MinimizeOnClose, // bool
ProxyUse, // bool ProxyUse, // bool

@ -37,7 +37,6 @@ void OptionTests::migrateSettings()
QSettings settings; QSettings settings;
settings.setValue("nDatabaseCache", 600); settings.setValue("nDatabaseCache", 600);
settings.setValue("nThreadsScriptVerif", 12); settings.setValue("nThreadsScriptVerif", 12);
settings.setValue("fUseUPnP", false);
settings.setValue("fListen", false); settings.setValue("fListen", false);
settings.setValue("bPrune", true); settings.setValue("bPrune", true);
settings.setValue("nPruneSize", 3); settings.setValue("nPruneSize", 3);
@ -50,7 +49,6 @@ void OptionTests::migrateSettings()
QVERIFY(settings.contains("nDatabaseCache")); QVERIFY(settings.contains("nDatabaseCache"));
QVERIFY(settings.contains("nThreadsScriptVerif")); QVERIFY(settings.contains("nThreadsScriptVerif"));
QVERIFY(settings.contains("fUseUPnP"));
QVERIFY(settings.contains("fListen")); QVERIFY(settings.contains("fListen"));
QVERIFY(settings.contains("bPrune")); QVERIFY(settings.contains("bPrune"));
QVERIFY(settings.contains("nPruneSize")); QVERIFY(settings.contains("nPruneSize"));
@ -64,7 +62,6 @@ void OptionTests::migrateSettings()
QVERIFY(options.Init(error)); QVERIFY(options.Init(error));
QVERIFY(!settings.contains("nDatabaseCache")); QVERIFY(!settings.contains("nDatabaseCache"));
QVERIFY(!settings.contains("nThreadsScriptVerif")); QVERIFY(!settings.contains("nThreadsScriptVerif"));
QVERIFY(!settings.contains("fUseUPnP"));
QVERIFY(!settings.contains("fListen")); QVERIFY(!settings.contains("fListen"));
QVERIFY(!settings.contains("bPrune")); QVERIFY(!settings.contains("bPrune"));
QVERIFY(!settings.contains("nPruneSize")); QVERIFY(!settings.contains("nPruneSize"));

@ -54,7 +54,6 @@ int main(int argc, char* argv[])
gArgs.ForceSetArg("-discover", "0"); gArgs.ForceSetArg("-discover", "0");
gArgs.ForceSetArg("-dnsseed", "0"); gArgs.ForceSetArg("-dnsseed", "0");
gArgs.ForceSetArg("-fixedseeds", "0"); gArgs.ForceSetArg("-fixedseeds", "0");
gArgs.ForceSetArg("-upnp", "0");
gArgs.ForceSetArg("-natpmp", "0"); gArgs.ForceSetArg("-natpmp", "0");
std::string error; std::string error;

@ -433,7 +433,6 @@ def write_config(config_path, *, n, chain, extra_config="", disable_autoconnect=
# in tests. # in tests.
f.write("peertimeout=999999999\n") f.write("peertimeout=999999999\n")
f.write("printtoconsole=0\n") f.write("printtoconsole=0\n")
f.write("upnp=0\n")
f.write("natpmp=0\n") f.write("natpmp=0\n")
f.write("shrinkdebugfile=0\n") f.write("shrinkdebugfile=0\n")
f.write("deprecatedrpc=create_bdb\n") # Required to run the tests f.write("deprecatedrpc=create_bdb\n") # Required to run the tests

@ -13,7 +13,6 @@
], ],
"default-features": [ "default-features": [
"wallet", "wallet",
"miniupnpc",
"zeromq", "zeromq",
"tests", "tests",
"qt5" "qt5"
@ -31,10 +30,6 @@
"description": "Enable Berkeley DB wallet support", "description": "Enable Berkeley DB wallet support",
"dependencies": [ "berkeleydb" ] "dependencies": [ "berkeleydb" ]
}, },
"miniupnpc": {
"description": "Enable UPnP",
"dependencies": [ "miniupnpc" ]
},
"zeromq": { "zeromq": {
"description": "Enable ZMQ notifications", "description": "Enable ZMQ notifications",
"dependencies": [ "zeromq" ] "dependencies": [ "zeromq" ]

Loading…
Cancel
Save