Matching Hashes: Reproducing the Guix-Built Bitcoin Core Release Binary with Nix

b10c1 pts0 comments

Matching Hashes: Reproducing the Guix-built Bitcoin Core release binary with NixEarlier this week, I produced a Nix-built bitcoind binary for Bitcoin Core v31.0 whose hash exactly matches the official Guix-built x86_64-pc-linux-gnu release binary. The result came out of a three year old side project, with a difficult goal: Can a binary built with Nix be made bit-for-bit identical to one produced by Bitcoin Core&rsquo;s Guix reproducible build system?<br>Surprisingly, the answer is yes:<br># on a x86_64 host with Nix installed:<br>$ git clone https://github.com/0xB10C/bitcoind-gunix.git &&\<br>cd bitcoind-gunix &&\<br>git checkout v31.0-match &&\<br>time nix build<br>$ tmpdir=$(mktemp -d) &&\<br>curl -fsSL https://bitcoincore.org/bin/bitcoin-core-31.0/bitcoin-31.0-x86_64-linux-gnu.tar.gz |\<br>tar -xz -C "$tmpdir" --strip-components=2 bitcoin-31.0/bin/bitcoind<br>$ sha256sum "$tmpdir/bitcoind" result/bin/bitcoind

dae69848ae9aaadcc3aa697d1c92b1283273a59c8d87b220b29ddc2813e25eb6 /tmp/tmp.D1kB5yIfR9/bitcoind<br>dae69848ae9aaadcc3aa697d1c92b1283273a59c8d87b220b29ddc2813e25eb6 result/bin/bitcoind<br>At first glance, this might sounds like this should be straightforward: Nix and Guix both compile the same Bitcoin Core source code with GCC, so why wouldn’t the resulting binaries match? In practice, reproducible builds are extremely fragile. Tiny differences in compiler behavior, filesystem paths, timestamps, linker metadata, dependency versions, or environment variables are enough to end up with a different binary, having a different final hash. And while Nix and Guix are philosophically similar, they are independently constructed toolchains with different package graphs, patches, and bootstrap chains. Bitcoin Core uses Guix so release binaries can be independently verified by other developers and users.<br>The matching hash shows that the Bitcoin Core build process is deterministic enough that an independently built toolchain can end up producing the exact same binary. The reproducibility doesn’t seem to be coming from Guix as a special environment alone, but from the build itself. In that sense, it shifts reproducible builds from something that only holds inside the carefully controlled Guix system to something you can actually check across two (carefully controlled) systems. In the future, Guix could be just one participant in a supply-chain model where trust comes from independent builds converging on the same artifact.<br>When starting this project, I didn&rsquo;t really set out to have a fully matching binary. This seemed to be way too much work in an area I&rsquo;m far from an expert in. A first goal was to build all dependencies from source instead of using the versions packaged by Nix. Then, the next goal was to get to a similar stripped binary size, but I eventually lost interest and worked on other things. In 2025, josiebake investigated a bit more, but wasn&rsquo;t able to make much progress either.<br>Reading about LLM tools now frequently solving math problems, I figured I&rsquo;d give Claude Code a VM on a powerful host (for fast compilation) with Nix installed, a checkout of the bitcoind-gunix repository, allowed most tool usage, and give it a /goal produce a Nix-built binary with a hash matching the Bitcoin Core v31.0 release binary for x86_64-pc-linux-gnu. Along the way, I told it to write down its progress in a CLAUDE.md file and make frequent, atomic commits. To help it, I ended up supplying a checkout of the Bitcoin Core repository at the v31.0 tag, later a v31.0 Guix build log, a directory with the Guix depends build artifacts, and a checkout of the Guix repository at the commit used by Bitcoin Core. After burning through roughly 1.5 weeks&rsquo; worth of Claude Pro usage (I set up a /loop 2h continue with what you were doing. If you are stuck, try solving a different problem first command so it would continue once my usage reset), while I spent the weekend camping, it came back to me with a Nix-built binary that matches the bitcoind Guix v31.0 release binary for x86_64-pc-linux-gnu. I used a mix of Claude Sonnet 4.6 and Opus 4.7.<br>Claude ended up producing around 80 commits, which I haven&rsquo;t reviewed. Looking at the end result, it&rsquo;s obvious that it worked around some problems by hardcoding replacements for a few bytes in e.g. glibc ELF notes and replaced a debug-section CRC32 in the bitcoind binary. At some point it said: &ldquo;This is a multi-day refactor - I&rsquo;m not going to do it&rdquo; and started working around it. Getting rid of these workarounds would probably require more LLM tokens, or money, than I don&rsquo;t plan to spend. If someone is interested in moving this forward, this could be an interesting place to spend spare LLM tokens on. There are also other binaries, like bitcoin-cli, that would need to match as well. Then, as a much bigger step, there&rsquo;s cross-compiling for macOS and Windows. Personally, I’m not planning to continue working on this, since I have other projects requiring my attention.<br>By...

guix bitcoin binary core bitcoind rsquo

Related Articles