Skip to content

Commit 4da0112

Browse files
committed
Merge bitcoin/bitcoin#30595: kernel: Introduce C header API
6c7a34f kernel: Add Purpose section to header documentation (TheCharlatan) 7e9f00b kernel: Allowing reducing exports (TheCharlatan) 7990463 kernel: Add pure kernel bitcoin-chainstate (TheCharlatan) 36ec9a3 Kernel: Add functions for working with outpoints (TheCharlatan) 5eec7fa kernel: Add block hash type and block tree utility functions to C header (TheCharlatan) f5d5d12 kernel: Add function to read block undo data from disk to C header (TheCharlatan) 09d0f62 kernel: Add functions to read block from disk to C header (TheCharlatan) a263a4c kernel: Add function for copying block data to C header (TheCharlatan) b30e15f kernel: Add functions for the block validation state to C header (TheCharlatan) aa262da kernel: Add validation interface to C header (TheCharlatan) d27e277 kernel: Add interrupt function to C header (TheCharlatan) 1976b13 kernel: Add import blocks function to C header (TheCharlatan) a747ca1 kernel: Add chainstate load options for in-memory dbs in C header (TheCharlatan) 070e777 kernel: Add options for reindexing in C header (TheCharlatan) ad80abc kernel: Add block validation to C header (TheCharlatan) cb1590b kernel: Add chainstate loading when instantiating a ChainstateManager (TheCharlatan) e2c1bd3 kernel: Add chainstate manager option for setting worker threads (TheCharlatan) 65571c3 kernel: Add chainstate manager object to C header (TheCharlatan) c62f657 kernel: Add notifications context option to C header (TheCharlatan) 9e1bac4 kernel: Add chain params context option to C header (TheCharlatan) 337ea86 kernel: Add kernel library context object (TheCharlatan) 28d679b kernel: Add logging to kernel library C header (TheCharlatan) 2cf136d kernel: Introduce initial kernel C header API (TheCharlatan) Pull request description: This is a first attempt at introducing a C header for the libbitcoinkernel library that may be used by external applications for interfacing with Bitcoin Core's validation logic. It currently is limited to operations on blocks. This is a conscious choice, since it already offers a lot of powerful functionality, but sits just on the cusp of still being reviewable scope-wise while giving some pointers on how the rest of the API could look like. The current design was informed by the development of some tools using the C header: * A re-implementation (part of this pull request) of [bitcoin-chainstate](https://github.com/bitcoin/bitcoin/blob/master/src/bitcoin-chainstate.cpp). * A re-implementation of the python [block linearize](https://github.com/bitcoin/bitcoin/tree/master/contrib/linearize) scripts: https://github.com/TheCharlatan/bitcoin/tree/kernelLinearize * A silent payment scanner: https://github.com/josibake/silent-payments-scanner * An electrs index builder: https://github.com/josibake/electrs/commits/electrs-kernel-integration * A rust bitcoin node: https://github.com/TheCharlatan/kernel-node * A reindexer: https://github.com/TheCharlatan/bitcoin/tree/kernelApi_Reindexer The library has also been used by other developers already: * A historical block analysis tool: https://github.com/ismaelsadeeq/mining-analysis * A swiftsync hints generator: https://github.com/theStack/swiftsync-hints-gen * Fast script validation in floresta: vinteumorg/Floresta#456 * A swiftsync node implementation: https://github.com/2140-dev/swiftsync/tree/master/node Next to the C++ header also made available in this pull request, bindings for other languages are available here: * Rust: https://github.com/TheCharlatan/rust-bitcoinkernel * Python: https://github.com/stickies-v/py-bitcoinkernel * Go: https://github.com/stringintech/go-bitcoinkernel * Java: https://github.com/yuvicc/java-bitcoinkernel The rust bindings include unit and fuzz tests for the API. The header currently exposes logic for enabling the following functionality: * Feature-parity with the now deprecated libbitcoin-consensus * Optimized sha256 implementations that were not available to previous users of libbitcoin-consensus thanks to a static kernel context * Full support for logging as well as control over categories and severity * Feature parity with the existing experimental bitcoin-chainstate * Traversing the block index as well as using block index entries for reading block and undo data. * Running the chainstate in memory * Reindexing (both full and chainstate-only) * Interrupting long-running functions The pull request introduces a new kernel-only test binary that purely relies on the kernel C header and the C++ standard library. This is intentionally done to show its capabilities without relying on other code inside the project. This may be relaxed to include some of the existing utilities, or even be merged into the existing test suite. The complete docs for the API as well as some usage examples are hosted on [thecharlatan.ch/kernel-docs](https://thecharlatan.ch/kernel-docs/index.html). The docs are generated from the following repository (which also holds the examples): [github.com/TheCharlatan/kernel-docs](https://github.com/TheCharlatan/kernel-docs). #### How can I review this PR? Scrutinize the commit messages, run the tests, write your own little applications using the library, let your favorite code sanitizer loose on it, hook it up to your fuzzing infrastructure, profile the difference between the existing bitcoin-chainstate and the bitcoin-chainstate introduced here, be nitty on the documentation, police the C interface, opine on your own API design philosophy. To get a feeling for the API, read through the tests, or one of the examples. To configure this PR for making the shared library and the bitcoin-chainstate and test_kernel utilities available: ``` cmake -B build -DBUILD_KERNEL_LIB=ON -DBUILD_UTIL_CHAINSTATE=ON ``` Once compiled the library is part of the build artifacts that can be installed with: ``` cmake --install build ``` #### Why a C header (and not a C++ header) * Shipping a shared library with a C++ header is hard, because of name mangling and an unstable ABI. * Mature and well-supported tooling for integrating C exists for nearly every popular language. * C offers a reasonably stable ABI Also see bitcoin/bitcoin#30595 (comment). #### What about versioning? The header and library are still experimental and I would expect this to remain so for some time, so best not to worry about versioning yet. #### Potential future additions In future, the C header could be expanded to support (some of these have been roughly implemented): * Handling transactions, block headers, coins cache, utxo set, meta data, and the mempool * Adapters for an abstract coins store * Adapters for an abstract block store * Adapters for an abstract block tree store * Allocators and buffers for more efficient memory usage * An "[io-less](https://sans-io.readthedocs.io/how-to-sans-io.html)" interface * Hooks for an external mempool, or external policy rules #### Current drawbacks * For external applications to read the block index of an existing Bitcoin Core node, Bitcoin Core needs to shut down first, since leveldb does not support reading across multiple processes. Other than migrating away from leveldb, there does not seem to be a solution for this problem. Such a migration is implemented in #32427. * The fatal error handling through the notifications is awkward. This is partly improved through #29642. * Handling shared pointers in the interfaces is unfortunate. They make ownership and freeing of the resources fuzzy and poison the interfaces with additional types and complexity. However, they seem to be an artifact of the current code that interfaces with the validation engine. The validation engine itself does not seem to make extensive use of these shared pointers. * If multiple instances of the same type of objects are used, there is no mechanism for distinguishing the log messages produced by each of them. A potential solution is #30342. * The background leveldb compaction thread may not finish in time leading to a non-clean exit. There seems to be nothing we can do about this, outside of patching leveldb. ACKs for top commit: alexanderwiederin: re-ACK bitcoin/bitcoin@6c7a34f stringintech: re-ACK 6c7a34f laanwj: Code review ACK 6c7a34f ismaelsadeeq: reACK 6c7a34f 👾 fanquake: ACK 6c7a34f - soon we'll be running bitcoin (kernel) Tree-SHA512: ffe7d4581facb7017d06da8b685b81f4b5e4840576e878bb6845595021730eab808d8f9780ed0eb0d2b57f2647c85dcb36b6325180caaac469eaf339f7258030
2 parents 96614ff + 6c7a34f commit 4da0112

19 files changed

+5419
-273
lines changed

.github/ci-test-each-commit-exec.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ def main():
4242
"-DBUILD_BENCH=ON",
4343
"-DBUILD_FUZZ_BINARY=ON",
4444
"-DWITH_USDT=ON",
45+
"-DBUILD_KERNEL_LIB=ON",
46+
"-DBUILD_KERNEL_TEST=ON",
4547
"-DCMAKE_CXX_FLAGS=-Wno-error=unused-member-function",
4648
])
4749
run(["cmake", "--build", "build", "-j", str(num_procs)])

.github/workflows/ci.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ jobs:
205205
job-type: [standard, fuzz]
206206
include:
207207
- job-type: standard
208-
generate-options: '-DBUILD_GUI=ON -DWITH_ZMQ=ON -DBUILD_BENCH=ON -DWERROR=ON'
208+
generate-options: '-DBUILD_GUI=ON -DWITH_ZMQ=ON -DBUILD_BENCH=ON -DBUILD_KERNEL_LIB=ON -DBUILD_UTIL_CHAINSTATE=ON -DWERROR=ON'
209209
job-name: 'Windows native, VS 2022'
210210
- job-type: fuzz
211211
generate-options: '-DVCPKG_MANIFEST_NO_DEFAULT_FEATURES=ON -DVCPKG_MANIFEST_FEATURES="wallet" -DBUILD_GUI=OFF -DBUILD_FOR_FUZZING=ON -DWERROR=ON'
@@ -283,7 +283,7 @@ jobs:
283283
$exeName = $_.Name
284284
285285
# Skip as they currently do not have manifests
286-
if ($exeName -eq "fuzz.exe" -or $exeName -eq "bench_bitcoin.exe" -or $exeName -eq "test_bitcoin-qt.exe") {
286+
if ($exeName -eq "fuzz.exe" -or $exeName -eq "bench_bitcoin.exe" -or $exeName -eq "test_bitcoin-qt.exe" -or $exeName -eq "test_kernel.exe" -or $exeName -eq "bitcoin-chainstate.exe") {
287287
Write-Host "Skipping $exeName (no manifest present)"
288288
return
289289
}
@@ -310,6 +310,7 @@ jobs:
310310
BITCOINTX: '${{ github.workspace }}\build\bin\Release\bitcoin-tx.exe'
311311
BITCOINUTIL: '${{ github.workspace }}\build\bin\Release\bitcoin-util.exe'
312312
BITCOINWALLET: '${{ github.workspace }}\build\bin\Release\bitcoin-wallet.exe'
313+
BITCOINCHAINSTATE: '${{ github.workspace }}\build\bin\Release\bitcoin-chainstate.exe'
313314
TEST_RUNNER_EXTRA: ${{ github.event_name != 'pull_request' && '--extended' || '' }}
314315
run: py -3 test/functional/test_runner.py --jobs $NUMBER_OF_PROCESSORS --ci --quiet --tmpdirprefix="${RUNNER_TEMP}" --combinedlogslen=99999999 --timeout-factor=${TEST_RUNNER_TIMEOUT_FACTOR} ${TEST_RUNNER_EXTRA}
315316

@@ -402,7 +403,7 @@ jobs:
402403
$exeName = $_.Name
403404
404405
# Skip as they currently do not have manifests
405-
if ($exeName -eq "fuzz.exe" -or $exeName -eq "bench_bitcoin.exe") {
406+
if ($exeName -eq "fuzz.exe" -or $exeName -eq "bench_bitcoin.exe" -or $exeName -eq "test_kernel.exe") {
406407
Write-Host "Skipping $exeName (no manifest present)"
407408
return
408409
}

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ option(BUILD_UTIL "Build bitcoin-util executable." ${BUILD_TESTS})
105105

106106
option(BUILD_UTIL_CHAINSTATE "Build experimental bitcoin-chainstate executable." OFF)
107107
option(BUILD_KERNEL_LIB "Build experimental bitcoinkernel library." ${BUILD_UTIL_CHAINSTATE})
108+
option(BUILD_KERNEL_TEST "Build tests for the experimental bitcoinkernel library." ${BUILD_KERNEL_LIB})
108109

109110
option(ENABLE_WALLET "Enable wallet." ON)
110111
if(ENABLE_WALLET)
@@ -210,6 +211,7 @@ if(BUILD_FOR_FUZZING)
210211
set(BUILD_UTIL OFF)
211212
set(BUILD_UTIL_CHAINSTATE OFF)
212213
set(BUILD_KERNEL_LIB OFF)
214+
set(BUILD_KERNEL_TEST OFF)
213215
set(BUILD_WALLET_TOOL OFF)
214216
set(BUILD_GUI OFF)
215217
set(ENABLE_EXTERNAL_SIGNER OFF)
@@ -667,6 +669,7 @@ message(" bitcoin-util ........................ ${BUILD_UTIL}")
667669
message(" bitcoin-wallet ...................... ${BUILD_WALLET_TOOL}")
668670
message(" bitcoin-chainstate (experimental) ... ${BUILD_UTIL_CHAINSTATE}")
669671
message(" libbitcoinkernel (experimental) ..... ${BUILD_KERNEL_LIB}")
672+
message(" kernel-test (experimental) .......... ${BUILD_KERNEL_TEST}")
670673
message("Optional features:")
671674
message(" wallet support ...................... ${ENABLE_WALLET}")
672675
message(" external signer ..................... ${ENABLE_EXTERNAL_SIGNER}")

ci/test/00_setup_env_mac_cross.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ export XCODE_BUILD_ID=15A240d
1717
export RUN_UNIT_TESTS=false
1818
export RUN_FUNCTIONAL_TESTS=false
1919
export GOAL="deploy"
20-
export BITCOIN_CONFIG="-DBUILD_GUI=ON -DREDUCE_EXPORTS=ON"
20+
export BITCOIN_CONFIG="-DBUILD_GUI=ON -DBUILD_KERNEL_LIB=ON -DREDUCE_EXPORTS=ON"

ci/test/00_setup_env_mac_native.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export CONTAINER_NAME="ci_mac_native" # macos does not use a container, but the
1010
export PIP_PACKAGES="--break-system-packages pycapnp zmq"
1111
export GOAL="install deploy"
1212
export CMAKE_GENERATOR="Ninja"
13-
export BITCOIN_CONFIG="-DBUILD_GUI=ON -DWITH_ZMQ=ON -DREDUCE_EXPORTS=ON -DCMAKE_EXE_LINKER_FLAGS='-Wl,-stack_size -Wl,0x80000'"
13+
export BITCOIN_CONFIG="-DBUILD_GUI=ON -DWITH_ZMQ=ON -DBUILD_KERNEL_LIB=ON -DBUILD_UTIL_CHAINSTATE=ON -DBUILD_KERNEL_TEST=ON -DREDUCE_EXPORTS=ON -DCMAKE_EXE_LINKER_FLAGS='-Wl,-stack_size -Wl,0x80000'"
1414
export CI_OS_NAME="macos"
1515
export NO_DEPENDS=1
1616
export OSX_SDK=""

ci/test/00_setup_env_native_nowallet_libbitcoinkernel.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ export PACKAGES="python3-zmq python3-pip clang-17 llvm-17 libc++abi-17-dev libc+
1313
export PIP_PACKAGES="--break-system-packages pycapnp"
1414
export DEP_OPTS="NO_WALLET=1 CC=clang-17 CXX='clang++-17 -stdlib=libc++'"
1515
export GOAL="install"
16-
export BITCOIN_CONFIG="-DREDUCE_EXPORTS=ON -DBUILD_UTIL_CHAINSTATE=ON -DBUILD_KERNEL_LIB=ON -DBUILD_SHARED_LIBS=ON"
16+
export BITCOIN_CONFIG="-DREDUCE_EXPORTS=ON -DBUILD_UTIL_CHAINSTATE=ON -DBUILD_KERNEL_LIB=ON -DBUILD_KERNEL_TEST=ON -DBUILD_SHARED_LIBS=ON"

ci/test/00_setup_env_win64.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ export PACKAGES="g++-mingw-w64-x86-64-posix nsis"
1313
export RUN_UNIT_TESTS=false
1414
export RUN_FUNCTIONAL_TESTS=false
1515
export GOAL="deploy"
16-
export BITCOIN_CONFIG="-DREDUCE_EXPORTS=ON -DBUILD_GUI_TESTS=OFF \
16+
export BITCOIN_CONFIG="-DREDUCE_EXPORTS=ON -DBUILD_GUI_TESTS=OFF -DBUILD_KERNEL_LIB=ON -DBUILD_KERNEL_TEST=ON \
1717
-DCMAKE_CXX_FLAGS='-Wno-error=maybe-uninitialized'"

src/CMakeLists.txt

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -404,28 +404,30 @@ endif()
404404

405405
if(BUILD_KERNEL_LIB)
406406
add_subdirectory(kernel)
407-
endif()
408-
409-
if(BUILD_UTIL_CHAINSTATE)
410-
add_executable(bitcoin-chainstate
411-
bitcoin-chainstate.cpp
412-
)
413-
add_windows_application_manifest(bitcoin-chainstate)
414-
# TODO: The `SKIP_BUILD_RPATH` property setting can be deleted
415-
# in the future after reordering Guix script commands to
416-
# perform binary checks after the installation step.
417-
# Relevant discussions:
418-
# - https://github.com/hebasto/bitcoin/pull/236#issuecomment-2183120953
419-
# - https://github.com/bitcoin/bitcoin/pull/30312#issuecomment-2191235833
420-
set_target_properties(bitcoin-chainstate PROPERTIES
421-
SKIP_BUILD_RPATH OFF
422-
)
423-
target_link_libraries(bitcoin-chainstate
424-
PRIVATE
425-
core_interface
426-
bitcoinkernel
427-
)
428-
install_binary_component(bitcoin-chainstate INTERNAL)
407+
if (BUILD_KERNEL_TEST)
408+
add_subdirectory(test/kernel)
409+
endif()
410+
if(BUILD_UTIL_CHAINSTATE)
411+
add_executable(bitcoin-chainstate
412+
bitcoin-chainstate.cpp
413+
)
414+
add_windows_application_manifest(bitcoin-chainstate)
415+
# TODO: The `SKIP_BUILD_RPATH` property setting can be deleted
416+
# in the future after reordering Guix script commands to
417+
# perform binary checks after the installation step.
418+
# Relevant discussions:
419+
# - https://github.com/hebasto/bitcoin/pull/236#issuecomment-2183120953
420+
# - https://github.com/bitcoin/bitcoin/pull/30312#issuecomment-2191235833
421+
set_target_properties(bitcoin-chainstate PROPERTIES
422+
SKIP_BUILD_RPATH OFF
423+
)
424+
target_link_libraries(bitcoin-chainstate
425+
PRIVATE
426+
core_interface
427+
bitcoinkernel
428+
)
429+
install_binary_component(bitcoin-chainstate INTERNAL)
430+
endif()
429431
endif()
430432

431433

0 commit comments

Comments
 (0)