From d10c5c34c3d899db8bcff47ac8c6ba396a6da4b6 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 24 Jul 2024 12:53:35 +0100 Subject: [PATCH] cmake: Add wallet functionality --- CMakeLists.txt | 39 +++++++++ cmake/bitcoin-config.h.in | 9 ++ cmake/module/FindBerkeleyDB.cmake | 133 ++++++++++++++++++++++++++++++ src/CMakeLists.txt | 25 +++++- src/test/CMakeLists.txt | 4 + src/test/util/CMakeLists.txt | 1 + src/wallet/CMakeLists.txt | 58 +++++++++++++ src/wallet/test/CMakeLists.txt | 32 +++++++ 8 files changed, 299 insertions(+), 2 deletions(-) create mode 100644 cmake/module/FindBerkeleyDB.cmake create mode 100644 src/wallet/CMakeLists.txt create mode 100644 src/wallet/test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 9529847bd15..406c53a564e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,12 +64,44 @@ list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/module) #============================= # Configurable options #============================= +include(CMakeDependentOption) # When adding a new option, end the with a full stop for consistency. option(BUILD_DAEMON "Build bitcoind executable." ON) option(BUILD_CLI "Build bitcoin-cli executable." ON) option(BUILD_TESTS "Build test_bitcoin executable." ON) +option(ENABLE_WALLET "Enable wallet." ON) +option(WITH_SQLITE "Enable SQLite wallet support." ${ENABLE_WALLET}) +if(WITH_SQLITE) + if(VCPKG_TARGET_TRIPLET) + # Use of the `unofficial::` namespace is a vcpkg package manager convention. + find_package(unofficial-sqlite3 CONFIG REQUIRED) + else() + find_package(SQLite3 3.7.17 REQUIRED) + endif() + set(USE_SQLITE ON) + set(ENABLE_WALLET ON) +endif() +option(WITH_BDB "Enable Berkeley DB (BDB) wallet support." OFF) +cmake_dependent_option(WARN_INCOMPATIBLE_BDB "Warn when using a Berkeley DB (BDB) version other than 4.8." ON "WITH_BDB" OFF) +if(WITH_BDB) + find_package(BerkeleyDB 4.8 MODULE REQUIRED) + set(USE_BDB ON) + set(ENABLE_WALLET ON) + if(NOT BerkeleyDB_VERSION VERSION_EQUAL 4.8) + message(WARNING "Found Berkeley DB (BDB) other than 4.8.\n" + "BDB (legacy) wallets opened by this build will not be portable!" + ) + if(WARN_INCOMPATIBLE_BDB) + message(WARNING "If this is intended, pass \"-DWARN_INCOMPATIBLE_BDB=OFF\".\n" + "Passing \"-DWITH_BDB=OFF\" will suppress this warning." + ) + endif() + endif() +endif() +cmake_dependent_option(BUILD_WALLET_TOOL "Build bitcoin-wallet tool." ${BUILD_TESTS} "ENABLE_WALLET" OFF) + option(WITH_CCACHE "Attempt to use ccache for compiling." ON) set(configure_warnings) @@ -235,6 +267,13 @@ message("=================") message("Executables:") message(" bitcoind ............................ ${BUILD_DAEMON}") message(" bitcoin-cli ......................... ${BUILD_CLI}") +message(" bitcoin-wallet ...................... ${BUILD_WALLET_TOOL}") +message("Optional features:") +message(" wallet support ...................... ${ENABLE_WALLET}") +if(ENABLE_WALLET) + message(" - descriptor wallets (SQLite) ...... ${WITH_SQLITE}") + message(" - legacy wallets (Berkeley DB) ..... ${WITH_BDB}") +endif() message("Tests:") message(" test_bitcoin ........................ ${BUILD_TESTS}") message("") diff --git a/cmake/bitcoin-config.h.in b/cmake/bitcoin-config.h.in index a58a97373d4..d046913ce8c 100644 --- a/cmake/bitcoin-config.h.in +++ b/cmake/bitcoin-config.h.in @@ -38,6 +38,9 @@ /* Define this symbol to build code that uses SSE4.1 intrinsics */ #cmakedefine ENABLE_SSE41 1 +/* Define to 1 to enable wallet functions. */ +#cmakedefine ENABLE_WALLET 1 + /* Define this symbol to build code that uses x86 SHA-NI intrinsics */ #cmakedefine ENABLE_X86_SHANI 1 @@ -128,4 +131,10 @@ /* Define to 1 if strerror_r returns char *. */ #cmakedefine STRERROR_R_CHAR_P 1 +/* Define if BDB support should be compiled in */ +#cmakedefine USE_BDB 1 + +/* Define if sqlite support should be compiled in */ +#cmakedefine USE_SQLITE 1 + #endif //BITCOIN_CONFIG_H diff --git a/cmake/module/FindBerkeleyDB.cmake b/cmake/module/FindBerkeleyDB.cmake new file mode 100644 index 00000000000..03a3cce10c5 --- /dev/null +++ b/cmake/module/FindBerkeleyDB.cmake @@ -0,0 +1,133 @@ +# 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/. + +#[=======================================================================[ +FindBerkeleyDB +-------------- + +Finds the Berkeley DB headers and library. + +Imported Targets +^^^^^^^^^^^^^^^^ + +This module provides imported target ``BerkeleyDB::BerkeleyDB``, if +Berkeley DB has been found. + +Result Variables +^^^^^^^^^^^^^^^^ + +This module defines the following variables: + +``BerkeleyDB_FOUND`` + "True" if Berkeley DB found. + +``BerkeleyDB_VERSION`` + The MAJOR.MINOR version of Berkeley DB found. + +#]=======================================================================] + +set(_BerkeleyDB_homebrew_prefix) +if(CMAKE_HOST_APPLE) + find_program(HOMEBREW_EXECUTABLE brew) + if(HOMEBREW_EXECUTABLE) + # The Homebrew package manager installs the berkeley-db* packages as + # "keg-only", which means they are not symlinked into the default prefix. + # To find such a package, the find_path() and find_library() commands + # need additional path hints that are computed by Homebrew itself. + execute_process( + COMMAND ${HOMEBREW_EXECUTABLE} --prefix berkeley-db@4 + OUTPUT_VARIABLE _BerkeleyDB_homebrew_prefix + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif() +endif() + +find_path(BerkeleyDB_INCLUDE_DIR + NAMES db_cxx.h + HINTS ${_BerkeleyDB_homebrew_prefix}/include + PATH_SUFFIXES 4.8 48 db4.8 4 db4 5.3 db5.3 5 db5 +) +mark_as_advanced(BerkeleyDB_INCLUDE_DIR) +unset(_BerkeleyDB_homebrew_prefix) + +if(NOT BerkeleyDB_LIBRARY) + if(VCPKG_TARGET_TRIPLET) + # The vcpkg package manager installs the berkeleydb package with the same name + # of release and debug libraries. Therefore, the default search paths set by + # vcpkg's toolchain file cannot be used to search libraries as the debug one + # will always be found. + set(CMAKE_FIND_USE_CMAKE_PATH FALSE) + endif() + + get_filename_component(_BerkeleyDB_lib_hint "${BerkeleyDB_INCLUDE_DIR}" DIRECTORY) + + find_library(BerkeleyDB_LIBRARY_RELEASE + NAMES db_cxx-4.8 db4_cxx db48 db_cxx-5.3 db_cxx-5 db_cxx libdb48 + NAMES_PER_DIR + HINTS ${_BerkeleyDB_lib_hint} + PATH_SUFFIXES lib + ) + mark_as_advanced(BerkeleyDB_LIBRARY_RELEASE) + + find_library(BerkeleyDB_LIBRARY_DEBUG + NAMES db_cxx-4.8 db4_cxx db48 db_cxx-5.3 db_cxx-5 db_cxx libdb48 + NAMES_PER_DIR + HINTS ${_BerkeleyDB_lib_hint} + PATH_SUFFIXES debug/lib + ) + mark_as_advanced(BerkeleyDB_LIBRARY_DEBUG) + + unset(_BerkeleyDB_lib_hint) + unset(CMAKE_FIND_USE_CMAKE_PATH) + + include(SelectLibraryConfigurations) + select_library_configurations(BerkeleyDB) + # The select_library_configurations() command sets BerkeleyDB_FOUND, but we + # want the one from the find_package_handle_standard_args() command below. + unset(BerkeleyDB_FOUND) +endif() + +if(BerkeleyDB_INCLUDE_DIR) + file(STRINGS "${BerkeleyDB_INCLUDE_DIR}/db.h" _BerkeleyDB_version_strings REGEX "^#define[\t ]+DB_VERSION_(MAJOR|MINOR|PATCH)[ \t]+[0-9]+.*") + string(REGEX REPLACE ".*#define[\t ]+DB_VERSION_MAJOR[ \t]+([0-9]+).*" "\\1" _BerkeleyDB_version_major "${_BerkeleyDB_version_strings}") + string(REGEX REPLACE ".*#define[\t ]+DB_VERSION_MINOR[ \t]+([0-9]+).*" "\\1" _BerkeleyDB_version_minor "${_BerkeleyDB_version_strings}") + string(REGEX REPLACE ".*#define[\t ]+DB_VERSION_PATCH[ \t]+([0-9]+).*" "\\1" _BerkeleyDB_version_patch "${_BerkeleyDB_version_strings}") + unset(_BerkeleyDB_version_strings) + # The MAJOR.MINOR.PATCH version will be logged in the following find_package_handle_standard_args() command. + set(_BerkeleyDB_full_version ${_BerkeleyDB_version_major}.${_BerkeleyDB_version_minor}.${_BerkeleyDB_version_patch}) + set(BerkeleyDB_VERSION ${_BerkeleyDB_version_major}.${_BerkeleyDB_version_minor}) + unset(_BerkeleyDB_version_major) + unset(_BerkeleyDB_version_minor) + unset(_BerkeleyDB_version_patch) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(BerkeleyDB + REQUIRED_VARS BerkeleyDB_LIBRARY BerkeleyDB_INCLUDE_DIR + VERSION_VAR _BerkeleyDB_full_version +) +unset(_BerkeleyDB_full_version) + +if(BerkeleyDB_FOUND AND NOT TARGET BerkeleyDB::BerkeleyDB) + add_library(BerkeleyDB::BerkeleyDB UNKNOWN IMPORTED) + set_target_properties(BerkeleyDB::BerkeleyDB PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${BerkeleyDB_INCLUDE_DIR}" + ) + if(BerkeleyDB_LIBRARY_RELEASE) + set_property(TARGET BerkeleyDB::BerkeleyDB APPEND PROPERTY + IMPORTED_CONFIGURATIONS RELEASE + ) + set_target_properties(BerkeleyDB::BerkeleyDB PROPERTIES + IMPORTED_LOCATION_RELEASE "${BerkeleyDB_LIBRARY_RELEASE}" + ) + endif() + if(BerkeleyDB_LIBRARY_DEBUG) + set_property(TARGET BerkeleyDB::BerkeleyDB APPEND PROPERTY + IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(BerkeleyDB::BerkeleyDB PROPERTIES + IMPORTED_LOCATION_DEBUG "${BerkeleyDB_LIBRARY_DEBUG}" + ) + endif() +endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 09e57e13789..6eff28fb262 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -142,6 +142,26 @@ target_link_libraries(bitcoin_common ) +if(ENABLE_WALLET) + add_subdirectory(wallet) + + if(BUILD_WALLET_TOOL) + add_executable(bitcoin-wallet + bitcoin-wallet.cpp + init/bitcoin-wallet.cpp + wallet/wallettool.cpp + ) + target_link_libraries(bitcoin-wallet + core_interface + bitcoin_wallet + bitcoin_common + bitcoin_util + Boost::headers + ) + endif() +endif() + + # P2P and RPC server functionality used by `bitcoind` and `bitcoin-qt` executables. add_library(bitcoin_node STATIC EXCLUDE_FROM_ALL addrdb.cpp @@ -234,8 +254,8 @@ add_library(bitcoin_node STATIC EXCLUDE_FROM_ALL validation.cpp validationinterface.cpp versionbits.cpp - - dummywallet.cpp + $<$:wallet/init.cpp> + $<$>:dummywallet.cpp> ) target_link_libraries(bitcoin_node PRIVATE @@ -260,6 +280,7 @@ if(BUILD_DAEMON) target_link_libraries(bitcoind core_interface bitcoin_node + $ ) endif() diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index d607e0782f6..ee13bb5523e 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -154,6 +154,10 @@ target_link_libraries(test_bitcoin $ ) +if(ENABLE_WALLET) + add_subdirectory(${PROJECT_SOURCE_DIR}/src/wallet/test wallet) +endif() + function(add_boost_test source_file) if(NOT EXISTS ${source_file}) return() diff --git a/src/test/util/CMakeLists.txt b/src/test/util/CMakeLists.txt index eb79ea11a74..5d88d1da3ec 100644 --- a/src/test/util/CMakeLists.txt +++ b/src/test/util/CMakeLists.txt @@ -17,6 +17,7 @@ add_library(test_util STATIC EXCLUDE_FROM_ALL transaction_utils.cpp txmempool.cpp validation.cpp + $<$:${PROJECT_SOURCE_DIR}/src/wallet/test/util.cpp> ) target_link_libraries(test_util diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt new file mode 100644 index 00000000000..19a05b16aae --- /dev/null +++ b/src/wallet/CMakeLists.txt @@ -0,0 +1,58 @@ +# 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/. + +# Wallet functionality used by bitcoind and bitcoin-wallet executables. +add_library(bitcoin_wallet STATIC EXCLUDE_FROM_ALL + coincontrol.cpp + coinselection.cpp + context.cpp + crypter.cpp + db.cpp + dump.cpp + external_signer_scriptpubkeyman.cpp + feebumper.cpp + fees.cpp + interfaces.cpp + load.cpp + migrate.cpp + receive.cpp + rpc/addresses.cpp + rpc/backup.cpp + rpc/coins.cpp + rpc/encrypt.cpp + rpc/signmessage.cpp + rpc/spend.cpp + rpc/transactions.cpp + rpc/util.cpp + rpc/wallet.cpp + scriptpubkeyman.cpp + spend.cpp + transaction.cpp + wallet.cpp + walletdb.cpp + walletutil.cpp +) +target_link_libraries(bitcoin_wallet + PRIVATE + core_interface + bitcoin_common + univalue + Boost::headers +) + +if(NOT USE_SQLITE AND NOT USE_BDB) + message(FATAL_ERROR "Wallet functionality requested but no BDB or SQLite support available.") +endif() +if(USE_SQLITE) + target_sources(bitcoin_wallet PRIVATE sqlite.cpp) + target_link_libraries(bitcoin_wallet + PRIVATE + $ + $ + ) +endif() +if(USE_BDB) + target_sources(bitcoin_wallet PRIVATE bdb.cpp salvage.cpp) + target_link_libraries(bitcoin_wallet PUBLIC BerkeleyDB::BerkeleyDB) +endif() diff --git a/src/wallet/test/CMakeLists.txt b/src/wallet/test/CMakeLists.txt new file mode 100644 index 00000000000..7332674242f --- /dev/null +++ b/src/wallet/test/CMakeLists.txt @@ -0,0 +1,32 @@ +# 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/. + +# Do not use generator expressions in test sources because the +# SOURCES property is processed to gather test suite macros. +target_sources(test_bitcoin + PRIVATE + init_test_fixture.cpp + wallet_test_fixture.cpp + coinselector_tests.cpp + feebumper_tests.cpp + group_outputs_tests.cpp + init_tests.cpp + ismine_tests.cpp + psbt_wallet_tests.cpp + rpc_util_tests.cpp + scriptpubkeyman_tests.cpp + spend_tests.cpp + wallet_crypto_tests.cpp + wallet_tests.cpp + wallet_transaction_tests.cpp + walletdb_tests.cpp + walletload_tests.cpp +) +if(USE_BDB) + target_sources(test_bitcoin + PRIVATE + db_tests.cpp + ) +endif() +target_link_libraries(test_bitcoin bitcoin_wallet)