Originally based on 22.0-fix_build_without_leveldb.patch. - Allow system libsecp256k1 - Allow system leveldb - Abort if runtime leveldb != compiled-against leveldb - Handle berkdb support being disabled better --- a/configure.ac +++ b/configure.ac @@ -1362,6 +1362,23 @@ if test "$enable_fuzz_binary" = "yes"; then CHECK_RUNTIME_LIB fi +dnl Check for libsecp256k1, only if explicitly requested +AC_ARG_WITH([system-libsecp256k1], + [AS_HELP_STRING([--with-system-libsecp256k1], + [Build with system libsecp256k1 (default is no; DANGEROUS; NOT SUPPORTED)])], + [system_libsecp256k1=$withval], + [system_libsecp256k1=no] +) +if test x$system_libsecp256k1 != xno; then + PKG_CHECK_MODULES([libsecp256k1],[libsecp256k1],,[true]) +else + libsecp256k1_CFLAGS='-I$(srcdir)/secp256k1/include' + libsecp256k1_LIBS='secp256k1/libsecp256k1.la' +fi +AM_CONDITIONAL([EMBEDDED_LIBSECP256K1],[test x$system_libsecp256k1 = xno]) +AC_SUBST(libsecp256k1_CFLAGS) +AC_SUBST(libsecp256k1_LIBS) + if test "$enable_wallet" != "no"; then dnl Check for libdb_cxx only if wallet enabled if test "$use_bdb" != "no"; then @@ -1413,11 +1430,76 @@ if test "$use_usdt" != "no"; then fi AM_CONDITIONAL([ENABLE_USDT_TRACEPOINTS], [test "$use_usdt" = "yes"]) +build_leveldb=yes if test "$build_bitcoin_cli$build_bitcoin_tx$build_bitcoin_util$build_bitcoind$bitcoin_enable_qt$use_bench$use_tests" = "nonononononono"; then use_upnp=no use_natpmp=no use_zmq=no + build_leveldb=no +fi + +if test x$build_leveldb = xno; then + system_leveldb=no +fi +dnl Check for leveldb, only if explicitly requested +if test x$system_leveldb != xno; then + build_leveldb=no + LEVELDB_CPPFLAGS= + AC_CHECK_LIB([leveldb],[main],[ + LIBLEVELDB=-lleveldb + ],[ + AC_MSG_ERROR([leveldb library not found; using --with-system-leveldb is not supported anyway]) + ]) + AC_CHECK_HEADER([leveldb/filter_policy.h],[],[ + AC_MSG_ERROR([LevelDB headers not found; using --with-system-leveldb is not supported anyway]) + ]) + AC_CHECK_HEADER([leveldb/helpers/memenv.h],[ + AC_MSG_CHECKING([for memenv.h path]) + BITCOIN_SUBDIR_TO_INCLUDE([LEVELDB_CPPFLAGS],[leveldb/helpers/],[memenv]) + ],[ + AC_CHECK_HEADER([memenv.h],[],[ + AC_MSG_ERROR([LevelDB headers not found; using --with-system-leveldb is not supported anyway]) + ]) + ]) + + AC_MSG_CHECKING([library containing leveldb::NewMemEnv]) + TEMP_LIBS="$LIBS" + TEMP_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $LEVELDB_CPPFLAGS" + for searchlib in "" "-lmemenv" ERR; do + if test "x$searchlib" = "xERR"; then + AC_MSG_RESULT([no]) + AC_MSG_ERROR([LevelDB's memenv helper not found; using --with-system-leveldb is not supported anyway]) + fi + searchlib="$searchlib $LIBLEVELDB" + LIBS="$searchlib $TEMP_LIBS" + AC_LINK_IFELSE([AC_LANG_SOURCE([ + #include + #include + + int main() { + leveldb::Env *myenv = leveldb::NewMemEnv(leveldb::Env::Default()); + delete myenv; + } + ])],[ + AC_MSG_RESULT([$searchlib]) + LIBMEMENV="$searchlib" + break + ]) + done + LIBS="$TEMP_LIBS" + CPPFLAGS="$TEMP_CPPFLAGS" fi +AM_CONDITIONAL([EMBEDDED_LEVELDB],[test x$build_leveldb = xyes]) +AC_SUBST(LEVELDB_CPPFLAGS) +AC_SUBST(LIBLEVELDB) +AC_SUBST(LIBMEMENV) +AC_ARG_WITH([system-leveldb], + [AS_HELP_STRING([--with-system-leveldb], + [Build with system LevelDB (default is no; DANGEROUS; NOT SUPPORTED)])], + [system_leveldb=$withval], + [system_leveldb=no] +) dnl Check for libminiupnpc (optional) if test "$use_upnp" != "no"; then --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,7 +23,7 @@ noinst_PROGRAMS = TESTS = BENCHMARKS = -BITCOIN_INCLUDES=-I$(builddir) -I$(srcdir)/$(MINISKETCH_INCLUDE_DIR_INT) -I$(srcdir)/secp256k1/include -I$(srcdir)/$(UNIVALUE_INCLUDE_DIR_INT) $(LEVELDB_CPPFLAGS) +BITCOIN_INCLUDES=-I$(builddir) -I$(srcdir)/$(MINISKETCH_INCLUDE_DIR_INT) $(libsecp256k1_CFLAGS) -I$(srcdir)/$(UNIVALUE_INCLUDE_DIR_INT) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) LIBBITCOIN_NODE=libbitcoin_node.a LIBBITCOIN_COMMON=libbitcoin_common.a @@ -32,7 +32,11 @@ LIBBITCOIN_CLI=libbitcoin_cli.a LIBBITCOIN_UTIL=libbitcoin_util.a LIBBITCOIN_CRYPTO_BASE=crypto/libbitcoin_crypto_base.la LIBBITCOINQT=qt/libbitcoinqt.a +if EMBEDDED_LIBSECP256K1 LIBSECP256K1=secp256k1/libsecp256k1.la +else +LIBSECP256K1=$(libsecp256k1_LIBS) +endif if ENABLE_ZMQ LIBBITCOIN_ZMQ=libbitcoin_zmq.a @@ -67,8 +71,10 @@ LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_ARM_SHANI) endif noinst_LTLIBRARIES += $(LIBBITCOIN_CRYPTO) +if EMBEDDED_LIBSECP256K1 $(LIBSECP256K1): $(wildcard secp256k1/src/*.h) $(wildcard secp256k1/src/*.c) $(wildcard secp256k1/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) +endif # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: @@ -1080,7 +1086,9 @@ endif include Makefile.minisketch.include include Makefile.crc32c.include +if EMBEDDED_LEVELDB include Makefile.leveldb.include +endif include Makefile.test_util.include include Makefile.test_fuzz.include --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -377,8 +377,9 @@ if ENABLE_BENCH $(BENCH_BINARY) --sanity-check > /dev/null endif endif +if EMBEDDED_LIBSECP256K1 $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check - +endif if ENABLE_TESTS UNIVALUE_TESTS = univalue/test/object univalue/test/unitester noinst_PROGRAMS += $(UNIVALUE_TESTS) --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -7,26 +7,45 @@ #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 +bool dbwrapper_SanityCheck() +{ + unsigned long header_version = (leveldb::kMajorVersion << 16) | leveldb::kMinorVersion; + unsigned long library_version = (leveldb_major_version() << 16) | leveldb_minor_version(); + + if (header_version != library_version) { + InitError(Untranslated(strprintf("Compiled with LevelDB %d.%d, but linked with LevelDB %d.%d (incompatible).", + leveldb::kMajorVersion, leveldb::kMinorVersion, + leveldb_major_version(), leveldb_minor_version() + ))); + return false; + } + + return true; +} + class CBitcoinLevelDBLogger : public leveldb::Logger { public: // This code is adapted from posix_logger.h, which is why it is using vsprintf. --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -31,6 +31,8 @@ class Env; static const size_t DBWRAPPER_PREALLOC_KEY_SIZE = 64; static const size_t DBWRAPPER_PREALLOC_VALUE_SIZE = 1024; +bool dbwrapper_SanityCheck(); + class dbwrapper_error : public std::runtime_error { public: --- a/src/kernel/checks.cpp +++ b/src/kernel/checks.cpp @@ -3,9 +3,10 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include - +#include #include #include +#include #include #include @@ -15,6 +16,10 @@ namespace kernel { std::optional SanityChecks(const Context&) { + if (!dbwrapper_SanityCheck()) { + return Untranslated("Database sanity check failure. Aborting."); + } + if (!ECC_InitSanityCheck()) { return Untranslated("Elliptic curve cryptography sanity check failure. Aborting."); } --- a/src/qt/createwalletdialog.cpp +++ b/src/qt/createwalletdialog.cpp @@ -12,6 +12,7 @@ #include +#include #include CreateWalletDialog::CreateWalletDialog(QWidget* parent) : @@ -94,9 +95,16 @@ CreateWalletDialog::CreateWalletDialog(QWidget* parent) : ui->external_signer_checkbox->setChecked(false); #endif -#ifndef USE_BDB - ui->descriptor_checkbox->setEnabled(false); - ui->descriptor_checkbox->setChecked(true); +#ifdef USE_BDB + connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); +#else + connect(ui->buttonBox, &QDialogButtonBox::accepted, [this]() { + if (!this->isDescriptorWalletChecked()) { + QMessageBox::critical(this, tr("Cannot create wallet"), tr("This build was compiled without BDB support, so only experimental descriptor wallets are supported.")); + return; + } + this->accept(); + }); #endif #ifndef ENABLE_EXTERNAL_SIGNER