Bitcoin full node and query server

October 2026

Archive of the libbitcoin Slack #general channel.

Thursday, October 1, 2026

evoskuil01:14
--version now loads the store (if present) to pull the schema version...
Database is started.
Version Information...
boost................ 1.91.0
secp256k1............ internal
openssl (tls)........ libbitcoin tls 1.3
libbitcoin-system.... 4.0.9996 952eb134
libbitcoin-database.. 4.0.4499 52fd956b
libbitcoin-network... 4.0.7173 48092f1e
libbitcoin-node...... 4.0.4100 43278b8b
libbitcoin-server.... 4.0.3086 f09be940
compiled schema...... 4.0.2
database schema...... 4.0.2
Please wait while database is stopping...
Database stopped successfully in 7 secs.
With both indexes on vs. both off, we are running about 47 minutes faster passing block 740k. I suspect this will widen as the utxo store starts to bite harder.
evoskuil01:24
This gap analysis shows it clearly. We raced ahead in the first few minutes, and Core was actually catching up after that, until it peaked and starting declining. Its design is optimized for the low end, but as blocks get big, and the utxo set gets big, that advantage disappears. The vertical line shows the point at which the cache hit the limit and it dumped the whole thing and started over cold. The sudden dip near 712k is a libbitcoin window step.
(edited)
image.png
evoskuil01:38
These errors that hit the log today in the meeting are actually excellent error handling:
2026-09-30T17:45:54Z.6 Failed to accept private native connection, tls alert certificate unknown
2026-09-30T17:45:54Z.6 Failed to accept private native connection, tls alert certificate unknown
2026-09-30T17:45:54Z.6 Failed to accept private native connection, tls alert certificate unknown
2026-09-30T17:45:54Z.6 Failed to accept private native connection, tls alert certificate unknown
2026-09-30T17:45:54Z.6 Failed to accept private native connection, tls alert certificate unknown
2026-09-30T17:45:54Z.6 Failed to accept private native connection, tls alert certificate unknown
The client is rejecting your certificate; the server isn't failing. Our server never sends certificate_unknown (46) itself. That error only appears when the peer sends a fatal alert during the handshake, which server::handle_alert (server.cpp:434) records as a received failure. So the browser got your certificate, checked it, decided not to trust it, and closed the handshake.
evoskuil01:51
Meeting follow-up: Yes, a static build linked against the ultrafast with Option-cuda=true will run on a machine with no GPU or no NVIDIA driver, and fall back to the CPU. So we can presumably make the binaries GPU portable at least for CUDA initially.
(edited)
evoskuil02:01
Meeting follow-up: we can build native windows builds in clang, should be easy to fix up any issues in the PP defines. Not much reason to apart from expanding the dev matrix. Also we could create Windows presets for building the VS projects in CMake, with a little work around dependencies.
Also forgot to mention, but @eynhaender will be happy to know that config files are now portable, as commas in integers now work (just commas, not localized).
😁 1
evoskuil08:32
At 807k bs is 112 minutes ahead, more than double the 52 minutes at 744k.
image.png
evoskuil09:10
At current rate of deceleration bc is projected to complete at 62.5 hrs, or +5.2 hrs longer than bs.
image.png
🎉 2
evoskuil09:44
image.png
evoskuil20:42
I'm really impressed with this prediction.
image.png
bc is now 3.5 hrs behind the bs pace, tracking closely to the +5 hr projection.
image.png
We now own full validation down to 16GB and milestone down to 8GB, even with tx index and spender index turned off in bc. And the bigger the machine, the greater the advantage. Wait until you see the compact blocks numbers :).
(edited)
🚀 1
evoskuil21:40
I've reduced the startup warning to sha (or crypto on Arm) and avx2. The rest still displays but won't pause the start or warn.
👍🏻 1👍 1

Friday, October 2, 2026

evoskuil01:47
Almost there... about 10% slower than bs.
(edited)
image.pngimage.png
evoskuil01:52
...and there's still so much more to optimize!
evoskuil15:30
Complete, next adding in bc "assume valid" on v32 rc2.
(edited)
image.png
evoskuil16:30
This is the culmination of about 2 months of posix mmap work and configuration measurement and tuning. Previously we were unable to validate on the Pi without thrashing hard and going parabolic. These results now hold across all platforms, above the memory floor, and require no manual configuration.
(edited)
💪 1
pmienk18:25
Release matrix:
  • releases in question are static binary bitcoin server (bs) executables.
  • platforms succeeding compilation:
  • macos-arm64
  • macos-intel
  • linux (ubuntu)
  • linux-arm64 (ubuntu-arm64)
  • windows (windows server 2025)
(edited)
  • Currently failing windows-arm64 due to missing boost dependencies
evoskuil18:28
presumably also libsecp
oh, we don't need that one 🙂
how soon i forget
pmienk18:28
yeah, not exercising that in release
evoskuil18:28
ok, kevin owns boost nuget.
(edited)
pmienk18:30
arm64 parameters:
  • <unparameterized>
  • --enable-crypto
  • --enable-sha3
x64 parameters:
  • --enable-avx2
  • --enable-avx512
  • --enable-shani
