Skip to content

Instantly share code, notes, and snippets.

@dergoegge
Created March 9, 2026 14:49
Show Gist options
  • Select an option

  • Save dergoegge/2f66365264f316b5ca60ec7565d06d74 to your computer and use it in GitHub Desktop.

Select an option

Save dergoegge/2f66365264f316b5ca60ec7565d06d74 to your computer and use it in GitHub Desktop.
Antithesis Testing for Bitcoin Core

Antithesis Testing for Bitcoin Core

What is Antithesis?

Antithesis is an autonomous testing platform. It runs your software inside a deterministic simulation environment (deterministic hypervisor), where it systematically injects faults (network partitions, container restarts, disk fills, process pauses, etc.) while exploring execution paths to find bugs. Every test run is fully reproducible via deterministic replay.

Bitcoin Core is compiled with Antithesis coverage instrumentation (-fsanitize-coverage=trace-pc-guard), which guides the platform's exploration toward new code paths. Sanitizers can be enabled to catch memory and concurrency bugs alongside the fault injection (just like in our CI).

Test Structure

The tests running on Antithesis are new tests, and not part of the main repository (for now). The functional, fuzz or unit tests are not involved.

A test run consists of Docker images, packaged as an Antithesis test template:

  1. Node images -- Bitcoin Core nodes running in regtest mode, connected to each other via -addnode. Different nodes run with different sanitizers and configurations (e.g. pruning).

  2. Workload image -- A collection of executables that drive test activity by interacting with the nodes. Antithesis invokes these individual workload drivers throughout the test run.

  3. Config image -- Contains only the docker-compose.yaml that defines the topology of the test (nodes, workload, ...).

Workloads

initial-rpc-workload -- Exercises Bitcoin Core via RPC: mining blocks, sending transactions (simple, cross-node, RBF, raw, sendmany, consolidation), calling various RPCs (pruneblockchain, getblocktemplate, gettxoutsetinfo, loadwallet/unloadwallet, abandontransaction), and checking eventual consistency across nodes. Also tests the multiprocess IPC interface (bitcoin-node with -ipcbind=unix) via Cap'n Proto, exercising the mining interface (createNewBlock, checkBlock, getMiningInfo) and echo.

Properties Checked

Workload drivers use the Antithesis SDK to assert properties:

  • Crash detection -- Nodes must stay alive through fault injection
  • Eventual consistency -- After faults stop, all nodes should converge to the same chain tip
  • Sanitizer violations -- TSan/ASan reports are captured as bugs

Reading Bug Reports

Bug reports typically include:

  • Antithesis logs -- The platform's own logs showing which faults were injected, which properties failed, and at what virtual time. Property failures reference the assert_always! / assert_sometimes! macros from the workload code.

  • Sanitizer reports -- Any issues reported by one of the sanitizers being used.

  • Bitcoin Core debug logs -- Standard debug.log output from each node (node1, node2, node3). All log categories are enabled (-debug). Nodes are identified by their container hostname.

Debugging

Because Antithesis runs everything inside its deterministic hypervisor (proprietary), findings cannot be reproduced locally using the test template. The exact execution depends on the platform's scheduling and fault injection decisions, which are not replicable outside of it.

To investigate a finding, Antithesis provides the Multiverse Debugger through their web platform. It allows time-travel debugging of the full deterministic execution: stepping forward and backward, inspecting state at any point, and exploring alternative execution paths. Access to the debugger is possible through the Antithesis web UI, if you have the necessary permissions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment