Skip to content

[Reproducible Builds] 4 small CI changes would make the Linux AppImage verifiable (SOURCE_DATE_EPOCH, QML mtimes, tool pinning, LWK determinism) #187

Description

@xrviv

Summary

We (WalletScrutiny) rebuilt the green_qt 3.4.0 x86_64 AppImage from source in a CI-equivalent container and got remarkably close to the official artifact: the main blockstream binary is size-identical with zero differing bytes in .text, and every Qt 6.11 library, all GDK output, QML resources, and assets are byte-identical. Green desktop is, in substance, nearly reproducible today — the remaining differences are all environmental, and each has a concrete, low-cost fix in CI:

# Remaining diff Cause Fix
1 OpenSSL built on: string in blockstream OpenSSL embeds build time; CI doesn't set SOURCE_DATE_EPOCH export SOURCE_DATE_EPOCH (e.g. the tag's commit timestamp) in the release pipeline — OpenSSL honors it
2 ~3.2 KB of .rodata in blockstream qmlcachegen embeds each QML file's mtime (QV4::CompiledData sourceTimeStamp); git sets mtimes to CI checkout time normalize source mtimes before build (e.g. git ls-files -z | xargs -0 touch -d @$SOURCE_DATE_EPOCH)
3 AppImage plugin set + AppRun linuxdeploy/linuxdeploy-plugin-qt/appimagetool fetched from floating continuous tags pin tool releases (and checksums) in CI
4 usr/lib/liblwk.so (~2.5 MB unstripped) LWK release builds are nondeterministic (ThinLTO .llvm.<hash> symbol churn) — reproduces with two identical consecutive builds separate issue filed: Blockstream/lwk#165

With 1–4 addressed, the AppImage is plausibly byte-for-byte reproducible — the closest of any desktop wallet we have verified.

What we verified (evidence)

  • Official Blockstream_Green_x86_64.AppImage 3.4.0, SHA256 0d5ae746f85c... (matches signed SHA256SUMS).
  • Rebuild: green_qt at 88056710, GDK 0.77.4 @ 2b43409a, Rust 1.85.0, LWK @ bdbf0904, Qt 6.11.0, jammy-based container.
  • Result: 18 payload diff lines total.
  • blockstream: 41,703,528 bytes both; cmp -l clusters mapped with readelf -SW: zero diffs in .text; the 6 .rodata clusters decode as millisecond Unix timestamps inside QML compilation-unit metadata (official: 0x019E8770BAC5 = 2026-06-02 08:29 UTC — your CI's checkout moment; ours: our build moment); plus exactly one differing string: OpenSSL built on: Mon Jun 1 18:35:53 2026 UTC.
  • Qt/GDK/QML/resources: byte-identical.
  • Packaging: official bundles networkinformation/ plugins + glib chain + libQt6ShaderTools.so.6; ours has apprun-hooks/; AppRun differs — consistent with different continuous snapshots of the AppImage tools.
  • Minor: blockstream.desktop / linux_production.png are mode 666 in the official AppImage (CI umask), and libsystemd/libudev show jammy package drift between image dates.

Why it's worth it

Users (and verifiers like us) can then confirm that the shipped binary corresponds exactly to the public source — for a wallet, that's a meaningful trust upgrade, and green_qt is unusually close already. We're happy to share our full rebuild scripts, diff analysis, and to re-verify once any subset of the changes lands.

Activity

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

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestplatform: linuxAffects Linux builds, packaging, or runtime.status: confirmedReproduced or otherwise confirmed by maintainers.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions