Skip to content

Latest commit

 

History

History
89 lines (59 loc) · 4.29 KB

File metadata and controls

89 lines (59 loc) · 4.29 KB

Reproducible Build Verification

Scripts for verifying that the published Bull Bitcoin Mobile app matches a build from source.

How it works

Three components work together:

../Containerfile.tools and ../Containerfile.app (root)

Two-file build setup driven by make android release:

  • Containerfile.tools installs all toolchains (Rust pinned via RUST_VERSION, Flutter via FVM, Android SDK, Gradle).
  • Containerfile.app copies the repo, runs pub get / build_runner / gen-l10n, and configures Gradle. It does NOT run flutter build — that happens via podman run against the resulting image so the multi-GB build output is never committed to a layer.

Two environment variables are set at build time to eliminate sources of non-determinism:

  • SOURCE_DATE_EPOCH — set to the timestamp of the latest git commit (git log -1 --format=%ct). OpenSSL embeds a wall-clock build timestamp in compiled binaries by default; setting this variable makes it use a fixed value instead, so any .so that links against OpenSSL (libark_wallet.so, libboltz.so, libtor.so) is identical across builds.
  • CARGO_ENCODED_RUSTFLAGS — three --remap-path-prefix flags that rewrite absolute paths baked into Rust binaries at compile time (home directory, .cargo, .rustup) to fixed strings (/cargo, /rustup, /build). cargokit reads CARGO_ENCODED_RUSTFLAGS rather than RUSTFLAGS; flags are separated by the ASCII unit separator \x1f (octal \037).

Dockerfile (this directory)

A small verification tools image containing apktool, bundletool, and Java. It is used only for decoding APKs — it never builds the app. verify_build.sh builds this image automatically and runs apktool/bundletool inside it so no local Java installation is required.

verify_build.sh

Orchestrates the full verification:

  1. Builds the verification tools image from Dockerfile
  2. Optionally downloads the official APK from the GitHub release, or uses a locally provided APK or split APK directory
  3. Builds the app from the current repo checkout via make android release (which uses the root Containerfile.tools + Containerfile.app)
  4. Picks up the extracted APK from the repo root (./BULL-release.apk)
  5. Decodes both APKs with apktool (inside the tools container)
  6. Diffs the decoded output excluding META-INF (signatures are not part of reproducibility)
  7. Writes a RESULTS.md verdict to the workspace directory

For build-to-build comparisons to be reproducible, both builds must use the exact same git commit. SOURCE_DATE_EPOCH is derived from git log -1 --format=%ct, so if two builds are from different commits they will embed different timestamps and the .so files will differ.


Prerequisites

  • Docker or Podman
  • 8GB+ available RAM
  • 50GB+ free disk space
  • curl and git installed

Usage

cd reproducibility

# Verify against the GitHub release APK (downloads it automatically)
# Repo must be checked out at the matching tag (e.g. git checkout v10.9.8)
./verify_build.sh --version 10.9.8

# Verify a locally provided APK against a fresh build from the current checkout
./verify_build.sh --apk ./bullbitcoin.apk

# Same, with an explicit version (used in the workspace directory name)
./verify_build.sh --version 10.9.8 --apk ./bullbitcoin.apk

# Verify against split APKs extracted from a device (Play Store path)
./verify_build.sh --apk ~/bullbitcoin-splits/

# Clean up the workspace after verification
./verify_build.sh --apk ./bullbitcoin.apk --cleanup

Output

A workspace directory bullbitcoin_<version>_verification/ is created next to the script containing:

  • RESULTS.md — verdict, version info, hash, and commit
  • official-decoded/ — apktool decode of the reference APK
  • built-decoded/ — apktool decode of the freshly built APK
  • diff.txt / diff_<split>.txt — differences found, if any (excluding META-INF)

Extracting split APKs from a device (Play Store path)

adb shell pm path com.bullbitcoin.mobile
# outputs something like: package:/data/app/com.bullbitcoin.mobile-.../base.apk
adb pull /data/app/com.bullbitcoin.mobile-.../base.apk ~/bullbitcoin-splits/
adb pull /data/app/com.bullbitcoin.mobile-.../split_config.arm64_v8a.apk ~/bullbitcoin-splits/
# pull any other split_config.*.apk files listed

Then pass --apk ~/bullbitcoin-splits/ to the script.