Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/release-reproducible.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,20 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract Rust version from Cargo.toml
id: rust_version
run: |
RUST_VERSION=$(cargo metadata --format-version 1 | jq -r '.packages[] | select(.name == "reth") | .rust_version' || echo "1")
echo "RUST_VERSION=$RUST_VERSION" >> $GITHUB_OUTPUT

- name: Build and push reproducible image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile.reproducible
push: true
build-args: |
RUST_VERSION=${{ steps.rust_version.outputs.RUST_VERSION }}
tags: |
${{ env.DOCKER_REPRODUCIBLE_IMAGE_NAME }}:${{ needs.extract-version.outputs.VERSION }}
${{ env.DOCKER_REPRODUCIBLE_IMAGE_NAME }}:latest
Expand Down
52 changes: 48 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ env:
CARGO_TERM_COLOR: always
DOCKER_IMAGE_NAME_URL: https://ghcr.io/${{ github.repository_owner }}/reth
DOCKER_OP_IMAGE_NAME_URL: https://ghcr.io/${{ github.repository_owner }}/op-reth
DEB_SUPPORTED_TARGETS: x86_64-unknown-linux-gnu aarch64-unknown-linux-gnu riscv64gc-unknown-linux-gnu

jobs:
dry-run:
Expand Down Expand Up @@ -73,6 +74,10 @@ jobs:
os: ubuntu-24.04
profile: maxperf
allow_fail: false
- target: x86_64-unknown-linux-gnu
os: ubuntu-24.04
profile: reproducible
allow_fail: false
- target: aarch64-unknown-linux-gnu
os: ubuntu-24.04
profile: maxperf
Expand Down Expand Up @@ -119,12 +124,34 @@ jobs:
echo "MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx --show-sdk-platform-version)" >> $GITHUB_ENV

- name: Build Reth
run: make PROFILE=${{ matrix.configs.profile }} ${{ matrix.build.command }}-${{ matrix.configs.target }}
if: ${{ !(matrix.build.binary == 'op-reth' && matrix.configs.profile == 'reproducible') }}
run: |
if [[ "${{ matrix.build.binary }}" == "reth" && "${{ matrix.configs.profile }}" == "reproducible" ]]; then
make build-reth-reproducible
else
make PROFILE=${{ matrix.configs.profile }} ${{ matrix.build.command }}-${{ matrix.configs.target }}
fi

- name: Build Reth deb package
if: ${{ matrix.build.binary == 'reth' && contains(env.DEB_SUPPORTED_TARGETS, matrix.configs.target) }}
run: make build-deb-${{ matrix.configs.target }} PROFILE=${{ matrix.configs.profile }} VERSION=${{ needs.extract-version.outputs.VERSION }}

- name: Move binary
run: |
mkdir artifacts
[[ "${{ matrix.configs.target }}" == *windows* ]] && ext=".exe"
mv "target/${{ matrix.configs.target }}/${{ matrix.configs.profile }}/${{ matrix.build.binary }}${ext}" ./artifacts

# Handle reproducible builds which always target x86_64-unknown-linux-gnu
if [[ "${{ matrix.build.binary }}" == "reth" && "${{ matrix.configs.profile }}" == "reproducible" ]]; then
mv "target/x86_64-unknown-linux-gnu/${{ matrix.configs.profile }}/${{ matrix.build.binary }}${ext}" ./artifacts
else
mv "target/${{ matrix.configs.target }}/${{ matrix.configs.profile }}/${{ matrix.build.binary }}${ext}" ./artifacts
fi

# Move deb packages if they exist
if [[ "${{ matrix.build.binary }}" == "reth" && "${{ env.DEB_SUPPORTED_TARGETS }}" == *"${{ matrix.configs.target }}"* ]]; then
mv "target/${{ matrix.configs.target }}/${{ matrix.configs.profile }}/${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}-${{ matrix.configs.profile }}.deb" ./artifacts
fi

