Skip to content

Commit 85182a1

Browse files
committed
provide reproducible binary build
1 parent 0aac023 commit 85182a1

File tree

4 files changed

+199
-0
lines changed

4 files changed

+199
-0
lines changed

.cargo/config.toml

Whitespace-only changes.

.github/workflows/release-tee.yml

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
name: release-tee
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
tag:
7+
description: "Release tag (e.g., v1.7.0). If empty, uses version from Cargo.toml"
8+
type: string
9+
required: false
10+
11+
env:
12+
CARGO_TERM_COLOR: always
13+
14+
permissions:
15+
id-token: write # OIDC token for Sigstore signing
16+
attestations: write # Persist attestations
17+
contents: write # Release artifact upload
18+
19+
jobs:
20+
prepare:
21+
runs-on: ubuntu-latest
22+
outputs:
23+
tag_name: ${{ steps.release_info.outputs.tag_name }}
24+
steps:
25+
- uses: actions/checkout@v4
26+
- name: Get version
27+
id: release_info
28+
run: |
29+
if [[ -n "${{ github.event.inputs.tag }}" ]]; then
30+
echo "tag_name=${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT
31+
else
32+
cargo install cargo-get
33+
echo "tag_name=v$(cargo get workspace.package.version)" >> $GITHUB_OUTPUT
34+
fi
35+
36+
build-contracts:
37+
runs-on: ubuntu-latest
38+
needs: prepare
39+
container:
40+
image: ghcr.io/dojoengine/katana-dev:latest
41+
steps:
42+
- uses: actions/checkout@v4
43+
- name: Build contracts
44+
run: make contracts
45+
- name: Upload contract artifacts
46+
uses: actions/upload-artifact@v4
47+
with:
48+
name: contract-artifacts
49+
path: ./crates/contracts/build
50+
retention-days: 1
51+
52+
reproducible-build:
53+
name: Reproducible TEE Build
54+
needs: [prepare, build-contracts]
55+
runs-on: ubuntu-latest-8-cores
56+
outputs:
57+
binary-hash: ${{ steps.hash.outputs.sha384 }}
58+
59+
steps:
60+
- name: Checkout repository
61+
uses: actions/checkout@v4
62+
63+
- name: Download contract artifacts
64+
uses: actions/download-artifact@v4
65+
with:
66+
name: contract-artifacts
67+
path: ./crates/contracts/build
68+
69+
- name: Set up Docker Buildx
70+
uses: docker/setup-buildx-action@v3
71+
72+
- name: Build reproducible binary
73+
run: |
74+
docker build \
75+
-f reproducible.Dockerfile \
76+
-t katana-reproducible:${{ needs.prepare.outputs.tag_name }} \
77+
--no-cache \
78+
.
79+
80+
- name: Extract binary from container
81+
run: |
82+
docker create --name katana-extract katana-reproducible:${{ needs.prepare.outputs.tag_name }}
83+
docker cp katana-extract:/katana ./katana-reproducible
84+
docker rm katana-extract
85+
86+
- name: Calculate binary hash
87+
id: hash
88+
run: |
89+
SHA384=$(sha384sum ./katana-reproducible | cut -d ' ' -f 1)
90+
echo "sha384=${SHA384}" >> $GITHUB_OUTPUT
91+
echo "Binary SHA-384: ${SHA384}"
92+
93+
- name: Archive reproducible binary
94+
env:
95+
VERSION_NAME: ${{ needs.prepare.outputs.tag_name }}
96+
run: |
97+
tar -czvf "katana_${VERSION_NAME}_linux_amd64_tee.tar.gz" katana-reproducible
98+
sha384sum katana-reproducible > "katana_${VERSION_NAME}_linux_amd64_tee.sha384"
99+
100+
- name: Generate build provenance attestation
101+
id: attest
102+
uses: actions/attest-build-provenance@v2
103+
with:
104+
subject-path: ./katana-reproducible
105+
106+
- name: Upload release artifacts
107+
uses: actions/upload-artifact@v4
108+
with:
109+
name: tee-release-artifacts
110+
path: |
111+
katana_${{ needs.prepare.outputs.tag_name }}_linux_amd64_tee.tar.gz
112+
katana_${{ needs.prepare.outputs.tag_name }}_linux_amd64_tee.sha384
113+
114+
- name: Summary
115+
run: |
116+
echo "## TEE Reproducible Build Complete" >> $GITHUB_STEP_SUMMARY
117+
echo "" >> $GITHUB_STEP_SUMMARY
118+
echo "**Version:** ${{ needs.prepare.outputs.tag_name }}" >> $GITHUB_STEP_SUMMARY
119+
echo "**SHA-384:** \`${{ steps.hash.outputs.sha384 }}\`" >> $GITHUB_STEP_SUMMARY
120+
echo "" >> $GITHUB_STEP_SUMMARY
121+
echo "### Verify Attestation" >> $GITHUB_STEP_SUMMARY
122+
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
123+
echo "gh attestation verify ./katana-reproducible --repo ${{ github.repository }}" >> $GITHUB_STEP_SUMMARY
124+
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY

crates/tee/README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,37 @@ The quote contains:
5858
- Quote generation requires hardware access; quote generation will return errors on unsupported platforms
5959
- The 64-byte report data is a Poseidon hash of `H_poseidon(state_root, block_hash)`, padded with zeros
6060

61+
## Reproducible Builds
62+
63+
For TEE deployments, verifiable builds are essential. The release pipeline produces a reproducible TEE binary with signed attestation.
64+
65+
### Verify Build Attestation
66+
67+
```bash
68+
# Download artifacts from workflow run
69+
gh run download <run-id> --name tee-release-artifacts --repo dojoengine/katana
70+
tar -xzf katana_v1.7.0_linux_amd64_tee.tar.gz
71+
gh attestation verify ./katana-reproducible --repo dojoengine/katana
72+
```
73+
74+
### Reproduce Locally
75+
76+
```bash
77+
git clone https://github.com/dojoengine/katana.git && cd katana
78+
git checkout v1.7.0
79+
docker build -f reproducible.Dockerfile -t katana-verify .
80+
docker create --name verify katana-verify
81+
docker cp verify:/katana ./katana-local && docker rm verify
82+
sha384sum ./katana-local # Should match published hash
83+
```
84+
85+
### Build Details
86+
87+
- **Base**: `rust:1.86.0-slim-bookworm` (pinned by digest)
88+
- **Target**: `x86_64-unknown-linux-musl` (static linking)
89+
- **Profile**: `performance` (fat LTO, single codegen unit)
90+
- **SOURCE_DATE_EPOCH**: `1735689600` (2025-01-01 00:00:00 UTC)
91+
6192
## References
6293

6394
### AMD SEV-SNP

reproducible.Dockerfile

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Reproducible build Dockerfile for Katana TEE
2+
#
3+
# Produces bit-for-bit identical builds across different machines.
4+
#
5+
# Usage:
6+
# docker build -f reproducible.Dockerfile -t katana-reproducible .
7+
# docker create --name extract katana-reproducible
8+
# docker cp extract:/katana ./katana-reproducible
9+
# docker rm extract
10+
11+
# Pin Rust image by digest (rust:1.86.0-slim-bookworm for amd64)
12+
FROM rust@sha256:a044f7ab9a762f95be2ee7eb2c49e4d4a4ec60011210de9f7da01d552cae3a55 AS builder
13+
14+
# Install musl toolchain for static linking
15+
RUN apt-get update && apt-get install -y --no-install-recommends \
16+
musl-tools \
17+
musl-dev \
18+
&& rm -rf /var/lib/apt/lists/*
19+
20+
RUN rustup target add x86_64-unknown-linux-musl
21+
22+
WORKDIR /build
23+
24+
# Reproducibility environment variables
25+
ENV SOURCE_DATE_EPOCH=1735689600 \
26+
RUSTFLAGS="--remap-path-prefix=/build=/build --remap-path-prefix=/root/.cargo=/cargo -C target-feature=+crt-static" \
27+
CARGO_HOME=/cargo \
28+
LANG=C.UTF-8
29+
30+
# Copy source (respects .dockerignore)
31+
COPY . .
32+
33+
# Build static binary
34+
RUN cargo build \
35+
--locked \
36+
--target x86_64-unknown-linux-musl \
37+
--bin katana \
38+
--profile performance
39+
40+
RUN cp /build/target/x86_64-unknown-linux-musl/performance/katana /katana
41+
42+
# Minimal final stage
43+
FROM scratch AS final
44+
COPY --from=builder /katana /katana

0 commit comments

Comments
 (0)