currently exercising multiplying all windows/x64 with --enable-cuda for compilation along with a test --enable-cuda variant for macos/linux/macos-arm64/linux-arm64
evoskuil18:33
crypto should be gone
that was changed to sha and aes
(edited)
pmienk18:34
another reason i want this matrix in codegen
evoskuil18:36
yeah, it's a lot. I'm not sure what we should do with aes (can we assume it on most machines). it's only for TLS optimization so safe bet is to leave it off.
pmienk18:36
-Denable-shani=<ON/OFF> Use Intel SHA Extensions. Default: OFF -Denable-sha512=<ON/OFF> Use Intel SHA512 Extensions (implies AVX2). Default: OFF -Denable-aesni=<ON/OFF> Use Intel AES-NI and PCLMULQDQ intrinsics. Default: OFF -Denable-vaes=<ON/OFF> Use Intel VAES and VPCLMULQDQ intrinsics (implies AES-NI and AVX2). Default: OFF -Denable-avx512ifma=<ON/OFF> Use Intel AVX512 IFMA intrinsics (implies AVX512VL). Default: OFF -Denable-avx512=<ON/OFF> Use Intel AVX512 intrinsics. Default: OFF -Denable-avxifma=<ON/OFF> Use Intel AVX IFMA intrinsics (implies AVX2). Default: OFF -Denable-avx2=<ON/OFF> Use Intel AVX2 intrinsics. Default: OFF -Denable-sse41=<ON/OFF> Use SSE4.1 hardware instructions. Default: OFF -Denable-sha=<ON/OFF> Use ARM SHA1/SHA256 Extensions. Default: OFF -Denable-sha3=<ON/OFF> Use ARM SHA3 Extensions for SHA512. Default: OFF -Denable-aes=<ON/OFF> Use ARM AES and PMULL Extensions. Default: OFF -Dwith-secp256k1=<ON/OFF> Use bitcoin-core/secp256k1 library. Default: OFF -Denable-cuda=<ON/OFF> Use cuda (gpu) batch signature verification.
evoskuil18:36
cuda can be on for all non-mac builds (really shouldn't be an option on mac).
pmienk18:37
looks like there's been some shift
evoskuil18:38
there was the crypto split for arm, to solve last night's issue, and then sorted to group arm and intel.
Just noticed this one is the only one without the arm/intel comment:
Use SSE4.1 hardware instructions.
pmienk18:40
so arm: sha/sha3/aes, everything proceeding is x64, correct?
(edited)
evoskuil18:41
yes
just that one missing comment
should be
Use Intel SSE4.1 hardware instructions.
pmienk18:42
and cuda - makes sense on all platforms? or is it nonsense on macos due to their own hardware?
evoskuil18:43
right, I'll remove it from mac config, but just in case set it off so it doesn't waste binary space with the IL. Others can be on. I've been waiting to change the default until I finish some runs today.
The gpu batch perf is good on high end, but our impl is slower than ufast still. so now I gotta tun it.
pmienk18:47
okay, so cuda variation on windows/linux/linux-arm64.
with arm, looks like aes is 15 years old, sha3 10yo, and practically anyting past 2021 supports all
👍🏻 1
evoskuil18:51
yes, but someone should actually run it with cuda on linux
pmienk18:52
to me, this looks like reducing arm to everything and everything + cuda if someone can verify that (1) works (2) is common enough to make sense
evoskuil18:52
wasn't that the issue we had last night, arm didn't have everything?
(edited)
pmienk18:53
in the testbed, it didn't have whatever was being represented as crypto while it did have sha3
evoskuil18:53
crypto is sha + aes
so maybe sha isn't as common as sha3?
pmienk18:55
clanker doesn't give me a historic introduction for 'sha'
sha -> sha1 then 2016
no, 2013
evoskuil18:56
sha is sha256 and sha1 (160)
pmienk18:56
might be an macos/generic arm schism
(edited)
evoskuil18:57
both for arm (our sha) and intel (shani) they come as a package
(edited)
pmienk18:58
the macos-latest (arm64) image gets this output:
boost................ 1.86.0
secp256k1............ internal
openssl (tls)........ libbitcoin tls 1.3
libbitcoin-system.... 4.0.10066 f89f1c56
libbitcoin-database.. 4.0.4508 f3378db9
libbitcoin-network... 4.0.7195 596e1957
libbitcoin-node...... 4.0.4117 dc2d2bfa
libbitcoin-server.... 4.0.3122 91bf6df9
compiled schema...... 4.0.2
Hardware configuration (arm64)...
crypto...... platform:0 compiled:1.
sha3........ platform:1 compiled:1.
neon........ platform:1 compiled:1.
cuda........ platform:0 compiled:1.
cuda ecc.... platform:0 enabled:0.
opencl...... platform:0.
metal....... platform:1.
evoskuil18:59
Yeah, I merged the split commits an hour ago.
pmienk18:59
funny, all i did there was --enable-cuda
it compiled crypto/sha3 without turning them on
this latest run of mine must have missed some changes splitting crypto out
evoskuil19:01
the presentation picks up compiled from the compiler defines.
pmienk19:01
so the platform makes the option moot
evoskuil19:02
no, the compiler defines are set because of the options.
it's different on windows, the compiler doesn't set anything for sha
pmienk19:03
so macos-latest compiled with --enable-cuda sets --enable-crypto/--enable-sha3?
evoskuil19:03
in the previous build, if you set both crypto and then sha3, you would get only sha3.
because they don't merge for arm, last writer wins.
that's why we had to split them.
but if you don't set either, you should get neither.
pmienk19:04
sure. I must have some intermediary bits then. its moot to try and explore the output but it's inconsistent with my understanding or this explanation currently. will refresh when the pulls in
evoskuil19:05
cuda doesn't set CPU flags, it's just a PP symbol we set to redirect sigs to gpu batching if we can load the library and if it's configured.
(edited)
I can't explain how you would get the crypto compiled bit set on --hardware if the flags aren't passed to the compiler.
seems necessary that it was set either inadvertently or due to some problem in the artifacts.
pmienk19:09
when the cmake output says the flag is off, i'm not sure where it's coming from. but if I'm in intermediate state I'd rather confirm good bits before exploring this further
evoskuil19:10
what does that show?
pmienk19:10
********************** Preparing to build libbitcoin-system **********************
Initializing 'obj'...
configure options:
-Dwith-tests:BOOL=OFF
-Dwith-examples:BOOL=OFF
-Denable-cuda=ON
-Dwith-tests=OFF
-DCMAKE_INSTALL_PREFIX=/Users/runner/work/libbitcoin-server/libbitcoin-server/prefix
-DCMAKE_PREFIX_PATH=/Users/runner/work/libbitcoin-server/libbitcoin-server/prefix
-DCMAKE_BUILD_TYPE=Release
-DBUILD_SHARED_LIBS=OFF
-- The C compiler identification is AppleClang 21.0.0.21000101
-- The CXX compiler identification is AppleClang 21.0.0.21000101
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/clang - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test HAS_FLAG_WALL
-- Performing Test HAS_FLAG_WALL - Success
-- Performing Test HAS_FLAG_WEXTRA
-- Performing Test HAS_FLAG_WEXTRA - Success
-- Performing Test HAS_FLAG_WNO-REORDER
-- Performing Test HAS_FLAG_WNO-REORDER - Success
-- Performing Test HAS_FLAG_WNO-MISSING-FIELD-INITIALIZERS
-- Performing Test HAS_FLAG_WNO-MISSING-FIELD-INITIALIZERS - Success
-- Performing Test HAS_FLAG_WNO-MISSING-BRACES
-- Performing Test HAS_FLAG_WNO-MISSING-BRACES - Success
-- Performing Test HAS_FLAG_WNO-COMMENT
-- Performing Test HAS_FLAG_WNO-COMMENT - Success
-- Performing Test HAS_FLAG_WNO-DEPRECATED-COPY
-- Performing Test HAS_FLAG_WNO-DEPRECATED-COPY - Success
-- Performing Test HAS_FLAG_WNO-IGNORED-ATTRIBUTES
-- Performing Test HAS_FLAG_WNO-IGNORED-ATTRIBUTES - Success
-- Performing Test HAS_FLAG_WNO-LONG-LONG
-- Performing Test HAS_FLAG_WNO-LONG-LONG - Success
-- Performing Test HAS_FLAG_FSTACK-PROTECTOR-ALL
-- Performing Test HAS_FLAG_FSTACK-PROTECTOR-ALL - Success
-- Configuring done (4.0s)
-- Generating done (0.1s)
-- Build files have been written to: /Users/runner/work/libbitcoin-server/libbitcoin-server/libbitcoin-system/obj
-- Cache values
Boost_DIR:PATH=/Users/runner/work/libbitcoin-server/libbitcoin-server/prefix/lib/cmake/Boost-1.86.0
CMAKE_ADDR2LINE:FILEPATH=CMAKE_ADDR2LINE-NOTFOUND
CMAKE_AR:FILEPATH=/usr/bin/ar
CMAKE_BUILD_TYPE:STRING=Release
CMAKE_COLOR_MAKEFILE:BOOL=ON
CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/clang++
CMAKE_CXX_FLAGS:STRING=-O3
CMAKE_CXX_FLAGS_DEBUG:STRING=-g
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
CMAKE_C_COMPILER:FILEPATH=/usr/bin/clang
CMAKE_C_FLAGS:STRING=-O3
CMAKE_C_FLAGS_DEBUG:STRING=-g
CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND
CMAKE_EXE_LINKER_FLAGS:STRING=
CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=
CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=
CMAKE_INSTALL_BINDIR:PATH=bin
CMAKE_INSTALL_DATADIR:PATH=
CMAKE_INSTALL_DATAROOTDIR:PATH=share
CMAKE_INSTALL_DOCDIR:PATH=
CMAKE_INSTALL_INCLUDEDIR:PATH=include
CMAKE_INSTALL_INFODIR:PATH=
CMAKE_INSTALL_LIBDIR:PATH=lib
CMAKE_INSTALL_LIBEXECDIR:PATH=libexec
CMAKE_INSTALL_LOCALEDIR:PATH=
CMAKE_INSTALL_LOCALSTATEDIR:PATH=var
CMAKE_INSTALL_MANDIR:PATH=
CMAKE_INSTALL_NAME_TOOL:FILEPATH=/usr/bin/install_name_tool
CMAKE_INSTALL_OLDINCLUDEDIR:PATH=/usr/include
CMAKE_INSTALL_PREFIX:PATH=/Users/runner/work/libbitcoin-server/libbitcoin-server/prefix
CMAKE_INSTALL_RUNSTATEDIR:PATH=
CMAKE_INSTALL_SBINDIR:PATH=sbin
CMAKE_INSTALL_SHAREDSTATEDIR:PATH=com
CMAKE_INSTALL_SYSCONFDIR:PATH=etc
CMAKE_LINKER:FILEPATH=/usr/bin/ld
CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make
CMAKE_MODULE_LINKER_FLAGS:STRING=
CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=
CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
CMAKE_NM:FILEPATH=/usr/bin/nm
CMAKE_OBJCOPY:FILEPATH=CMAKE_OBJCOPY-NOTFOUND
CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump
CMAKE_OSX_ARCHITECTURES:STRING=
CMAKE_OSX_DEPLOYMENT_TARGET:STRING=
CMAKE_OSX_SYSROOT:STRING=
CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib
CMAKE_READELF:FILEPATH=CMAKE_READELF-NOTFOUND
CMAKE_SHARED_LINKER_FLAGS:STRING=
CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=
CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=
CMAKE_SKIP_INSTALL_RPATH:BOOL=NO
CMAKE_SKIP_RPATH:BOOL=NO
CMAKE_STATIC_LINKER_FLAGS:STRING=
CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING=
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING=
CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING=
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING=
CMAKE_STRIP:FILEPATH=/usr/bin/strip
CMAKE_TAPI:FILEPATH=/Applications/Xcode_26.6.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/tapi
CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE
GIT_EXECUTABLE:FILEPATH=/opt/homebrew/bin/git
boost_container_DIR:PATH=/Users/runner/work/libbitcoin-server/libbitcoin-server/prefix/lib/cmake/boost_container-1.86.0
boost_headers_DIR:PATH=/Users/runner/work/libbitcoin-server/libbitcoin-server/prefix/lib/cmake/boost_headers-1.86.0
boost_json_DIR:PATH=/Users/runner/work/libbitcoin-server/libbitcoin-server/prefix/lib/cmake/boost_json-1.86.0
boost_program_options_DIR:PATH=/Users/runner/work/libbitcoin-server/libbitcoin-server/prefix/lib/cmake/boost_program_options-1.86.0
boost_unit_test_framework_DIR:PATH=/Users/runner/work/libbitcoin-server/libbitcoin-server/prefix/lib/cmake/boost_unit_test_framework-1.86.0
boost_url_DIR:PATH=/Users/runner/work/libbitcoin-server/libbitcoin-server/prefix/lib/cmake/boost_url-1.86.0
enable-aes:BOOL=OFF
enable-aesni:BOOL=OFF
enable-avx2:BOOL=OFF
enable-avx512:BOOL=OFF
enable-avx512ifma:BOOL=OFF
enable-avxifma:BOOL=OFF
enable-cuda:BOOL=ON
enable-sha:BOOL=OFF
enable-sha3:BOOL=OFF
enable-sha512:BOOL=OFF
enable-shani:BOOL=OFF
enable-sse41:BOOL=OFF
enable-vaes:BOOL=OFF
with-examples:BOOL=OFF
with-secp256k1:BOOL=OFF
with-tests:BOOL=OFF
cmake thinks enable-sha/sha3 off
the resulting binary thinks sha3 is compiled in
evoskuil19:11
that's a later build right?
there's no crypto option in there, so it's nto the same build as the cl output.
I changed them together.
pmienk19:13
your changing them didn't change the parameterization i passed to the installer - I sent a dead --enable-crypto, but there may well be an issue with -server not having taken updated bits and so having crypto listed in output.
either that, or whatever output changes were made weren't done in concert with regenerated build artifacts
either way, sha3 with no parameterization shouldn't be expected. but I'll clean up the version snapshot to eliminate these concerns
evoskuil19:15
server updated them in the same pr together, but -build was earlier.
yeah, it's no longer a moving target. but there's no good way to test this stuff broadly, so certainly could still be issues.
pmienk19:16
i gotta assume changes made it to -system instead of -server to deal with the parameterization, but i don't know about presentation
so easily could be a -system/-server mismatch
evoskuil19:18
I merged system within a few minutes of server, but yes they need to be in sync. if you passed crypto to old system, it would have set crypto as compiled, and new server would see that as aes + sha, and old server would see it as crypto. but if nothing was passed then I see no way for either to show compiled, in either case.
(edited)
pmienk19:19
given the output, it was a new system, but could have been old server
evoskuil19:19
right, has to be old server (> 1 hr ago)
pmienk19:20
these builds take about 2 hours to run and had just completed when I decided to try and hammer down the matrix here. i'm updating repos
evoskuil19:23
I promise no more config work! things that are open:
  • remove or ignore cuda option on macOS (I will ignore it in the PP defines).
  • change cuda default to on (once it looks solid).
The big change was the Arm sha/aes/sha3 composition (necessary because Arm doesn't compose like intel).
(edited)
pmienk19:28
i guess the question comes down to what of those are supported on >10yo mac-arm64 hardware
having not touched a mac in 13 years, i have no clue what they've got going on
evoskuil19:31
my super intel mac which is 5yo has maybe aes, not sha/sha3
pmienk19:31
thought that was intel, not arm64
evoskuil19:32
yeah, dunno. I think prob the one thing we can't assume is any type of sha.
and the only one we really need is sha/shani
(edited)
and that's more important for Arm, due to lack of AVX2/512
we can generally assume avx2 (and sse4/neon). we might be able to assume sha (arm). that's the one that's really worth tracking down.
pmienk19:35
according to grok, sha1/sha256 was introduced in 2013-2014 in apple hardware, 2016 in ARMv8.2-A
evoskuil19:36
what matters more is whether they kept shipping hardware without it
pmienk19:37
some pi5's dont have it
looks like at least 1 underpowered variant in 3/4/5s
so they're still kicking them out of factories as of today
evoskuil19:41
Dont' they know everyone runs a node??
Vano Chkheidze21:22
image.png
on cuda
evoskuil21:23
what are the column titles?
Vano Chkheidze21:24
before and now
ecsdsa verify 60% faster now
on gpu
shnor 15%
evoskuil21:24
batch or single? ah gpu
(edited)
Vano Chkheidze21:25
cpu i will try same later if i increase it
👍🏻 1
evoskuil22:40
I've updated the --settings dump so that default values in the message text are derived from the actual values at the time of the parse.

Saturday, October 3, 2026

evoskuil15:41
Bitcoin Core 32.0rc2 is running on the Pi5 (Jennings). There was work in this version (not in the current release which I previously ran) to "prefetch" utxos for the one block currently being validated, using a persistent threadpool that grabs from LevelDB utxos that would be a cache miss upon validation hitting the utxo store. This has been advertised as a significant performance increase, which I don't think will hold up.
image.png
evoskuil16:05
Notice there is a sweet spot for dbcache. A formerly optimal 10GB (which we used in the last run) is no longer optimal. So I've reduced the config back to the default for this run. So there is less RAM consumed by in-memory utxo state but more time spent hitting the disk. The threadpool defaults to 8 (always) but that would very likely be too high for Jennings, a 4 thread machine, and they only reported 8-16 thread machines. The threadpool shares CPU with validation, and validation already runs at 100% CPU inside a block. While a naive look at CPU would show ~92% overall, this is an average of low CPU between blocks and nearly 100% CPU within blocks. So there's nothing to recover when the blocks are too small to max out CPU on script validation. And in those cases there's also not much to gain. The performance loss from sequential validation is in the time between blocks, including the ramp up and down of work dispatch within each block. That can't be recovered by creating a secondary dispatch of work within the block. It's work that each validator thread can just do on its own, with the same outcome and less complexity and less pool overhead. We don't do any parallelization within a block, that's far too granular of a dispatch, which would result in a lot of avoidable marshalling overhead. We just dispatch each block on its own thread, populate the prevouts of the entire block internal to the validation, and validate the whole block. We do dispatch the prevout population on a c++ parallel loop, but that doesn't compete with the block validation, it precedes it sequentially. It's the blocks validating concurrently that fill the gaps in the sawtooth CPU plot, allowing 100% actual utilization. The sweet spot scenario that this optimization provides is for a machine with high thread count and low memory. With high memory there is no benefit from the parallel disk reads (a deduction confirmed by their own numbers). The marshalling cost eats up the benefit of the small number of cache misses. And with low thread count the prefetch just competes with the validator. So there's no improvement in scalability and no benefit at the low end, which I expect we'll measure.
(edited)
evoskuil17:11
In other news, shelly hit 71 mins full validation to 950k on its native secp256k1 and cuda integration. The previous record is 63 mins from late July. The latest code has a small additional cost for header DoS protection, some changes to mmap, slightly different hashmap load factor configuration, and an outs table increased by 15GB (for address indexing, even when the index/head is off). Our validation is actually faster, the difference is resulting from the 15GB of extra writes. So I'll optimize out that column when it's not being used. I set address index off for this run to get the fair comparison against the record run, which pre-dates the address index optimization into the outs table.
1 reply · evoskuil · last Oct 03, 2026
evoskuil17:20
Optimizations to the node's signature capture brought the batched evaluation rate up to the full capture rate. Formerly we would validate inline while batching was processing. This was better than waiting on the validation, but not as good as capturing while validating the last capture. So I added double-buffering, which creates a second set of signature batching tables. So now we batch validate all captures, and the capture rate against all sigs is ~99.5%. Interestingly this didn't reduce the wall time for the full validation run, it was almost identical to the batch leakage of around 8%. But it eliminated all of the CPU time spent validating that 8% of all signatures. On a lower CPU machine that becomes wall time.
evoskuil17:31
Behind at every point through the first 300k blocks. There's little to gain in that range (empty/small blocks) and the overhead is a cost.
image.png

Sunday, October 4, 2026

evoskuil05:41
Doing a little better than bc v31.1 (-1.4%), and still +7.8% vs. bs.
image.pngimage.png
evoskuil18:26
image.png

Monday, October 5, 2026

evoskuil02:50
Today we got secp constant time everywhere a secret is touched on the CPU — scan key, tweaks, nonces, secrets, shared secrets — at the cost above; verify unchanged; GPU explicitly exempt (server scanning scenario). github.com/libbitcoin/libbitcoin-system/pull/2069
🎉 2
evoskuil03:08
Also added memory safety for ephemeral secrets a couple days ago. Config secrets are held for process lifetime.
(edited)
evoskuil03:17
Today we also got compact blocks finally reviewed, tested and merged - though I haven't spent any time with it in operation.
evoskuil03:22
Today we also got silent payments fully integrated. @josie’s system PR for all of the necessary primitives went in, the tables and most of the sparrow (frigate) interface were done a while back. Now that the secp/cuda stuff is fully integrated, it was easy to integrate and optimize the scanning. Blazing fast on single thread CPU at 71,500 rows/sec, (using avx512-ifma acceleration). And on GPU at 27,500,000 rows/sec.
(edited)
🎉 2
evoskuil03:33
This is all of SP scan table entries being generated for a window during a milestone run. It's similar to validation and client filters, in that during the same phase the populated block and all prevouts are used to generate the table. All three of these will get faster with the view-based blocks (coming soon). There are CPU gaps, as in validation, as the contiguous set of blocks fills in and the downloads tail off at the end of each window.
(edited)
image.pngimage.png
evoskuil03:47
That's the last work in progress row of the v4 interface sheet marked off.
image.png
Should be updated live soon. libbitcoin.info
libbitcoin
A Bitcoin full node and query server. One node that speaks the protocols your software already uses.
evoskuil07:17
First full (not fully optimized) SP indexation added 21 minutes to the 950k baseline milestone time of 25 minutes, so 46 mins total. A big part of that is I/O, which will be largely eliminated with the block view read optimization, which will also benefit full validation and client filters.
evoskuil07:32
First SP query (ever) ... The sparrow service answered on the first connection, so the node is current and the service is live:
  • handshake server.version returned sparrow-server 1.4
  • blockchain.silentpayments.subscribe accepted the BIP352 test-vector scan secret and spend key, echoing the sp1 address with start height 0 and label 0
  • the full scan of the index completed 19 seconds later with progress 1.0 and an empty history
Empty is the expected result for the test-vector keys, which have no mainnet payments. The scan covered the full silent table, about 350M rows from the previous store's count, so that is roughly 18M rows per second end to end on shelly's device, in line with the earlier 14 second scan on the pre-gate store. To verify a positive match the service needs a key pair with a known mainnet silent payment. If you have a test receiver, pass its scan secret and spend key to the same script and it will print the history entries. Second SP query (warm)... The subscribe reply and the completion notification are identical to the first scan. The halving is the silent table being resident after the first pass, so 9 seconds is the device-bound figure for the full index on shelly and 19 seconds included paging the columns in. Third SP query (verify)... Third scan: 9 seconds again, empty history, same reply. The warm figure is stable at 9 seconds for the full index, so that is the number for shelly's device on this store.
(edited)
Estimated CPU scan time on Shelly (128 AVX512-IFMA threads) is 45-60 seconds. Single thread without IFMA estimate is 45-60 minutes.
evoskuil07:53
My first compact block arrived... and it beat the Blockstream explorer by a significant amount, maybe 10 seconds.
image.png
I dunno, maybe they don't have notifications...
image.png
evoskuil14:08
Note that in the current build compact blocks is off by default. Next server commit will enable it by default. To enable:
[peer]
enable_compact = true
evoskuil14:37
Validated pooled block [970030] of (3512) txs in (73643) usecs.
Validated full block [970031] of (2890) txs in (282545) usecs.
"pooled" means the whole block came from pool rows and no scripts ran. "full" means at least one tx was unpooled and the block took the normal path. Working efficiently all blocks should be pooled, even those for which we are missing txs upon announcement.
(edited)
evoskuil14:44
Now that we are operating a tx pool, there is pool-based fee data, so I've updated the fee estimator. This should now produce the equivalent of the Core estimations, though I haven't pushed it yet. Also I've added the wtxidrelay protocol, though it's missing a wtxid index into the pool table, which is currently indexed only in the other direction (tx_link -> pool_link). This will require a second table head for a single table, and all are temporary. So a little more work to do on that. Given that this is optional, and fills only when current, it has no impact on IBD times. I've also found I can collapse all but two of the columns in all of the SoA tables, so that will get simpler and slightly more efficient, just a mechanical refactor.
(edited)
evoskuil14:50
These settings also impact compact:
[node]
compact_timeout_seconds = 60
compact_missing_percent = 50
evoskuil19:49
Image from iOS
A
ariard21:13
Hello galt and guys, Is there an ongoing implementation of BIP 54 somewhere in libbitcoin ? Even if I know folks have different viewpoint on the necessity and rational of each fix, at worst they can be implemented each one individually. Willing to either go to implement some parts, or at least to review it in libbitcoin and that way to check more the BIP.
evoskuil21:32
It's not implemented, PRs welcome.
1 reply · ariard · last Oct 07, 2026
A
ariard05:04
Okay I'll go to implement the 2 first fixes (a) difficulty adjustment exploits and (b) long block validation time in that lovely C++. Will follow-up on that.

Tuesday, October 6, 2026

evoskuil00:08
This will be interesting…
(edited)
Image from iOS
evoskuil00:45
Image from iOS
evoskuil14:01
Core v32 assume valid with a bigger cache ended up being slower than smaller cache. So this is their optimal config.
(edited)
Image from iOS
evoskuil16:28
Just adding the tx index, oof.
Image from iOS
1 reply · evoskuil · last Oct 06, 2026
evoskuil22:04
Image from iOS
evoskuil16:29
Assume valid (without indexing) on RPi5 not gonna win any awards.
(edited)
Image from iOS
evoskuil19:34
10 hrs assume valid with no indexing vs. 1.5 hrs with tx index, spend index, and address index.
Image from iOS
🚀 1
pmienk21:24
Running a test in my repo before push/tag/build-release - below is the set of builds currently slated for release via workflow:
  • macos
  • arm64 - aes/sha/sha3 enabled
  • x64 - aesni/avx2/sse41 enabled
  • windows
  • arm64
  • no nondefault optimizations
  • sha
  • sha3 (chains sha)
  • x64
  • avx2
  • shani
  • avx512
  • avx512 + shani
  • linux
  • arm64
  • no nondefault optimizations
  • sha
  • sha + sha3
  • x64
  • avx2
  • avx2 + shani
  • avx512
  • avx512 + shani
  • x64 - musl
  • avx2
  • avx2 + shani
  • avx512
  • avx512 + shani
(edited)
3 replies · pmienk, eynhaender · last Oct 07, 2026
pmienk21:28
This list was not intended to be exhaustive, as has been discussed prior. If that were the case, we would easily balloon into 64+ binaries. Feedback appreciated - if there are configurations we can loose or other scenarios we should be supporting as an alternative, insight would be greatly appreciated. This is mostly me poking around.
pmienk21:29
The musl effort is only a last minute addition based on prior effort hosting in docker, it's unclear as to whether it should replace nix or be dropped.
eynhaender05:36
An solid selection, I’m not missing anything.
evoskuil22:04
replied to a thread: view
Image from iOS

Wednesday, October 7, 2026

Huddle with pmienk, eynhaender, evoskuil, Eric Chennells, Rowan Voskuil · 117 min15:56
1 reply · evoskuil · last Oct 07, 2026
evoskuil22:34
  • static linked binaries
  • acceptance test binaries
  • verify compact blocks
  • verify silent payments
  • functional test reorg
  • verify testnet3/4, regtest
  • implement/verify signet
  • document quickstarts
evoskuil22:34
replied to a thread: view
  • static linked binaries
  • acceptance test binaries
  • verify compact blocks
  • verify silent payments
  • functional test reorg
  • verify testnet3/4, regtest
  • implement/verify signet
  • document quickstarts

Thursday, October 8, 2026

evoskuil03:41
Note that Core doesn't provide an address index. So I'll be adding that by compounding these with Fulcrum. And it has no silent payment index, so I'll be compounding that with Frigate. Our SP index isn't shown yet either.
image.pngimage.png
Full validation runs take a lot longer. Here's the latest.
image.pngimage.png
🚀 1
evoskuil04:18
Note that Jennings is 1 x 2.5 Gbps (vs. 2 x), so the higher milestone time is just bandwidth.
pmienk08:13
Binary linkage information:
========================================
File: candidate/bs-musl-x64-avx512-shani
candidate/bs-musl-x64-avx512-shani: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, BuildID[sha1]=7da6507aefcb8fa7d8ff4a9a447dd036f9a2a070, stripped
--- No dynamic dependencies (likely fully static) ---
	/lib/ld-musl-x86_64.so.1 (0x746103bdb000)
	libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x746101b57000)
	libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x746103ba7000)
	libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x746103bdb000)
