From cb9b9c87f39e5f36f3a519a990277f3e95cf14c3 Mon Sep 17 00:00:00 2001 From: Solar Mithril Date: Wed, 13 Aug 2025 17:23:41 +0500 Subject: [PATCH 1/3] Add makefile command to create reproducible build --- Makefile | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Makefile b/Makefile index 62625a93..793478fc 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,26 @@ GIT_TAG ?= $(shell git describe --tags --abbrev=0) FEATURES ?= +# Environment variables for reproducible builds +# Initialize RUSTFLAGS +RUST_BUILD_FLAGS = +# Enable static linking to ensure reproducibility across builds +RUST_BUILD_FLAGS += --C target-feature=+crt-static +# Set the linker to use static libgcc to ensure reproducibility across builds +RUST_BUILD_FLAGS += -C link-arg=-static-libgcc +# Remove build ID from the binary to ensure reproducibility across builds +RUST_BUILD_FLAGS += -C link-arg=-Wl,--build-id=none +# Remove metadata hash from symbol names to ensure reproducible builds +RUST_BUILD_FLAGS += -C metadata='' +# Set timestamp from last git commit for reproducible builds +SOURCE_DATE ?= $(shell git log -1 --pretty=%ct) +# Disable incremental compilation to avoid non-deterministic artifacts +CARGO_INCREMENTAL_VAL = 0 +# Set C locale for consistent string handling and sorting +LOCALE_VAL = C +# Set UTC timezone for consistent time handling across builds +TZ_VAL = UTC + ##@ Help .PHONY: help @@ -31,6 +51,15 @@ build: ## Build (debug version) op-rbuilder: ## Build op-rbuilder (debug version) cargo build -p op-rbuilder --bin op-rbuilder --features "$(FEATURES)" +.PHONY: build-reproducible +build-reproducible: ## Build the reth binary into `target` directory with reproducible builds. Only works for x86_64-unknown-linux-gnu currently + SOURCE_DATE_EPOCH=$(SOURCE_DATE) \ + RUSTFLAGS="${RUST_BUILD_FLAGS} --remap-path-prefix $$(pwd)=." \ + CARGO_INCREMENTAL=${CARGO_INCREMENTAL_VAL} \ + LC_ALL=${LOCALE_VAL} \ + TZ=${TZ_VAL} \ + cargo build -p op-rbuilder --bin op-rbuilder --features "$(FEATURES)" --profile "release" --locked --target x86_64-unknown-linux-gnu --features "$(FEATURES)" + .PHONY: tdx-quote-provider tdx-quote-provider: ## Build tdx-quote-provider (debug version) cargo build -p tdx-quote-provider --bin tdx-quote-provider --features "$(FEATURES)" From 6243492d33d1a65874a90e4639d7974d55848651 Mon Sep 17 00:00:00 2001 From: Alex Hulbert Date: Wed, 13 Aug 2025 10:44:06 -0400 Subject: [PATCH 2/3] Remove unnecessary "unknown" target vendor --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 793478fc..9e712574 100644 --- a/Makefile +++ b/Makefile @@ -52,13 +52,13 @@ op-rbuilder: ## Build op-rbuilder (debug version) cargo build -p op-rbuilder --bin op-rbuilder --features "$(FEATURES)" .PHONY: build-reproducible -build-reproducible: ## Build the reth binary into `target` directory with reproducible builds. Only works for x86_64-unknown-linux-gnu currently +build-reproducible: ## Build the reth binary into `target` directory with reproducible builds SOURCE_DATE_EPOCH=$(SOURCE_DATE) \ RUSTFLAGS="${RUST_BUILD_FLAGS} --remap-path-prefix $$(pwd)=." \ CARGO_INCREMENTAL=${CARGO_INCREMENTAL_VAL} \ LC_ALL=${LOCALE_VAL} \ TZ=${TZ_VAL} \ - cargo build -p op-rbuilder --bin op-rbuilder --features "$(FEATURES)" --profile "release" --locked --target x86_64-unknown-linux-gnu --features "$(FEATURES)" + cargo build -p op-rbuilder --bin op-rbuilder --features "$(FEATURES)" --profile "release" --locked --features "$(FEATURES)" .PHONY: tdx-quote-provider tdx-quote-provider: ## Build tdx-quote-provider (debug version) From 882e2eac2f071e211574dfebb703a3f3b5a2b688 Mon Sep 17 00:00:00 2001 From: alexhulbert Date: Wed, 13 Aug 2025 15:20:58 -0400 Subject: [PATCH 3/3] Docker + CI for reproducible builds --- .github/workflows/docker_build.yaml | 12 +++++++- .github/workflows/release.yaml | 8 ++++-- .github/workflows/reproducible_verify.yaml | 33 ++++++++++++++++++++++ Dockerfile | 21 ++++++++++++++ 4 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/reproducible_verify.yaml diff --git a/.github/workflows/docker_build.yaml b/.github/workflows/docker_build.yaml index 1e619ca3..4e2b6ba9 100644 --- a/.github/workflows/docker_build.yaml +++ b/.github/workflows/docker_build.yaml @@ -46,6 +46,13 @@ jobs: runner: warp-ubuntu-latest-x64-16x - target: linux/arm64 runner: warp-ubuntu-latest-arm64-16x + docker_target: + - name: regular + target: rbuilder-runtime + tag_suffix: "" + - name: reproducible + target: rbuilder-reproducible-runtime + tag_suffix: "-reproducible" steps: - name: checkout sources uses: actions/checkout@v4 @@ -83,6 +90,9 @@ jobs: labels: ${{ steps.meta.outputs.labels }} platforms: ${{ matrix.configs.target }} push: true - tags: ${{ steps.meta.outputs.tags }} + target: ${{ matrix.docker_target.target }} + tags: | + ghcr.io/${{ github.repository }}/op-rbuilder:latest${{ matrix.docker_target.tag_suffix }} + ghcr.io/${{ github.repository }}/op-rbuilder:sha-${{ env.VERSION }}${{ matrix.docker_target.tag_suffix }} build-args: | RBUILDER_BIN=op-rbuilder diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3fc2b781..ad5df501 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -100,8 +100,12 @@ jobs: run: | git config --global --add safe.directory "$(pwd)" . $HOME/.cargo/env - cargo build --release --features=${{ matrix.features }} --target ${{ matrix.configs.target }} --package op-rbuilder - + SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) \ + RUSTFLAGS="--C target-feature=+crt-static -C link-arg=-static-libgcc -C link-arg=-Wl,--build-id=none -C metadata='' --remap-path-prefix=$(pwd)=." \ + CARGO_INCREMENTAL=0 \ + LC_ALL=C \ + TZ=UTC \ + cargo build --release --features=${{ matrix.features }} --locked --target ${{ matrix.configs.target }} --package op-rbuilder - name: Upload op-rbuilder artifact uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/reproducible_verify.yaml b/.github/workflows/reproducible_verify.yaml new file mode 100644 index 00000000..9880582c --- /dev/null +++ b/.github/workflows/reproducible_verify.yaml @@ -0,0 +1,33 @@ +name: Verify Reproducible Build + +on: + workflow_dispatch: + +jobs: + verify: + name: Verify reproducible builds + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - name: Build twice and compare + run: | + export REPRO_FLAGS="--C target-feature=+crt-static -C link-arg=-static-libgcc -C link-arg=-Wl,--build-id=none -C metadata='' --remap-path-prefix=$(pwd)=." + export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) + + RUSTFLAGS="$REPRO_FLAGS" CARGO_INCREMENTAL=0 LC_ALL=C TZ=UTC \ + cargo build --release --locked -p op-rbuilder + mv target/release/op-rbuilder build1 + + cargo clean + + RUSTFLAGS="$REPRO_FLAGS" CARGO_INCREMENTAL=0 LC_ALL=C TZ=UTC \ + cargo build --release --locked -p op-rbuilder + mv target/release/op-rbuilder build2 + + if cmp -s build1 build2; then + echo "✅ Builds are reproducible" + else + echo "❌ Builds differ" + exit 1 + fi diff --git a/Dockerfile b/Dockerfile index 5e9258c0..e1feccfb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -73,6 +73,21 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=$SCCACHE_DIR,sharing=locked \ cargo build --release --features="$FEATURES" --package=${RBUILDER_BIN} +# +# Reproducible builder container (deterministic source-date-epoch, no caching, no incremental builds) +# +FROM base AS rbuilder-reproducible +ARG RBUILDER_BIN +ARG FEATURES +WORKDIR /app +COPY . . +RUN SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) \ + RUSTFLAGS="--C target-feature=+crt-static -C link-arg=-static-libgcc -C link-arg=-Wl,--build-id=none -C metadata='' --remap-path-prefix=/app=." \ + CARGO_INCREMENTAL=0 \ + LC_ALL=C \ + TZ=UTC \ + cargo build --release --locked --features="$FEATURES" --package=${RBUILDER_BIN} + # Runtime container for rbuilder FROM gcr.io/distroless/cc-debian12 AS rbuilder-runtime ARG RBUILDER_BIN @@ -80,3 +95,9 @@ WORKDIR /app COPY --from=rbuilder /app/target/release/${RBUILDER_BIN} /app/rbuilder ENTRYPOINT ["/app/rbuilder"] +# Reproducible runtime container for rbuilder +FROM gcr.io/distroless/cc-debian12 AS rbuilder-reproducible-runtime +ARG RBUILDER_BIN +WORKDIR /app +COPY --from=rbuilder-reproducible /app/target/release/${RBUILDER_BIN} /app/rbuilder +ENTRYPOINT ["/app/rbuilder"]