Full stack Bitcoin software

Test Architecture

How libbitcoin is tested: testability, kinds of test, reference vectors, continuous integration and coverage.

How libbitcoin is tested: code built for testability, the kinds of test, the platforms each change is tested on, and how coverage is measured. The mechanics of writing a test are in Test practices.

1. Testability#

Code is written to be tested through its own interface. There are no test hooks: no test-only branches, no conditional compilation for tests, and no access granted to tests that other callers do not have. Mocks and fakes are injected to alter and detect behavior:

2. Kinds of test#

Kind Scope Suite
unit A method or function, isolated to the extent practical. C++, in each repository's test/
component A group of units, such as a class. C++, in each repository's test/
functional A feature group, such as client-server communication. C++, in each repository's test/
performance The speed of a unit or component. C++, in each repository's test/, disabled by default
acceptance Each server interface, as a client uses it. Python, in libbitcoin-server's endpoints/, against a live node

The C++ suites run in every CI job, except the performance tests, which are compiled only when HAVE_PERFORMANCE_TESTS is defined. The acceptance suite is customer acceptance: it exercises each interface of a running bs as its clients do, over its own protocols.

3. One thing, named#

A test case tests one thing, and its name states that thing: the method, the condition and the expected result. A failing test is then a diagnosis.

4. Reference vectors#

Tests establish correctness, using reference vectors wherever they exist.

Source Vectors Repositories
BIP-21 URI scheme explorer
BIP-32 HD wallets, test vectors 1, 2 and 5 system, explorer
BIP-38 Encrypted private keys system, explorer
BIP-39 Mnemonics (trezor python-mnemonic, bip32JP Japanese) system
BIP-143 Segwit v0 signature hash system
BIP-158 Compact block filters system
BIP-173 Bech32 addresses, valid and invalid system
BIP-174, BIP-370 PSBT, PSBT v2 system, server
BIP-324 ElligatorSwift, v2 transport packet encoding system, network
BIP-340 Schnorr signatures system
BIP-341 Taproot signature hash and wallet vectors system
BIP-352 Silent payments, send and receive system, database, node, server
BIP-380, BIP-386 Descriptor checksums, tr() descriptors system, server
RFC 2202, RFC 4231 HMAC-SHA1, HMAC-SHA256 and HMAC-SHA512 system
RFC 4648 Base16, base32 and base64 encodings system, explorer
RFC 5869 HKDF system
RFC 6070, RFC 7914 PBKDF2 and scrypt system
RFC 6979 Deterministic ECDSA (P-256) system
RFC 7617 HTTP basic authentication network
RFC 7748 X25519 system, network, server
RFC 8439 ChaCha20, Poly1305 and their AEAD system
RFC 8448 TLS 1.3 handshake traces network
FIPS 180-4, CAVP SHA-1 and SHA-2, including SHA-512/224 and SHA-512/256 system, explorer
FIPS 197, SP 800-38A AES and its modes system
FIPS 202 SHA-3 system
Wycheproof secp256k1 ECDSA, P-256 and P-384 ECDSA and ECDH, AES-GCM system
SLIP-39 Shamir mnemonics (trezor python-shamir-mnemonic) system
Unicode NormalizationTest.txt system
RIPEMD RIPEMD-128 and RIPEMD-160 reference vectors system
eSTREAM, NaCl Salsa20, XSalsa20-Poly1305 system
Bitcoin Core Script tests, valid and invalid, by fork system
Bitcoin Core key_io_valid.json, blockfilters.json, MuHash, descriptors system, network, server
Electrum Electrum mnemonics, v1 and current system
ElectrumX Merkle proofs with cp_height, block headers database, server
Bitcoin Wiki P2P message samples, wallet import format network, explorer

5. Continuous integration#

Every change is built and tested by CI (GitHub Actions) before review. Each library repository runs the same matrix. The gate runs on push and pull request, and the expanded matrix, run on demand, covers every compiler in all combinations of debug or release and static or shared (see Continuous integration and Compilers tested in CI). The current status of each repository is on Build status.

Each CI job runs the same install script published for end-user builds (see Building), so CI verifies the build scripts as well as the build. All build artifacts, for every build system and including the install scripts, are generated from templates and configurable metadata (see Build architecture).

Platform Architecture Word Byte order Compilers Build systems
Linux (Ubuntu 24.04) x64 64 little GCC 13 to 16, Clang 18 and 19 Autotools, CMake, presets
Linux (Ubuntu 24.04) x86 (32-bit) 32 little GCC Autotools
Linux (Ubuntu 24.04) arm64 64 little GCC Autotools
Linux (Ubuntu 24.04) arm32 32 little GCC Autotools
Linux (Ubuntu 24.04) s390x 64 big GCC, cross compiled, tested in QEMU Autotools
macOS arm64 (Apple silicon) 64 little Apple clang (current Xcode) Autotools, CMake
macOS x64 (Intel) 64 little Apple clang (current Xcode) Autotools, CMake
Windows x64 64 little MSVC v145, Clang (clang-cl) Visual Studio
Windows x86 (Win32) 32 little MSVC v145 Visual Studio
Windows arm64 64 little MSVC v145 Visual Studio

6. Coverage#

Line coverage. A GCC debug job in each repository's CI (GitHub Actions) is built with --coverage, and its lcov output is reported to Coveralls, excluding the paths listed in the repository's coverage element of the build model.

Constant time. A libbitcoin-system job in the expanded matrix runs the secp256k1 constant-time tests under valgrind, which reports any branch or memory access that depends on secret data.

Fuzzing. libbitcoin-system is a module of bitcoinfuzz, a differential fuzzer that runs the same inputs through several Bitcoin implementations and reports where their results differ.

Mutation testing. Coverage shows which code ran, not whether a test would fail if it were wrong. Mutation testing changes the code and checks that a test fails. libbitcoin-system is tested on MutantHub.

Copyright © 2011-2026 libbitcoin developers