--- ELF dynamic section (readelf -d) ---
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.musl-x86_64.so.1]
 0x000000000000001d (RUNPATH)            Library runpath: [/home/runner/work/libbitcoin-server/libbitcoin-server/prefix/lib]
Been chasing that 'likely fully static'
evoskuil13:35
Core's http/rpc server hung while Fulcrum was syncing from it, nothing logged, just dead.
😞 1
evoskuil14:29
Turns out that's Core just repeatedly timing out Fulcrum because Fulcrum looks dead because it's so slow. So Core config needs much higher idle timeouts with Fulcrum.
Core is 13.9 hrs assume valid with spend and tx index (no address index option) vs bs at 88 mins with spend, tx and address index on. At double the bandwidth Core would be the same and bs would be 44 mins.
(edited)
image.png

Friday, October 9, 2026

evoskuil02:12
image.png
eynhaender02:32
devastating
😅 1
1 reply · neillm · last Oct 09, 2026
neillm02:32
engineered
evoskuil03:18
Full jennings milestone matrix. Didn't capture the Core store sizes yet.
image.png
Notice that the top Core line corresponds to the indexing level of the bottom bs line, so Core takes 15.4x longer to achieve that same level of indexation, and doesn't support address indexation.
(edited)
pmienk06:33
github.com/libbitcoin/libbitcoin-server/releases#… - latest tagged release. my understanding is that the musl variants avoid glibc version issues, nix is targetting glibc 2.39 at present using ubuntu 24.04.
evoskuil13:56
Final address index, milestone runs, with store sizes. Silent payment compares in progress. Faster, smaller, simpler.
image.pngimage.png
evoskuil14:20
The tx pool (unconfirmed tx index, wtxid index, and validation/confirmation metadata) was formerly dropped at prune time, effectively resetting it at each restart, while using the index for optimizing the catch-up sync. That is now updated so that the pool is pruned on a row-by-row basis so that confirmed txs and txs that conflict with confirmed txs and children of conflicting txs are selectively dropped from the index. This can later be set up to operate on demand while running. The only limit to the size of the tx pool record count is disk space.
evoskuil15:33
I've set up neidermeyer to closely match Lopp's annual node benchmark machine (since 2017) and am running identical scenarios using Core v32 and BS latest. I had to build Core without shani because it picks it up from the machine unconditionally otherwise, and the target doesn't have shani. That review work typically starts in November. I expect to have the two outstanding validation performance optimizations (view-based validation and parallel confirmation) complete well before that, but even without them we are significantly faster.
(edited)
evoskuil16:24
I've verified that with the pending wtxid tx negotiation and mempool message, we finally have 100% coverage of network protocol from getheaders (31800) through wtxidrelay (70016), with the exception of bip37 (bloom filters), which is deprecated (and we implement the not supported signaling). The other much older deprecated messages are either implemented and disabled (reject, alert) or obsolete and ancient (checkorder, reply, submitorder). That's all there is apart from going back down level to blocks first, though I've disabled that code.
evoskuil16:39
Note that there are several much ballyhooed protocol proposals that appear either dead or dying, including Ancestor Package Relay (bip331), Erlay (bip330), Dandelion (bip156), P2P UTXO Set Sharing (bip452). Assume utxo sharing is the most recently active, but inactive since early June, nothing has happened on either PR or on the mailing list.
(edited)
evoskuil17:19
Frigate is heading to the moon. 🚀
image.png
eynhaender18:03
How do you run this combo? I thought you'd have to sync core first and then index fulcrum from there.
evoskuil18:16
Yep, tho you could sync one block of each, record the time and then move to the next block. So that's how I plot it.
👌🏻 1

Saturday, October 10, 2026

evoskuil01:42
Frigate has a lot of room for improvement when building the index. Single thread, no hardware acceleration, no GPU batching. But this may ultimately be driven by it's use of Core json-rpc interface as its data source.
(edited)
image.png
evoskuil02:39
I've embedded the src build of boost::program_options, replaced boost::url (simple parser is all we used of that huge library), and changed boost::json, boost::container, and boost::test to header only. boost::asio and others were already header only. This may increase the build time a bit, but completely eliminates any dependency on built libraries apart from the operating system (and in the case of Linux, glibc on the operating system). This reduces our supply chain risk even further, as these headers are our only dependencies. But it also should eliminate our number one user support issue, linkage against the wrong variants of pre-built boost libs. github.com/libbitcoin/libbitcoin-system/pull/2077
(edited)
evoskuil07:45
The double-buffering gpu batch implementation crated a stall potential, patch inbound.
evoskuil09:28
Fist optimized SP indexation. Shelly milestone, address index, sp index, unpruned, 41 mins. That compares to the 41.8 hrs for the bitcoind team.
👍 1
evoskuil10:04
With GPU acceleration and read optimization SP milestone went from 100% CPU during indexing to 2%.
👌 1
evoskuil15:44
I updated the full matrix on the bs side so that all reflected runs have the benefit of current optimizations.
image.png
evoskuil15:55
But it turns out these Shelly BS runs were contaminated by Neidermeyer running a LAN sync of Core from Shelly Core. So that is restarted and these are slower than they should be. I'll run them again tonight. Notice that the address index runs are actually faster than their counterparts, though that's within standard variance (5%).
(edited)
image.png
The latest big win is the SP GPU run, using the block view reader. Despite querying every block and prevout and doing the costly EC math to build the SP index, it only added 5 minutes to the run, and ran at 2% CPU. The block view is coming soon to full validation and client filter generation as well.
evoskuil17:41
P2P wtxidrelay and mempool messages are implemented, over a new wtxid index over the tx pool. So the tx pool is natively indexed by tx_link and there is another table that provides only a secondary index for the tx pool, by witness hash (wtxid). The rows are synchronized so there is not even a pointer from one to the other. This completes our full support for the non-deprecated set of P2P messages/protocols. Also the tx pool is now compacted upon store prune, which currently happens once upon process restart after the node becomes current. Compaction removes all spends of prevouts where there is a confirmed spend of the prevout, and all ancestors of such spenders that did not confirm (unconfirmable conflicts). However we do not currently accept unconfirmed txs where the tx spends an output that is already spent by another (e.g. no RBF, that's v5).
(edited)
evoskuil18:21
Also tx pool is now a contributor to the fee history, closing that hole. In fact most of the tx pool and mempool client-server capabilities are unlocked, so I'll be implementing a bunch of the partial/pending items that remain on the matrix.
evoskuil18:27
The v5 work is rapidly being isolated entirely to mining.
👌🏻 1🎉 1👌 1
evoskuil22:45
libbitcoin
A Bitcoin full node and query server. One node that speaks the protocols your software already uses.

Monday, October 12, 2026

eynhaender01:58
Just sent some sats from a mobile Cake Wallet to a Silent Payment address watched by Sparrow. Sparrow handled it like a pro 😎
Screenshot from 2026-10-11 20-48-37.pngScreenshot from 2026-10-11 20-49-06.png
😮 1💪🏻 1
Ooops, it dit it again
image.png
🔥 2🕺🏻 1
evoskuil06:45
What server did you use?!
eynhaender06:48
Oh, this was my working copy from yesterday. Everything later than github.com/libbitcoin/libbitcoin-server/pull/1045 should be fine.
Libbitcoin v4 is the best way to run your local Silent Payment Server now
💪🏻 2💪 1🎉 1
evoskuil06:49
Simulating Lopp's annual performance benchmark. bs is presently tracking 3% faster than the Core v32 LAN run (without its tx or spend indexes). Also 15% faster than the Core Internet run.
(edited)
image.pngimage.png
Vano Chkheidze09:15
if you think we can add to node other bip that need gpu speedup tell me i will expand engine
bip 352 is one of first example how gpu made it possible
evoskuil14:11
And I haven't even started on the major optimizations for validation (view-based whole block validation) and confirmation (parallel) yet.
image.pngimage.png
evoskuil16:35
Each complete to 900k (disk is 1TB). So we've gone from 21 hrs at ~925k to 10.3 hrs at 900k in the past year, and are now beating Core by 1 hr on Lopp's benchmark and by 2.6 hrs against an Internet Core sync on the same benchmark. And by even more when you consider the indexation difference (which I'll measure soon).
image.png
evoskuil18:50
image.png
evoskuil21:23
I've completed some extensive work on optimizing SP indexing (GPU and CPU) and scanning (GPU and CPU). We index blocks out of order as they are validated, but are now also able to provide start thresholds and height/time-based cursoring. The initial implementation scanned the full table and filtered the results. Now scanning will not exceed one concurrency window 50k blocks by default) of excess scanning for a given request. The work also included a chance to the way we track block state. This was originally envisioned as a multimap, which I later optimized into an arraymap. This allowed one state to be reflected and looked up directly from the block link without a search. But new states were appended to the table, and due to the simplified indexation, hid the previous states. This worked fine with a linear state progression, but block states became more complicated with the addition of client filtering indexing and now silent payment indexing. These are independent states that race each other and validation, which itself must contend with milestone/validation bypass, to combine to form a next stage, such as validated or confirmed. And read/write of these values needs to be very fast (no search) because of how extensively it's used. Over time we've evolved tables without heads (nomap), tables without bodies (headmap), arraymap/hashmap tables, and SoA variants of each. These remain simple and provide all sorts of powerful optimizations over the mmap. While working off the SP added complexity I realized that we didn't need a body for block state. The state has been reduced over time to a single byte. That can just be retained in the head bucket using a headmap, where the bucket is indexed by block link and the value is the flags. The flags can be read and written dynamically, because as a head the file is fully captured in a snapshot. So the flags can be merged into the head cell using a memory fence in our existing constructions. So, smaller, faster, one less file, and much more flexible. And so the block state machine implementation has become much simpler.
🔥 2

Tuesday, October 13, 2026

evoskuil02:19
image.pngimage.pngimage.png
evoskuil02:30
image.pngimage.png
pmienk04:33
github.com/libbitcoin/libbitcoin-server/releases#… Removed musl-arm64 due to potential security issue in build tooling.
👍🏻 1
evoskuil14:54
10.3 hrs vs. 15.7 hrs for a comparable run on Lopp's benchmark.
(edited)
image.png
🎉 2
evoskuil22:02
testnet4 (150K blocks) syncs milestone on shelly on < 1 min, full validation < 2 min. testnet3 (5.1M blocks) syncs milestone on shelly on < 20 min, full validation < 40 min. Most of that difference is the 5.1M block sequential confirmation tail, not validation (see Testnet3 Full Validation - orange is confirmation). That should reduce to ~28 mins with parallel confirmation. Blocks are so small in testnet that sequential confirmation falls behind parallel validation. Still have to tune the hashmaps.
(edited)
image.png
🤣 1
evoskuil22:15
Testnet 3
[bitcoin]
bip16_activation_time = 1329264000
bip30_deactivate_checkpoint = 0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8:21111
bip30_reactivate_height = 486000000
bip34_activation_sample = 100
bip34_activation_threshold = 51
bip34_enforcement_threshold = 75
bip34_freeze = 21111
bip65_freeze = 581885
bip66_freeze = 330776
bip9_bit0_active_checkpoint = 00000000025e930139bac5c6c31a403776da130831ab85be56578f3fa75369bb:770112
bip9_bit1_active_checkpoint = 00000000002b980fcd729daaa248fd9316a5200e9b367f4ff2c42453e84201ca:834624
bip9_bit2_active_checkpoint = 000000000000eb906ab072652b86b05a1afeb95df53ed5c5a63aa3574e1f1b33:2011968
checkpoint = 000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70:546
genesis_block = 0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff001d1aa4ae180101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000
milestone = 0000000000010c0090875c05870eed86761b7cde2c03e69d04e5314f6ff59341:5100000
minimum_work = 000000000000000000000000000000000000000000000b6a51f415a67c0da307

[forks]
difficult = false

[inbound]
bind = 127.0.0.1:18333

[peer]
identifier = 118034699

[wallet]
hd_private_prefix = 70615956
hd_public_prefix = 70617039
p2kh_prefix = 111
p2sh_prefix = 196
silent_prefix = tsp
wif_prefix = 239
witness_prefix = tb

[outbound]
seed = testnet-seed.bitcoin.jonasschnelli.ch:18333
seed = seed.tbtc.petertodd.net:18333
seed = seed.testnet.bitcoin.sprovoost.nl:18333
connections = 50
connect_batch_size = 10

[node]
maximum_concurrency = 1000000

[table.header]
expected = 5158746
size = 588097044

[table.txs]
buckets = 5100001
size = 21874552

[table.tx]
expected = 536643888
size = 343452088

[table.ins]
expected = 598161444
size = 311043951

[table.outs]
expected = 1166697559
size = 105002780

[table.input]
size = 981182034

[table.output]
size = 600719803

[table.strong]
expected = 536643888
size = 59030828

[table.candidate]
buckets = 5100001

[table.confirmed]
buckets = 5100001

[table.state]
buckets = 5100001

[table.scan]
buckets = 5100001
Testnet 4
[bitcoin]
bip16_activation_time = 1329264000
bip30_deactivate_checkpoint = 0000000012982b6d5f621229286b880e909984df669c2afabb102ce311b13f28:1
bip30_reactivate_height = 486000000
bip34_activation_sample = 100
bip34_activation_threshold = 51
bip34_enforcement_threshold = 75
bip34_freeze = 1
bip65_freeze = 1
bip66_freeze = 1
bip9_bit0_active_checkpoint = 0000000012982b6d5f621229286b880e909984df669c2afabb102ce311b13f28:1
bip9_bit1_active_checkpoint = 0000000012982b6d5f621229286b880e909984df669c2afabb102ce311b13f28:1
bip9_bit2_active_checkpoint = 0000000012982b6d5f621229286b880e909984df669c2afabb102ce311b13f28:1
checkpoint = 00000000da84f2bafbbc53dee25a72ae507ff4914b867c565be350b0da8bf043:0
genesis_block = 0100000000000000000000000000000000000000000000000000000000000000000000004e7b2b9128fe0291db0693af2ae418b767e657cd407e80cb1434221eaea7a07a046f3566ffff001dbb0c78170101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff5504ffff001d01044c4c30332f4d61792f323032342030303030303030303030303030303030303030303165626435386332343439373062336161396437383362623030313031316662653865613865393865303065ffffffff0100f2052a010000002321000000000000000000000000000000000000000000000000000000000000000000ac00000000
milestone = 0000000000d9877342754dea8ec1eb24631517d38e3443c370465ee53a8b7434:150000
minimum_work = 0000000000000000000000000000000000000000000009a0fe15d0177d086304

[forks]
block_storm_patch = true
difficult = false
time_warp_patch = true

[peer]
identifier = 675223068

[wallet]
hd_private_prefix = 70615956
hd_public_prefix = 70617039
p2kh_prefix = 111
p2sh_prefix = 196
silent_prefix = tsp
wif_prefix = 239
witness_prefix = tb

[inbound]
bind = 127.0.0.1:48333

[outbound]
seed = seed.testnet4.bitcoin.sprovoost.nl:48333
seed = seed.testnet4.wiz.biz:48333
connect_batch_size = 10
connections = 50

[node]
maximum_concurrency = 100000

[table.header]
expected = 156456
size = 17835984

[table.txs]
buckets = 150001
size = 604424

[table.tx]
expected = 14810011
size = 9478407

[table.ins]
expected = 33127580
size = 17226342

[table.outs]
expected = 57089349
size = 5138041

[table.input]
size = 9000000000

[table.output]
size = 20343818

[table.strong]
expected = 14810011
size = 1629101

[table.candidate]
buckets = 150001

[table.confirmed]
buckets = 150001

[table.state]
buckets = 150001

[table.scan]
buckets = 150001

Wednesday, October 14, 2026

evoskuil15:25
Image from iOS
Huddle with pmienk, eynhaender, neillm, Rowan Voskuil, josie, evoskuil · 291 min15:55
2 replies · eynhaender, neillm · last Oct 14, 2026
eynhaender17:14
back in 10
neillm17:35
Thanks all, had to hop
👍 1👍🏻 1
evoskuil21:22
image.png
🔥 1
evoskuil23:11
image.png
3 replies · pmienk, evoskuil · last Oct 14, 2026
pmienk23:13
It would really only be an unfair comparison if they were saturated with IO.
evoskuil23:14
We can lay that one to rest.
image.png
pmienk23:16
Figured 👍
evoskuil23:12
@josie I don't think it's the peer management! 😂
😂 1
josie23:25
still amazed theres only a 20m difference between cpu and gpu
evoskuil23:25
It's all in the collection cost.
josie23:25
and an 1.5h difference between reindex and reindex-chainstate
evoskuil23:25
sigs are super cheap 128 threads at a time.
💪 1

Thursday, October 15, 2026

evoskuil01:47
10 peers, same as brand x. Note that our 10 peer full validation is 2.2 hrs, and their 10 peer assume valid and also reindex chain state both come in well over 5hrs.
image.png
evoskuil02:00
X (formerly Twitter)
Libbitcoin is significantly faster validating the full chain provided by 10 peer connections over the p2p network than bitcoind just doing a local reindex of its already downloaded store. #libbitcoin is coming.
🔥 1
eynhaender02:24
X (formerly Twitter)
Pax #libbitcoin, at #bitcoinconf London
evoskuil02:28
Squat on Beak St. in SOHO. That was right before Amir told me how excited he was about his mmap hash table design.
Wikipedia
Beak Street is a street in Soho, London, that runs roughly east–west between Regent Street and Lexington Street.
2 replies · josie · last Oct 15, 2026
josie09:34
this is the same one from the stop g8 police raids, right?
👍🏻 1
josie09:37
if its the same one, i went by to see it when i was in london a few years back, only to discover its a gaudy turquoise office building now 🥲
evoskuil02:34
Same room/day as this. reddit.com/r/Bitcoin/…/bbc_click_interview_peter_todd_with_dark_wallet. The BBC broadcast was 6 days after that twitter post.
(edited)
evoskuil14:34
There's no address index, so still not a fair comparison for libbitcoin.
image.png
evoskuil15:22
Block view validation optimization is picking up some steam on the low end platform.
image.png
evoskuil20:21
Time to optimize CF using the block view, as CF with no validation now costs more than full validation.
image.png

Friday, October 16, 2026

eynhaender04:08
Sending and receiving Silent Payments with Sparrow using libbitcoin-server v4 as Electrum Backend and Block Explorer
🚀 2🕺🏻 1😵‍💫 1🤫 1🤐 1
evoskuil04:42
Client filters are optimized to the essential read cost. It's about 2.7x faster per tx than SP with GPU, because SP writes about 6x more data. dropped from 78.2 to 48.6 mins. This means that a combined SP + CF run should sit at the CF cost until taproot kicks in, and then should rise instead at just slightly above the SP rate.
image.png
evoskuil07:04
As expected, the full suite just follows SP, with filters adding only a few seconds (well within variance). I'm now running bitcoind with all indexes (adding client filter to top line).
(edited)
image.pngimage.png
evoskuil07:47
MP4libbitcoin-the-distance.mp4179.8 MB · too large to mirror
🎉 1😎 1❤️ 3
1 reply · josie · last Oct 16, 2026
josie12:21
amazing song
neillm16:04
Screenshot(70).png
👍🏻 1
evoskuil16:05
We put out those numbers, which would be headline news on any other day, and get mogged by the flying car nonsense.
🤣 1
josie17:14
the car was about as interesting as his "tesla bot" demo with some guy in a wetsuit
😂 1
evoskuil17:32
image.png

Saturday, October 17, 2026

evoskuil00:19
libbitcoin-cover.png
❤️ 2🔥 1
evoskuil02:11
(edited)
libbitcoin
Performance measurements of libbitcoin-server across machines and configurations, some with Bitcoin Core, libsecp256k1, or UltrafastSecp256k1 comparisons.
evoskuil02:16
image.png
evoskuil03:09

Sunday, October 18, 2026

evoskuil17:36
libbitcoin
Query performance measurements of libbitcoin-server across machines and configurations, some with Bitcoin Core, Fulcrum, or Frigate comparisons.
Still a work in progress, with ongoing minor changes in tuning and optimization.
evoskuil23:41
The base store size is now reduced by 11.7GB. This is the result of an optimization that makes the strong table (confirmed tx->block) into a head only arraymap, eliminating the hashmap. More than the size reduction, this represents what should be a significant performance improvement for confirmation and address history.
🎉 2

Monday, October 19, 2026

evoskuil02:41
image.png
😮 1😱 1
1 reply · evoskuil · last Oct 19, 2026
evoskuil02:53
What's in your node?
🤣 1🤷🏻‍♂️ 1💯 1
evoskuil02:43
Coincidentally I removed poolstl today, because it was a significant amount of code that we don't use, and I needed to modify the small amount that we do use. So that's been replaced, and it was our last internal or external dependency apart from boost.
evoskuil02:51
I've added the option --with-embedded so that the embedded web pages can be excluded. When this is not defined (on server) the embedded data is defaulted to empty, which enables the local files system load. If that is not set the API is still served for both admin and native interfaces. This reduces the size of the binary by 5-11% depending on OS.
evoskuil02:53
replied to a thread: view
What's in your node?
🤣 1🤷🏻‍♂️ 1💯 1
evoskuil03:06
UF was bundled in the duckdb extension so almost missed it.
image.png
evoskuil05:37
Did I miss any? LevelDB, DuckDB, RocksDB, SQLite
(edited)
evoskuil07:37
image.png
evoskuil17:51
The base store size is now reduced by 11.7GB. This is the result of an optimization that makes the strong table (confirmed tx->block) into a head only arraymap, eliminating the hashmap.
This has significantly improved low end performance. macOS pruned 10GB milestone dropped from 72 mins to 41 mins. The linux/windows milestones didn't change, as they remain network limited. Validation time on the minimum RAM (18GB) mac dropped at least 2 hours (partial run). So I'm going to drop the RAM schedule for macOS mins from 10/18GN to 8/16GB to match the others, and then reverify. This will result in consistent default head sizings by RAM on any OS. Also, all of the bigmac runs in the past, and these new ones, were running with AVX-512 enabled. But bigmac has the crippled chip, and no shani, so this materially hurts performance. The new startup config code highlighted the issue. So the verification runs will be compiled with AVX512 off (AVX2), and will certainly benefit from that as well. Finally, the strong table (head only) is written in purely sequential order, and read in the validation partial order (organized by concurrency window), but was still configured as random access (hashmap). So this will also be updated for the verification runs and should assist validation further. Total store size shrinks by 11.7GB, but the head gets almost 2GB larger. This slows snapshot/recovery a bit (maximal head set at 950k now 19.9GB). But the head being an arraymap means that its just streaming appends to the head as blocks arrive, total write ordering. So we don't force this head to be resident. That change was verified to be very effective. It is flushed to disk quickly after write. So the net head-resident space actually shrinks.
evoskuil18:02
All of the RPi5 (Jennings) lower end plots on the performance page will eventually get re-run, since this will materially affect them. I've already updated the store size on all pages. The block view run completed on Jennings with just over 1 hr savings:
image.png
👌🏻 1
evoskuil20:42
The above strong table optimization is now fully merged.
evoskuil22:52
I've been syncing bs off of bc for a bit. The throughput maxes out lower than expected, so I've been digging into why. I can't believe how poorly this network stack is constructed.
image.png

Tuesday, October 20, 2026

evoskuil00:42
bs can easily take many several times more blocks than bc can dish out, and bs is indexing them into relational tables while bc is just reading them directly into the socket from stored blocks on the disk. The disks are independent and fast, and all resource utilization is extremely low. The limiting factors all pertain to how bc manages the network, and to a lesser degree how it loads the blocks from the file system into the socket. It uses only one thread for network I/O across all channels. Nevertheless there is extensive long-duration mutex locking across the entire network stack (despite just one network thread by design). There is no asynchrony at all, the network is sequential on one thread. I set up 32 ports and connect to each manually from bs on performance-unmanaged connections. I tried up to 256, but 32 is far more capacity than bc can supply. It tops out somewhere around 18. The throughput is lower than over the Internet on the same machine. Which means bs can easily do more (and over 100+ connections vs. just 32), but the one bc thread is frequently stalled on page faults, critical sections, and polling. It's telling that this one thread never comes close to 100% utilization, as it spends so much time idling. It's not something that can be fixed with config or more resources. The design is a single thread, and there 99+% of machine resources are unused. We spend a lot of time looking at IBD, but this is the other side of the coin. bs can sync fast because it can cobble together any number of slow peers to reach its bandwidth limitation. bc is limited not only by its utxo accumulator sequentially, but its sophomoric network design.
(edited)
evoskuil05:35
The strong table optimization has sped up the macOS full validation on min RAM by 3 hrs (10.5 vs 13.5 hrs), while also reducing the test platform RAM from 18GB to 16GB. The macOS milestone min, ran at 8GB vs 10GB and went from 72 mins to 41 mins. So macOS mins are now comparable to win/linux.
The Windows and Linux milestone and validation runs also improved, but they were not as memory bound as macOS so not as much. Huge win all around though.
(edited)
🎉 2
evoskuil13:28
Milestone min ram, optimized strong table.
(edited)
image.png
evoskuil13:43
Validation min ram, optimized strong table, before and after (windows after still running).
image.png
evoskuil14:50
The remaining differences are the result of CPU capabilities across the distinct platforms, and no longer a function of RAM at this level.
evoskuil18:42
image.png
🚀 1
3 replies · pmienk, evoskuil · last Oct 20, 2026
pmienk18:44
my eyes must be going, can't read that graph
👍🏻 1
evoskuil18:44
image.png
pmienk18:44
thanks!
👍🏻 1
evoskuil18:44
replied to a thread: view
image.png
evoskuil18:46
This is the one comparison where we don't come out consistently on top...
image.png
But this may have something to do with the size of the Fulcrum index...
image.png
... which is 11x larger than bs'. Nevertheless, we are much faster cold for 0-10 entries, very respectable for middle tier, and significantly faster for very large sets. So I figured it isn't worth the extra 200GB or so. Fulcrum can also win on the largest sets with an unbounded cache setting, this shows its installed default (as it shows our default hashmap load factors, which target a 32GB machine).
(edited)

Wednesday, October 21, 2026

evoskuil00:29
This Slack #general channel has forever been accessible through a publicly-posted (our system wiki menu, and multiple Twitter/X postings) open invite, and I don't believe we have ever blocked anyone, and there are many pseudonymous lurkers (267 current "members" in all). As we approach release we believe it's important that people using the software can easily get a good sense of our process and our long history. Unfortunately this channel covers only the past 9 years or so, with 6 more on our email list and IRC, though the history here is substantial. In order to make the content both linkable and searchable We'll be setting up a #general mirror (with history), linked from our web site. Given that it's already public this isn't a change except in making it easier to work with. *Included* • Every message, thread, reaction and attachment (images, PDFs, snippets, videos) in #general. • Each member's display name, full name as shown in Slack, avatar, and profile title if set. *Not included* • Email addresses, phone numbers and Skype handles from member profiles. • Time zones, status text, custom profile fields and separate first/last name fields. • Gravatar links (they encode a hash of your email). Avatars are stored as images only. • Other channels, DMs and huddle transcripts. *Unchanged* Message text is archived as written. A few messages contain email addresses that people posted themselves; there are no phone numbers.
image.png
evoskuil01:37
libbitcoin
A Bitcoin full node and query server. One node that speaks the protocols your software already uses.
evoskuil02:01
libbitcoin.info
libbitcoin Slack #general archive, October 2026.
evoskuil13:56
Dropped another 0.5 hrs off of the Lopp bench, now about 1.5 hrs ahead (projected from 900k -> 950k, since neidermeyer is 1GB SSD).
image.png
evoskuil14:56
Found an insidious use of std::stream in the http path. We avoid std::stream in performance critical paths because it imposes a critical section, driving all threads into a bottleneck, among other things. So our http client-server benchmark numbers are about to jump. This was the result of throughput (vs. latency) testing. bs latency is better than bc on all requests except for block (which makes sense, since the whole bc store is just whole blocks on disk, making that faster and everything else slower). But the network architecture of bc limits its ability to deliver those blocks concurrently. bs doesn't have that limit, but it was hitting a ceiling in throughput at around 16 threads. The stream was the bottleneck, it just wasn't obvious until measuring throughput. But it also creates up to a 54% hit on latency.
I could understand 42, but 4 just makes no sense.
✅ 1
Huddle with pmienk, eynhaender, Marnix, evoskuil, Eric Chennells, Rowan Voskuil · 187 min15:54
5 replies · Eric Chennells, evoskuil, Rowan Voskuil · last Oct 21, 2026
evoskuil16:47
image.png
Rowan Voskuil16:48
image.png
Rowan Voskuil16:52
image.png
Rowan Voskuil16:57
image.png
evoskuil19:46
Bitcoin Core to end validation altogether: github.com/bitcoin/bitcoin/issues/36557
😲 1
5 replies · pmienk, evoskuil · last Oct 21, 2026
pmienk19:52
I wonder how we'll generate 'comparative' data afterward
evoskuil19:52
We'll have to keep btcd alive.
pmienk19:53
what's the hidden comment I wonder
evoskuil19:54
"I was a beginner, sorry. On Saturday, October 17, 2026, at 14:11, Tarhadi <@.> wrote: ..."*
evoskuil19:47
Predicted it over 10 years ago.
evoskuil19:53
X (formerly Twitter)
He misspelled, "drop validation". Trust Me Bro [tm] https://t.co/d0i6oaN06X

Thursday, October 22, 2026

eynhaender00:36
image.png
🤣 2🚀 1
1 reply · neillm · last Oct 22, 2026
neillm00:58
shut-up-and-take-my-money.mp4 MPEG 4 Video · 127.5 KB
evoskuil02:14
6.5x the p2p block throughput (so far)
image.png
evoskuil02:23
That's the single threaded synchronous network stack doing its thing. All the peers shared that one thread, so the more connections there are, the slower each one is. So its doesn't really matter how fast you can get the block off the disk.
(edited)
2 replies · pmienk, evoskuil · last Oct 22, 2026
pmienk02:25
And yet, speed is the justification for storing the serialized block together?
evoskuil03:10
I think it's more about what was easy. But as indexes have been jammed into it it just becomes slower and more complex.
evoskuil05:40
image.png
This last one has a sharp drop at 256 channels of binary blocks. That's an obvious anomaly which we'll track down. Have already resolved a couple of those with simple code changes.
evoskuil05:57
As you can see BC retains an advantage in blocks at up to 16 channels over http (though that's generally a private interface) and 4 channels over p2p, but we can scale to serve dramatically more thruput.
The plateaus appear to be a test harness (python) limitation, which I'm working though now. Those curves should just continue upward until they hit something real.
Note also that BC has a new and totally different http stack vs. its p2p stack. The http stack is actually multithreaded, which is why it scales while the p2p stack does not at all.
BS p2ps and https coming soon to the thruput plots, also zmtp (ZeroMQ) for BS/BC and zmtps for BS.
evoskuil06:19
At peak, BS serves encrypted blocks about 7.7× as fast as BC.
linear scale p2ps block thruput
image.png
evoskuil15:23
image.png
Curve ZMQ (ZeroMQ's specification of Bernstein's CurveCP) added to our numbers.
image.png
evoskuil15:33
This test is initiated over P2P, one transaction at a time, from a single peer connection in the test client:
  1. The client announces the transaction with an inv message.
  2. It waits for the server to request it with getdata. Transactions not requested within 1 second are recorded as unrequested and skipped.
  3. It sends the tx message. The clock starts as that send completes.
  4. The clock stops when that exact transaction arrives on the ZMQ rawtx subscription. If it doesn’t arrive within 1 second, it’s recorded as unnotified.
The 28,142 transactions of blocks 950,001–950,009 are sent this way in block order, each only after the previous one finishes. So the latency is the server’s full path: receive and parse the transaction, validate it, accept it to the pool, and publish the notification. The inv/getdata round trip is timed separately and not included.