- name: Configure GPG and create artifacts
env:
Expand All @@ -134,9 +161,12 @@ jobs:
export GPG_TTY=$(tty)
echo -n "$GPG_SIGNING_KEY" | base64 --decode | gpg --batch --import
cd artifacts
tar -czf ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}.tar.gz ${{ matrix.build.binary }}*
tar -czf ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}.tar.gz ${{ matrix.build.binary }}*[!.deb]
echo "$GPG_PASSPHRASE" | gpg --passphrase-fd 0 --pinentry-mode loopback --batch -ab ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}.tar.gz
mv *tar.gz* ..
if [[ -f "${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}-${{ matrix.configs.profile }}.deb" ]]; then
echo "$GPG_PASSPHRASE" | gpg --passphrase-fd 0 --pinentry-mode loopback --batch -ab ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}-${{ matrix.configs.profile }}.deb
fi
mv *tar.gz* *.deb* ..
shell: bash

- name: Upload artifact
Expand All @@ -153,6 +183,20 @@ jobs:
name: ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}.tar.gz.asc
path: ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}.tar.gz.asc

- name: Upload deb package
if: ${{ github.event.inputs.dry_run != 'true' && matrix.build.binary == 'reth' && contains(env.DEB_SUPPORTED_TARGETS, matrix.configs.target) }}
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}-${{ matrix.configs.profile }}.deb
path: ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}-${{ matrix.configs.profile }}.deb

- name: Upload deb package signature
if: ${{ github.event.inputs.dry_run != 'true' && matrix.build.binary == 'reth' && contains(env.DEB_SUPPORTED_TARGETS, matrix.configs.target) }}
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}-${{ matrix.configs.profile }}.deb.asc
path: ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}-${{ matrix.configs.profile }}.deb.asc

draft-release:
name: draft release
runs-on: ubuntu-latest
Expand Down
14 changes: 4 additions & 10 deletions .github/workflows/reproducible-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,18 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
with:
target: x86_64-unknown-linux-gnu
- name: Install cross main
run: |
cargo install cross --git https://github.com/cross-rs/cross
- name: Install cargo-cache
run: |
cargo install cargo-cache
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- name: Build Reth
run: |
make build-reproducible
mv target/x86_64-unknown-linux-gnu/release/reth reth-build-1
make build-reth-reproducible
mv target/x86_64-unknown-linux-gnu/reproducible/reth reth-build-1
- name: Clean cache
run: make clean && cargo cache -a
- name: Build Reth again
run: |
make build-reproducible
mv target/x86_64-unknown-linux-gnu/release/reth reth-build-2
make build-reth-reproducible
mv target/x86_64-unknown-linux-gnu/reproducible/reth reth-build-2
- name: Compare binaries
run: cmp reth-build-1 reth-build-2
6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,12 @@ inherits = "release"
lto = "fat"
codegen-units = 1

[profile.reproducible]
inherits = "release"
panic = "abort"
codegen-units = 1
incremental = false

[workspace.dependencies]
# reth
op-reth = { path = "crates/optimism/bin" }
Expand Down
16 changes: 8 additions & 8 deletions Dockerfile.reproducible
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# Use the Rust 1.88 image based on Debian Bookworm
FROM rust:1.88-bookworm AS builder
ARG RUST_VERSION=1
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this not make it less reproducible? before we used a specific version (1.88), this one shifts over time as new stables are released

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated CI pipeline to pass the same RUST_VERSION as defined in the root Cargo.toml. So this could only affect reproducibility if the Dockerfile is used outside of the CI pipeline run (e.g., building locally).

This change additionally removes the burden of constantly updating the Rust version in the Dockefile to match the project's root.


# Install specific version of libclang-dev
RUN apt-get update && apt-get install -y libclang-dev=1:14.0-55.7~deb12u1
FROM rust:$RUST_VERSION-bookworm AS builder

RUN apt-get update && apt-get install -y \
git \
libclang-dev=1:14.0-55.7~deb12u1

# Copy the project to the container
COPY ./ /app
WORKDIR /app

# Build the project with the reproducible settings
RUN make build-reproducible

RUN mv /app/target/x86_64-unknown-linux-gnu/release/reth /reth
RUN make build-reth-reproducible
RUN mv /app/target/x86_64-unknown-linux-gnu/reproducible/reth /reth

# Create a minimal final image with just the binary
FROM gcr.io/distroless/cc-debian12:nonroot-6755e21ccd99ddead6edc8106ba03888cbeed41a
Expand Down
55 changes: 31 additions & 24 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -64,34 +64,25 @@ install-op: ## Build and install the op-reth binary under `$(CARGO_HOME)/bin`.
build: ## Build the reth binary into `target` directory.
cargo build --bin reth --features "$(FEATURES)" --profile "$(PROFILE)"

.PHONY: build-reth
build-reth: ## Build the reth binary (alias for build target).
$(MAKE) build

# 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

.PHONY: build-reproducible
build-reproducible: ## Build the reth binary into `target` directory with reproducible builds. Only works for x86_64-unknown-linux-gnu currently

# `reproducible` only supports reth on x86_64-unknown-linux-gnu
build-%-reproducible:
@if [ "$*" != "reth" ]; then \
echo "Error: Reproducible builds are only supported for reth, not $*"; \
exit 1; \
fi
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 --bin reth --features "$(FEATURES)" --profile "release" --locked --target x86_64-unknown-linux-gnu
RUSTFLAGS="-C symbol-mangling-version=v0 -C strip=none -C link-arg=-Wl,--build-id=none -C metadata='' --remap-path-prefix $$(pwd)=." \
LC_ALL=C \
TZ=UTC \
cargo build --bin reth --features "$(FEATURES)" --profile "reproducible" --locked --target x86_64-unknown-linux-gnu

.PHONY: build-debug
build-debug: ## Build the reth binary into `target/debug` directory.
Expand Down Expand Up @@ -155,6 +146,22 @@ op-build-x86_64-apple-darwin:
op-build-aarch64-apple-darwin:
$(MAKE) op-build-native-aarch64-apple-darwin

build-deb-%:
@case "$*" in \
x86_64-unknown-linux-gnu|aarch64-unknown-linux-gnu|riscv64gc-unknown-linux-gnu) \
echo "Building debian package for $*"; \
;; \
*) \
echo "Error: Debian packages are only supported for x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, and riscv64gc-unknown-linux-gnu, not $*"; \
exit 1; \
;; \
esac
cargo install cargo-deb@3.6.0 --locked
cargo deb --profile $(PROFILE) --no-build --no-dbgsym --no-strip \
--target $* \
$(if $(VERSION),--deb-version "1~$(VERSION)") \
$(if $(VERSION),--output "target/$*/$(PROFILE)/reth-$(VERSION)-$*-$(PROFILE).deb")

# Create a `.tar.gz` containing a binary for a specific target.
define tarball_release_binary
cp $(CARGO_TARGET_DIR)/$(1)/$(PROFILE)/$(2) $(BIN_DIR)/$(2)
Expand Down
14 changes: 14 additions & 0 deletions bin/reth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@ repository.workspace = true
description = "Reth node implementation"
default-run = "reth"

[package.metadata.deb]
maintainer = "reth team"
depends = "$auto"
section = "network"
priority = "optional"
maintainer-scripts = "../../pkg/reth/debian/"
assets = [
"$auto",
["../../README.md", "usr/share/doc/reth/", "644"],
["../../LICENSE-APACHE", "usr/share/doc/reth/", "644"],
["../../LICENSE-MIT", "usr/share/doc/reth/", "644"],
]
systemd-units = { enable = false, start = false, unit-name = "reth", unit-scripts = "../../pkg/reth/debian" }

[lints]
workspace = true

Expand Down
13 changes: 13 additions & 0 deletions pkg/reth/debian/reth.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[Unit]
Description=Modular, contributor-friendly and blazing-fast implementation of the Ethereum protocol
Wants=network-online.target
After=network.target network-online.target

[Service]
Type=exec
DynamicUser=yes
StateDirectory=reth
ExecStart=/usr/bin/reth node --datadir %S/reth --log.file.max-files 0

[Install]
WantedBy=multi-user.target
Loading