Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Reproducible builds #326

Open
xrviv opened this issue Sep 20, 2024 · 10 comments · May be fixed by #411
Open

[Feature] Reproducible builds #326

xrviv opened this issue Sep 20, 2024 · 10 comments · May be fixed by #411
Assignees
Labels
documentation Improvements or additions to documentation

Comments

@xrviv
Copy link

xrviv commented Sep 20, 2024

Hello team bullbitcoin! 😃

I'm Danny, and I work with WalletScrutiny.com.
We have reviewed over 6500+ Bitcoin Android apps and firmware.
You can read about our methodology here.


We'd love to work with your team on verifying the reproducibility of your app, with appID com.bullbitcoin.mobile
To get there, may we suggest the following:

  • Include complete build instructions, including possible dummy keystores, etc., in the README.md or BUILD.md
  • Optional: Create a dockerfile to make this process seamless.

Hoping to hear from you again soon!

Kind Regards,

Danny

@i5hi
Copy link
Collaborator

i5hi commented Sep 20, 2024

Hey @xrviv,

Thanks for reviewing our project!

We will create a BUILD.md files with build instructions and keep you posted.

@i5hi i5hi self-assigned this Sep 20, 2024
@i5hi i5hi added the documentation Improvements or additions to documentation label Sep 20, 2024
@BullishNode
Copy link
Contributor

Thanks for your interest. This is an important issue for us. We will make sure to prioritize it before we move out of Beta.

@xrviv
Copy link
Author

xrviv commented Sep 24, 2024

I was able to build 0.3.2, with this Dockerfile:

Proof of Build https://asciinema.org/a/677360

# Use a base Ubuntu image
FROM ubuntu:20.04

# Avoid prompts from apt
ENV DEBIAN_FRONTEND=noninteractive

# Install necessary dependencies
RUN apt-get update && apt-get install -y \
    curl \
    git \
    unzip \
    xz-utils \
    zip \
    libglu1-mesa \
    wget \
    clang \
    cmake \
    ninja-build \
    pkg-config \
    libgtk-3-dev \
    software-properties-common \
    && rm -rf /var/lib/apt/lists/*

# Add the repository for OpenJDK 17
RUN add-apt-repository ppa:openjdk-r/ppa

# Install OpenJDK 17
RUN apt-get update && apt-get install -y openjdk-17-jdk && rm -rf /var/lib/apt/lists/*

# Set up Java environment
ENV JAVA_HOME /usr/lib/jvm/java-17-openjdk-amd64
ENV PATH $JAVA_HOME/bin:$PATH

# Install bundletool
RUN wget https://github.com/google/bundletool/releases/download/1.15.5/bundletool-all-1.15.5.jar -O /usr/local/bin/bundletool.jar
RUN echo '#!/bin/sh\njava -jar /usr/local/bin/bundletool.jar "$@"' > /usr/local/bin/bundletool && chmod +x /usr/local/bin/bundletool

# Install Rust
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
ENV PATH="/root/.cargo/bin:${PATH}"

# Verify Rust installation
RUN rustc --version && cargo --version

# Install Flutter
ENV FLUTTER_HOME /opt/flutter
ENV PATH $FLUTTER_HOME/bin:$PATH
RUN git clone https://github.com/flutter/flutter.git $FLUTTER_HOME
RUN cd $FLUTTER_HOME && git checkout stable && ./bin/flutter --version

# Set up Android SDK
ENV ANDROID_SDK_ROOT /opt/android-sdk
ENV PATH $PATH:$ANDROID_SDK_ROOT/cmdline-tools/latest/bin:$ANDROID_SDK_ROOT/platform-tools
RUN mkdir -p ${ANDROID_SDK_ROOT}/cmdline-tools && \
    wget -q https://dl.google.com/android/repository/commandlinetools-linux-8092744_latest.zip -O android-cmdline-tools.zip && \
    unzip -q android-cmdline-tools.zip -d ${ANDROID_SDK_ROOT}/cmdline-tools && \
    mv ${ANDROID_SDK_ROOT}/cmdline-tools/cmdline-tools ${ANDROID_SDK_ROOT}/cmdline-tools/latest && \
    rm android-cmdline-tools.zip

# Accept licenses and install necessary Android SDK components
RUN yes | sdkmanager --licenses
RUN sdkmanager "platform-tools" "platforms;android-34" "build-tools;34.0.0"

# Clean up existing app directory
RUN rm -rf /app

# Clone the Bull Bitcoin mobile repository
RUN git clone https://github.com/SatoshiPortal/bullbitcoin-mobile /app

# Copy device-spec.json into the container
COPY device-spec.json /app/device-spec.json

# Set up the Flutter project
WORKDIR /app
RUN flutter pub get

# Generate a fake keystore
RUN keytool -genkey -v -keystore /app/android/app/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload -storepass android -keypass android -dname "CN=Android Debug,O=Android,C=US"

# Set up key.properties
RUN echo "storePassword=android" > /app/android/key.properties && \
    echo "keyPassword=android" >> /app/android/key.properties && \
    echo "keyAlias=upload" >> /app/android/key.properties && \
    echo "storeFile=../app/upload-keystore.jks" >> /app/android/key.properties

# Pre-build the project to download all necessary dependencies
RUN flutter precache

# Build the AAB (Android App Bundle)
RUN flutter build appbundle --release

# Generate split APKs
RUN bundletool build-apks --bundle=/app/build/app/outputs/bundle/release/app-release.aab --output=/app/app.apks --device-spec=/app/device-spec.json

# List apks
# RUN unzip -l /app/app.apks

# Extract specific APKs
RUN unzip -p /app/app.apks splits/base-master.apk > /app/base.apk && \
    unzip -p /app/app.apks splits/base-armeabi_v7a.apk > /app/armeabi_v7a.apk && \
    unzip -p /app/app.apks splits/base-en.apk > /app/en.apk && \
    unzip -p /app/app.apks splits/base-xhdpi.apk > /app/xhdpi.apk

# Clean up
RUN rm /app/app.apks

# Create the output directory
RUN mkdir -p /app/build-output/

# Output the build artifacts
CMD ["sh", "-c", "cp /app/base.apk /app/armeabi_v7a.apk /app/en.apk /app/xhdpi.apk /app/build/app/outputs/bundle/release/app-release.aab /app/build-output/"]

The build had the following diffs:

danny@lw10:~/work/compare/com.bullbitcoin.mobile/0.3.2$ diff -r -q fromOfficial/ fromBuild/
Files fromOfficial/armeabi_v7a/AndroidManifest.xml and fromBuild/armeabi_v7a/AndroidManifest.xml differ
Files fromOfficial/armeabi_v7a/lib/armeabi-v7a/libapp.so and fromBuild/armeabi_v7a/lib/armeabi-v7a/libapp.so differ
Files fromOfficial/armeabi_v7a/lib/armeabi-v7a/libboltz_dart.so and fromBuild/armeabi_v7a/lib/armeabi-v7a/libboltz_dart.so differ
Files fromOfficial/armeabi_v7a/lib/armeabi-v7a/libflutter.so and fromBuild/armeabi_v7a/lib/armeabi-v7a/libflutter.so differ
Files fromOfficial/armeabi_v7a/lib/armeabi-v7a/liblwk_dart.so and fromBuild/armeabi_v7a/lib/armeabi-v7a/liblwk_dart.so differ
Only in fromOfficial/armeabi_v7a: META-INF
Only in fromOfficial/armeabi_v7a: stamp-cert-sha256
Files fromOfficial/armeabi_v7a.apk and fromBuild/armeabi_v7a.apk differ
Files fromOfficial/base/AndroidManifest.xml and fromBuild/base/AndroidManifest.xml differ
Files fromOfficial/base/assets/flutter_assets/NOTICES.Z and fromBuild/base/assets/flutter_assets/NOTICES.Z differ
Only in fromOfficial/base/META-INF: BNDLTOOL.RSA
Only in fromOfficial/base/META-INF: BNDLTOOL.SF
Only in fromOfficial/base/META-INF: MANIFEST.MF
Files fromOfficial/base/res/xml/splits0.xml and fromBuild/base/res/xml/splits0.xml differ
Files fromOfficial/base/resources.arsc and fromBuild/base/resources.arsc differ
Only in fromOfficial/base: stamp-cert-sha256
Files fromOfficial/base.apk and fromBuild/base.apk differ
Files fromOfficial/en/AndroidManifest.xml and fromBuild/en/AndroidManifest.xml differ
Only in fromOfficial/en: META-INF
Files fromOfficial/en/resources.arsc and fromBuild/en/resources.arsc differ
Only in fromOfficial/en: stamp-cert-sha256
Files fromOfficial/en.apk and fromBuild/en.apk differ
Files fromOfficial/xhdpi/AndroidManifest.xml and fromBuild/xhdpi/AndroidManifest.xml differ
Only in fromOfficial/xhdpi: META-INF
Files fromOfficial/xhdpi/resources.arsc and fromBuild/xhdpi/resources.arsc differ
Only in fromOfficial/xhdpi: stamp-cert-sha256
Files fromOfficial/xhdpi.apk and fromBuild/xhdpi.apk differ

@i5hi
Copy link
Collaborator

i5hi commented Sep 26, 2024

Thank you for creating that Dockerfile. I will add it to the repo and as we make progress I will update it.

So AndroidManifest.xml is the first differing file; which I am not sure why. I took a look at the existing AndroidManifest.xml file and there doesnt seem to be anything specific to the system building the project that is being added. Any ideas on what this could be about?

Regarding the libraries we are using; we had a bounty which a dev is working on and he found that if you use a different version of cargo as what we have used, the resulting binary differ.

I am building our android apks on a system running cargo 1.74.0 (ecb9851af 2023-10-18)

I assume we would also need a way of stripping the signature data from the binary.

I unfortunately am swamped with work at the moment to dig into the details but you've given me a great starting point.

Thanks again!

@xrviv
Copy link
Author

xrviv commented Oct 4, 2024

Hello @i5hi, thank you for the attentive and quick reply!

I apologize for the late reply, as we've been handling several issues at the moment.

I actually would not know how this came to differ unless we ran a diffoscope on it. We can derive clues from various providers though,

For Bitkey's AndroidManifest.xml:

Our review for Bitkey:

image

They also mentioned something about the resources.arsc mismatch here:

https://github.com/proto-at-block/bitkey/blob/main/app/verifiable-build/android/README.md#verification-notes

resources.arsc mismatch
Until recently, once we normalized the APK names and contents, we could just run diff -r to check for identity. Unfortunately Google Play has changed how they build resources.arsc. From our testing, it seems like they are using a [previously reserved byte](https://android.googlesource.com/platform/frameworks/base/+/master/libs/androidfw/include/androidfw/ResourceTypes.h#1405). When built using bundletool, that byte is always 0, thus making direct comparison using diff impossible.

Since resources are important part of the application, we're using aapt2 diff to check for differences between APKs from device and from bundletool.

As for the reasoning for the other files, they're WiP

@ethicnology
Copy link
Collaborator

Hello @xrviv,

I've tried your Dockerfile without success, here are the changes I did :

  • add device-spec.json (from your repo)
  • remove the ppa (openjdk-17-sdk is available in Ubuntu 20.04)
  • replace ANDROID_ROOT_SDK (deprecated) by ANDROID_HOME
  • use flutter with a non-root user
  • ENV legacy warnings

I have one remaining issue, the JAVA_HOME is invalid while apparently correctly sat-up (I kept your commands).

If you want to take a look, you can check the branch dockerfile or the last commit 400be42

I wonder how your environment let you use flutter commands as a root user, while flutter throw an error if you attempt it.

@ethicnology
Copy link
Collaborator

ethicnology commented Dec 30, 2024

removing

ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
ENV PATH=$JAVA_HOME/bin:$PATH

solved the JAVA_HOME error

@ethicnology ethicnology linked a pull request Dec 31, 2024 that will close this issue
@xrviv
Copy link
Author

xrviv commented Jan 7, 2025

Hi apologies, currently have my plate filled. Will get to this as soon as I can.

@ethicnology
Copy link
Collaborator

Don't bother, I reworked the Dockerfile and created PR #411 which seems to work for the Android apk.

We will merge it once more people have tested it.

@xrviv
Copy link
Author

xrviv commented Jan 8, 2025

Okay, I'm free now. Will proceed with this. Documenting my current attempts:

  1. https://gist.github.com/xrviv/f0d9dbe1547d262a0533a0a369a3f8e9 - FAIL. My own custom dockerfile
  2. https://gist.github.com/xrviv/c5925f3780c9bbcb330481f47c951fe8 - FAIL. My own custom dockerfile
  • The log mentions that Flutter's Gradle plugins (app_plugin_loader and main Gradle plugin) are being applied imperatively using the apply script method, which is deprecated. Flutter requires migrating to the declarative plugins block.
  • Gradle Configuration Issue for :path_provider_android: The error Could not get unknown property 'android' for project ':path_provider_android' suggests that the path_provider_android dependency might not be correctly configured for the Flutter project. This is likely due to missing or incompatible configuration in the build.gradle file for that module.
  1. will try manual build from here. https://gist.github.com/xrviv/7df822f0ffdfe142455ccb15163a49b7 - need to copy device-spec.json in build context... whoops.
  2. Another manual attempt - just noticed that this Dockerfile builds a single apk and not an App Bundle.

Diffs:

Only in com.bullbitcoin.mobile/: AndroidManifest.xml
Only in com.bullbitcoin.mobile/: androidx
Only in com.bullbitcoin.mobile/: assets
Only in com.bullbitcoin.mobile/: classes.dex
Only in /var/shared/apk/com.bullbitcoin.mobile/0.4.0-single/: com.bullbitcoin.mobile
Only in /var/shared/apk/com.bullbitcoin.mobile/0.4.0-single/: com.bullbitcoin.mobile_v25.apk
Only in com.bullbitcoin.mobile/: DebugProbesKt.bin
Only in com.bullbitcoin.mobile/: junit
Only in com.bullbitcoin.mobile/: kotlin
Only in com.bullbitcoin.mobile/: kotlin-tooling-metadata.json
Only in com.bullbitcoin.mobile/: lib
Only in com.bullbitcoin.mobile/: LICENSE-junit.txt
Only in com.bullbitcoin.mobile/: META-INF
Only in com.bullbitcoin.mobile/: play-services-basement.properties
Only in com.bullbitcoin.mobile/: play-services-base.properties
Only in com.bullbitcoin.mobile/: play-services-clearcut.properties
Only in com.bullbitcoin.mobile/: play-services-flags.properties
Only in com.bullbitcoin.mobile/: play-services-phenotype.properties
Only in com.bullbitcoin.mobile/: play-services-tasks.properties
Only in com.bullbitcoin.mobile/: play-services-vision-common.properties
Only in com.bullbitcoin.mobile/: play-services-vision.properties
Only in com.bullbitcoin.mobile/: res
Only in com.bullbitcoin.mobile/: resources.arsc
  1. Will modify to build app bundle. The adjusted Dockerfile.
  • Successful manual build - includes asciicast documentation - but not verifiable

    Diffs for armeabi_v7a.apk

    Binary files built/armeabi_v7a/AndroidManifest.xml and official/armeabi_v7a/AndroidManifest.xml differ
    Binary files built/armeabi_v7a/lib/armeabi-v7a/libapp.so and official/armeabi_v7a/lib/armeabi-v7a/libapp.so differ
    Binary files built/armeabi_v7a/lib/armeabi-v7a/libboltz_dart.so and official/armeabi_v7a/lib/armeabi-v7a/libboltz_dart.so differ
    Binary files built/armeabi_v7a/lib/armeabi-v7a/liblwk_dart.so and official/armeabi_v7a/lib/armeabi-v7a/liblwk_dart.so differ
    Binary files built/armeabi_v7a/lib/armeabi-v7a/libpayjoin_flutter.so and official/armeabi_v7a/lib/armeabi_v7a/libpayjoin_flutter.so differ
    Only in official/armeabi_v7a/: META-INF
    Only in official/armeabi_v7a/: stamp-cert-sha256
    

    Diffs for base.apk

    Binary files built/base/AndroidManifest.xml and official/base/AndroidManifest.xml differ
    Binary files built/base/res/xml/splits0.xml and official/base/res/xml/splits0.xml differ
    Binary files built/base/resources.arsc and official/base/resources.arsc differ
    Only in official/base/: stamp-cert-sha256
    

    Diffs for en.apk

    Binary files built/en/AndroidManifest.xml and official/en/AndroidManifest.xml differ
    Only in official/en: META-INF
    Binary files built/en/resources.arsc and official/en/resources.arsc differ
    Only in official/en: stamp-cert-sha256
    

    Diffs for xhdpi.apk

    Binary files built/xhdpi/AndroidManifest.xml and official/xhdpi/AndroidManifest.xml differ
    Only in official/xhdpi: META-INF
    Binary files built/xhdpi/resources.arsc and official/xhdpi/resources.arsc differ
    Only in official/xhdpi: stamp-cert-sha256
    

2025-01-09

  1. testing integration of com.bullbitcoin.mobile.sh and dockerfile with walletScrutinyCom's testAAB.sh
  1. will try again tomorrow
  2. ..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants