Blockstream / Blockstream/green_qt

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

Open
#187 8 comments 2 reactions 1 assignee Claimed by @qblk View on GitHub
enhancement platform: linux status: confirmed
Dominant language
C++
Stars
262
Forks
44
PR merge metrics
No merged PRs in 30d

Description

## 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.` symbol churn) — reproduces with two identical consecutive builds | separate issue filed: [Blockstream/lwk#165](https://github.com/Blockstream/lwk/issues/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.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.