From f93e7c0e10daccc8e5c03b9cb67d2d454b295c37 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Mon, 9 Mar 2015 18:35:15 +0000 Subject: [PATCH 1/6] configure: BITCOIN_SUBDIR_TO_INCLUDE: Improve compatibility with paths including space and multiline cpp output --- build-aux/m4/bitcoin_subdir_to_include.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-aux/m4/bitcoin_subdir_to_include.m4 b/build-aux/m4/bitcoin_subdir_to_include.m4 index 736270afea..3a9b08a882 100644 --- a/build-aux/m4/bitcoin_subdir_to_include.m4 +++ b/build-aux/m4/bitcoin_subdir_to_include.m4 @@ -9,7 +9,7 @@ AC_DEFUN([BITCOIN_SUBDIR_TO_INCLUDE],[ AC_MSG_RESULT([default]) else echo "#include <$2$3.h>" >conftest.cpp - newinclpath=`${CXXCPP} ${CPPFLAGS} -M conftest.cpp 2>/dev/null | [ tr -d '\\n\\r\\\\' | sed -e 's/^.*[[:space:]:]\(\/[^[:space:]]*\)]$3[\.h[[:space:]].*$/\1/' -e t -e d`] + newinclpath=$(${CXXCPP} ${CPPFLAGS} -M conftest.cpp 2>/dev/null | sed [-E -e ':a' -e '/\\$/!b b' -e N -e 's/\\\n/ /' -e 't a' -e ':b' -e 's/^[^:]*:[[:space:]]*(([^[:space:]\]|\\.)*[[:space:]])*(([^[:space:]\]|\\.)*)]$3\.h[([[:space:]].*)?$/\3/' -e 't' -e d]) AC_MSG_RESULT([${newinclpath}]) if test "${newinclpath}" != ""; then eval "$1=\"\$$1\"' -I${newinclpath}'" From 1490995c122d5fd2ba66eccca2ec51fdc3bbf6d5 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 8 Jun 2016 21:40:25 +0000 Subject: [PATCH 2/6] BITCOIN_SUBDIR_TO_INCLUDE: Improve compatibility further, and reformat to be more readable --- build-aux/m4/bitcoin_subdir_to_include.m4 | 42 ++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/build-aux/m4/bitcoin_subdir_to_include.m4 b/build-aux/m4/bitcoin_subdir_to_include.m4 index 3a9b08a882..4e38d26d39 100644 --- a/build-aux/m4/bitcoin_subdir_to_include.m4 +++ b/build-aux/m4/bitcoin_subdir_to_include.m4 @@ -5,14 +5,48 @@ dnl file COPYING or http://www.opensource.org/licenses/mit-license.php. dnl BITCOIN_SUBDIR_TO_INCLUDE([CPPFLAGS-VARIABLE-NAME],[SUBDIRECTORY-NAME],[HEADER-FILE]) dnl SUBDIRECTORY-NAME must end with a path separator AC_DEFUN([BITCOIN_SUBDIR_TO_INCLUDE],[ - if test "$2" = ""; then + m4_pushdef([_result_var],[$1]) + m4_pushdef([_rel_path],[$2]) + m4_pushdef([_header_file],[$3.h]) + if test "[]_rel_path" = ""; then AC_MSG_RESULT([default]) else - echo "#include <$2$3.h>" >conftest.cpp - newinclpath=$(${CXXCPP} ${CPPFLAGS} -M conftest.cpp 2>/dev/null | sed [-E -e ':a' -e '/\\$/!b b' -e N -e 's/\\\n/ /' -e 't a' -e ':b' -e 's/^[^:]*:[[:space:]]*(([^[:space:]\]|\\.)*[[:space:]])*(([^[:space:]\]|\\.)*)]$3\.h[([[:space:]].*)?$/\3/' -e 't' -e d]) + echo '[#]include <'"_rel_path"'/_header_file>' >conftest.cpp + newinclpath=$( + ${CXXCPP} ${CPPFLAGS} -M conftest.cpp 2>/dev/null | + ${SED} -E m4_bpatsubsts([[ + :build_line +# If the line doesn't end with a backslash, it is complete; go on to process it + /\\$/!b have_complete_line +# Otherwise, read the next line, and concatenate it to the current one with a space + N + s/\\\n/ / +# Then go back and check for a trailing backslash again. + t build_line + +# When we get here, we have the completed line, with all continuations collapsed. + :have_complete_line + s/^[^:]*:[[:space:]]*(([^[:space:]\]|\\.)*[[:space:]])*(([^[:space:]\]|\\.)*)(\\|\\\\|\/)?]]patsubst(]_header_file[,[\.],[\\.])[[([[:space:]].*)?$/\3/ +# ^^^^^^^ The Make line begins with a target (which we don't care about) +# ^^^^^^^^^^^^ Ignore any spaces following it +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Match any number of other dependencies +# ^^^^^^^^^^^^^^^^^^^^^^ Match any path components for our dependency; note this is reference 3, which we are replacing with +# ^^^^^^^^^^^^^ Accept the path ending in a backslash, a double-backslash (ie escaped), or a forward slash +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The filename must match exactly (periods are escaped, since a normal period matches any character in regex) +# ^^^^^^^^^^^^^^^^^ Filename must be followed by a space, but after that we don't care; we still need to match it all so it gets replaced, however +# Delete the line, but only if we failed to find the directory (t jumps past the d if we matched) + t + d +]],[ +\s*\(#.*\)?$],[],[ + \(.*\)],[ -e '\1']) +dnl ^^^^^^^^^^^^^^^^^^^^^^^ Deletes comments and processes sed expressions into -e arguments + ) + AC_MSG_RESULT([${newinclpath}]) if test "${newinclpath}" != ""; then - eval "$1=\"\$$1\"' -I${newinclpath}'" + eval "_result_var=\"\$_result_var\"' -I${newinclpath}'" fi fi + m4_popdef([_result_var],[_rel_path],[_header_file]) ]) From c63284965e80f912640aa261507011fe64a52e6c Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sun, 28 Aug 2022 21:53:24 +0000 Subject: [PATCH 3/6] Revert "Use more specific path when including `memenv.h` header" This reverts commit f3b5c1e4522f13060e9ace2913203e7a6b2eb2d1. --- src/Makefile.leveldb.include | 1 + src/dbwrapper.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile.leveldb.include b/src/Makefile.leveldb.include index bf14fe206b..066f8940c5 100644 --- a/src/Makefile.leveldb.include +++ b/src/Makefile.leveldb.include @@ -13,6 +13,7 @@ LIBMEMENV = $(LIBMEMENV_INT) LEVELDB_CPPFLAGS = LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include +LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/helpers/memenv LEVELDB_CPPFLAGS_INT = LEVELDB_CPPFLAGS_INT += -I$(srcdir)/leveldb diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index 2aade14ef4..fcd44e3dcb 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include From 0379e4c7f7622b83624c5aada2659de31bb42ac7 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Mon, 9 Sep 2013 03:06:17 +0000 Subject: [PATCH 4/6] configure: Add unsupported --with-system-leveldb configure flag --- configure.ac | 62 ++++++++++++++++++++++++++++++++++++ src/Makefile.am | 2 ++ src/Makefile.leveldb.include | 5 ++- 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index b5116922f9..c4bf857f1c 100644 --- a/configure.ac +++ b/configure.ac @@ -1289,6 +1289,68 @@ if test "$have_any_system" != "no"; then AC_DEFINE([HAVE_SYSTEM], [1], [Define to 1 if std::system or ::wsystem is available.]) fi +dnl Check for leveldb, only if explicitly requested +LEVELDB_CPPFLAGS= +LIBLEVELDB= +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] +) +if test x$system_leveldb != xno; then + 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$system_leveldb = xno]) +AC_SUBST(LEVELDB_CPPFLAGS) +AC_SUBST(LIBLEVELDB) +AC_SUBST(LIBMEMENV) + dnl SUPPRESSED_CPPFLAGS=SUPPRESS_WARNINGS([$SOME_CPPFLAGS]) dnl Replace -I with -isystem in $SOME_CPPFLAGS to suppress warnings from dnl headers from its include directories and return the result. diff --git a/src/Makefile.am b/src/Makefile.am index 1d7004ac86..00bf1a84f9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1104,8 +1104,10 @@ endif include Makefile.minisketch.include +if EMBEDDED_LEVELDB include Makefile.crc32c.include include Makefile.leveldb.include +endif include Makefile.test_util.include include Makefile.test_fuzz.include diff --git a/src/Makefile.leveldb.include b/src/Makefile.leveldb.include index 066f8940c5..1851afe9e1 100644 --- a/src/Makefile.leveldb.include +++ b/src/Makefile.leveldb.include @@ -8,10 +8,9 @@ LIBMEMENV_INT = leveldb/libmemenv.la noinst_LTLIBRARIES += $(LIBLEVELDB_INT) noinst_LTLIBRARIES += $(LIBMEMENV_INT) -LIBLEVELDB = $(LIBLEVELDB_INT) $(LIBCRC32C) -LIBMEMENV = $(LIBMEMENV_INT) +LIBLEVELDB += $(LIBLEVELDB_INT) $(LIBCRC32C) +LIBMEMENV += $(LIBMEMENV_INT) -LEVELDB_CPPFLAGS = LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/helpers/memenv From 9770213fca07e0d7a2581647409720e50c6e1b86 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 12 Jul 2018 20:00:47 +0000 Subject: [PATCH 5/6] init: Sanity check LevelDB build/runtime versions --- src/dbwrapper.cpp | 19 +++++++++++++++++++ src/dbwrapper.h | 2 ++ src/kernel/checks.cpp | 5 +++++ 3 files changed, 26 insertions(+) diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index fcd44e3dcb..4b722964a6 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -6,16 +6,19 @@ #include #include +#include #include #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -27,6 +30,22 @@ #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. diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 35782edca6..b5d009e245 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -28,6 +28,8 @@ namespace leveldb { class Env; } +bool dbwrapper_SanityCheck(); + static const size_t DBWRAPPER_PREALLOC_KEY_SIZE = 64; static const size_t DBWRAPPER_PREALLOC_VALUE_SIZE = 1024; diff --git a/src/kernel/checks.cpp b/src/kernel/checks.cpp index 4c303c172c..8cf8386850 100644 --- a/src/kernel/checks.cpp +++ b/src/kernel/checks.cpp @@ -4,6 +4,7 @@ #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."); } From 3937e4a03a626a40c9736a3d2015bc8ece166383 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 3 Nov 2021 00:32:16 +0000 Subject: [PATCH 6/6] Use internal LevelDB test interface to bump LevelDB mmap limit up to 4096 like Bitcoin Core's fork No-op for embedded, but still done anyway Not applicable to Windows or 32-bit systems --- src/dbwrapper.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index 4b722964a6..7f1ab02a1c 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -46,6 +46,26 @@ bool dbwrapper_SanityCheck() return true; } +#ifndef WIN32 +namespace leveldb { +class EnvPosixTestHelper { + static void SetReadOnlyMMapLimit(int limit); +public: + static inline void SetReadOnlyMMapLimitForBitcoin(int limit) { SetReadOnlyMMapLimit(limit); } +}; +} + +class BitcoinLevelDBInit { +public: + BitcoinLevelDBInit() { + if (sizeof(void*) >= 8) { + leveldb::EnvPosixTestHelper::SetReadOnlyMMapLimitForBitcoin(4096); + } + } +}; +static BitcoinLevelDBInit g_bitcoin_leveldb_init; +#endif + class CBitcoinLevelDBLogger : public leveldb::Logger { public: // This code is adapted from posix_logger.h, which is why it is using vsprintf.