Skip to content

Commit 9da53fc

Browse files
committed
support linking against system-installed leveldb and libsecp256k1
- Abort if runtime leveldb != compiled-against leveldb. Originally based on 22.0-fix_build_without_leveldb.patch.
1 parent 67b1e23 commit 9da53fc

File tree

6 files changed

+118
-2
lines changed

6 files changed

+118
-2
lines changed

CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#
88
# Centos Stream 9, EOL in May 2027:
99
# - CMake 3.26.5, https://mirror.stream.centos.org/9-stream/AppStream/x86_64/os/Packages/
10-
cmake_minimum_required(VERSION 3.22)
10+
cmake_minimum_required(VERSION 3.25)
1111
if(POLICY CMP0141)
1212
# MSVC debug information format flags are selected by an abstraction.
1313
# We want to use the CMAKE_MSVC_DEBUG_INFORMATION_FORMAT variable
@@ -176,6 +176,10 @@ if(WITH_MULTIPROCESS)
176176
)
177177
endif()
178178

179+
cmake_dependent_option(WITH_SYSTEM_LEVELDB "Link with system-installed LevelDB." OFF "ENABLE_WALLET" OFF)
180+
option(WITH_SYSTEM_LIBSECP256K1 "Link with system-installed libsecp256k1." OFF)
181+
mark_as_advanced(WITH_SYSTEM_LEVELDB WITH_SYSTEM_LIBSECP256K1)
182+
179183
cmake_dependent_option(BUILD_GUI_TESTS "Build test_bitcoin-qt executable." ON "BUILD_GUI;BUILD_TESTS" OFF)
180184
if(BUILD_GUI)
181185
set(qt_components Core Gui Widgets LinguistTools)

cmake/leveldb.cmake

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,36 @@
66
# support has been merged we should switch to using the upstream CMake
77
# buildsystem.
88

9+
if(WITH_SYSTEM_LEVELDB)
10+
11+
find_library(LevelDB_LIBRARY leveldb REQUIRED)
12+
find_library(LevelDB_MemEnv_LIBRARY memenv)
13+
add_library(leveldb SHARED IMPORTED)
14+
set_target_properties(leveldb PROPERTIES IMPORTED_LOCATION "${LevelDB_LIBRARY}")
15+
if(LevelDB_MemEnv_LIBRARY)
16+
target_link_libraries(leveldb
17+
INTERFACE
18+
"${LevelDB_MemEnv_LIBRARY}"
19+
)
20+
endif()
21+
block()
22+
list(APPEND CMAKE_REQUIRED_LIBRARIES leveldb)
23+
include(CheckSourceCompiles)
24+
check_source_compiles(CXX "
25+
#include <leveldb/env.h>
26+
#include <leveldb/helpers/memenv.h>
27+
int main() {
28+
leveldb::Env *myenv = leveldb::NewMemEnv(leveldb::Env::Default());
29+
delete myenv;
30+
}
31+
" LEVELDB_HAS_MEMENV)
32+
if(NOT LEVELDB_HAS_MEMENV)
33+
message(FATAL_ERROR "System-installed LevelDB lacks required MemEnv component.")
34+
endif()
35+
endblock()
36+
37+
else() # !WITH_SYSTEM_LEVELDB
38+
939
include(CheckCXXSymbolExists)
1040
check_cxx_symbol_exists(F_FULLFSYNC "fcntl.h" HAVE_FULLFSYNC)
1141

@@ -103,3 +133,10 @@ target_link_libraries(leveldb PRIVATE
103133
set_target_properties(leveldb PROPERTIES
104134
EXPORT_COMPILE_COMMANDS OFF
105135
)
136+
137+
endif() # !WITH_SYSTEM_LEVELDB
138+
139+
target_compile_definitions(leveldb
140+
INTERFACE
141+
EMBEDDED_LEVELDB=$<NOT:$<BOOL:${WITH_SYSTEM_LEVELDB}>>
142+
)

src/CMakeLists.txt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,43 @@ if(WITH_MULTIPROCESS)
3838
add_subdirectory(ipc)
3939
endif()
4040

41+
if(WITH_SYSTEM_LIBSECP256K1)
42+
43+
find_package(PkgConfig REQUIRED)
44+
pkg_check_modules(libsecp256k1 REQUIRED IMPORTED_TARGET libsecp256k1)
45+
add_library(secp256k1 ALIAS PkgConfig::libsecp256k1)
46+
block()
47+
string(APPEND CMAKE_REQUIRED_FLAGS " ${libsecp256k1_CFLAGS_OTHER}")
48+
list(APPEND CMAKE_REQUIRED_INCLUDES ${libsecp256k1_INCLUDE_DIRS})
49+
list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${libsecp256k1_LDFLAGS})
50+
list(APPEND CMAKE_REQUIRED_LIBRARIES ${libsecp256k1_LIBRARIES})
51+
unset(missing_modules)
52+
include(CheckSymbolExists)
53+
macro(check_secp256k1_module module symbol)
54+
string(TOUPPER "${symbol}" VAR)
55+
set(VAR "libsecp256k1_HAS_${VAR}")
56+
unset(${VAR})
57+
check_symbol_exists("${symbol}" "secp256k1_${module}.h" ${VAR})
58+
if(NOT ${VAR})
59+
list(APPEND missing_modules "${module}")
60+
endif()
61+
endmacro()
62+
message(CHECK_START "Checking for required libsecp256k1 modules")
63+
list(APPEND CMAKE_MESSAGE_INDENT " ")
64+
check_secp256k1_module(ellswift secp256k1_ellswift_encode)
65+
check_secp256k1_module(extrakeys secp256k1_xonly_pubkey_parse)
66+
check_secp256k1_module(recovery secp256k1_ecdsa_recover)
67+
check_secp256k1_module(schnorrsig secp256k1_schnorrsig_verify)
68+
list(POP_BACK CMAKE_MESSAGE_INDENT)
69+
if(missing_modules)
70+
list(JOIN missing_modules ", " missing_modules)
71+
message(FATAL_ERROR "System-installed libsecp256k1 lacks these required modules: ${missing_modules}.")
72+
endif()
73+
message(CHECK_PASS "all were found")
74+
endblock()
75+
76+
else() # !WITH_SYSTEM_LIBSECP256K1
77+
4178
#=============================
4279
# secp256k1 subtree
4380
#=============================
@@ -75,6 +112,8 @@ add_subdirectory(secp256k1)
75112
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
76113
string(APPEND CMAKE_C_COMPILE_OBJECT " ${APPEND_CPPFLAGS} ${APPEND_CFLAGS}")
77114

115+
endif() # !WITH_SYSTEM_LIBSECP256K1
116+
78117
# Stable, backwards-compatible consensus functionality.
79118
add_library(bitcoin_consensus STATIC EXCLUDE_FROM_ALL
80119
arith_uint256.cpp

src/dbwrapper.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@
2222
#include <leveldb/db.h>
2323
#include <leveldb/env.h>
2424
#include <leveldb/filter_policy.h>
25-
#include <leveldb/helpers/memenv/memenv.h>
25+
#if EMBEDDED_LEVELDB
26+
# include <leveldb/helpers/memenv/memenv.h>
27+
#else
28+
# include <leveldb/helpers/memenv.h>
29+
#endif
2630
#include <leveldb/iterator.h>
2731
#include <leveldb/options.h>
2832
#include <leveldb/slice.h>
@@ -51,6 +55,29 @@ static void HandleError(const leveldb::Status& status)
5155
throw dbwrapper_error(errmsg);
5256
}
5357

58+
#if EMBEDDED_LEVELDB
59+
bool dbwrapper_SanityCheck() { return true; }
60+
#else
61+
#include <node/interface_ui.h>
62+
#include <util/translation.h>
63+
#include <leveldb/c.h>
64+
bool dbwrapper_SanityCheck()
65+
{
66+
unsigned long header_version = (leveldb::kMajorVersion << 16) | leveldb::kMinorVersion;
67+
unsigned long library_version = (leveldb_major_version() << 16) | leveldb_minor_version();
68+
69+
if (header_version != library_version) {
70+
InitError(Untranslated(strprintf("Compiled with LevelDB %d.%d, but linked with LevelDB %d.%d (incompatible).",
71+
leveldb::kMajorVersion, leveldb::kMinorVersion,
72+
leveldb_major_version(), leveldb_minor_version()
73+
)));
74+
return false;
75+
}
76+
77+
return true;
78+
}
79+
#endif
80+
5481
class CBitcoinLevelDBLogger : public leveldb::Logger {
5582
public:
5683
// This code is adapted from posix_logger.h, which is why it is using vsprintf.

src/dbwrapper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ struct DBParams {
4646
DBOptions options{};
4747
};
4848

49+
bool dbwrapper_SanityCheck();
50+
4951
class dbwrapper_error : public std::runtime_error
5052
{
5153
public:

src/kernel/checks.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <kernel/checks.h>
66

7+
#include <dbwrapper.h>
78
#include <random.h>
89
#include <util/result.h>
910
#include <util/translation.h>
@@ -14,6 +15,12 @@ namespace kernel {
1415

1516
util::Result<void> SanityChecks(const Context&)
1617
{
18+
#if !EMBEDDED_LEVELDB
19+
if (!dbwrapper_SanityCheck()) {
20+
return util::Error{Untranslated("Database sanity check failure. Aborting.")};
21+
}
22+
#endif
23+
1724
if (!Random_SanityCheck()) {
1825
return util::Error{Untranslated("OS cryptographic RNG sanity check failure. Aborting.")};
1926
}

0 commit comments

Comments
 (0)