Skip to content
Open
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
84 changes: 81 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,77 @@ jobs:
path: ./crates/contracts/build
retention-days: 1

reproducibility-check:
name: reproducibility-check (linux-amd64)
needs: [prepare, build-contracts]
runs-on: ubuntu-latest-8-cores
env:
TARGET: x86_64-unknown-linux-gnu
steps:
- uses: actions/checkout@v4

- name: Set SOURCE_DATE_EPOCH
shell: bash
run: |
echo "SOURCE_DATE_EPOCH=$(git log -1 --format=%ct)" >> $GITHUB_ENV

- name: Download contract artifacts
uses: actions/download-artifact@v4
with:
name: contract-artifacts
path: ./crates/contracts/build

- uses: actions-rust-lang/setup-rust-toolchain@v1
name: Rust Toolchain Setup
with:
toolchain: ${{ env.RUST_VERSION }}
target: ${{ env.TARGET }}
cache-on-failure: true
cache-key: reproducibility-${{ env.TARGET }}

- name: Verify vendored dependency archive
shell: bash
run: |
./scripts/release/verify-vendor-archive.sh --extract-check

- name: Build (pass 1)
shell: bash
run: |
./scripts/release/build-katana-vendored.sh --target "$TARGET"
SHA_ONE=$(sha256sum "./target/$TARGET/performance/katana" | awk '{ print $1 }')
echo "sha_one=$SHA_ONE" >> $GITHUB_ENV

- name: Build (pass 2)
shell: bash
run: |
rm -rf ./target
./scripts/release/build-katana-vendored.sh --target "$TARGET"
SHA_TWO=$(sha256sum "./target/$TARGET/performance/katana" | awk '{ print $1 }')
echo "sha_two=$SHA_TWO" >> $GITHUB_ENV

- name: Compare hashes
shell: bash
run: |
echo "Build #1 SHA256: $sha_one"
echo "Build #2 SHA256: $sha_two"
if [[ "$sha_one" != "$sha_two" ]]; then
echo "Reproducibility check failed: hashes differ."
exit 1
fi

- name: Summary
shell: bash
run: |
echo "## Reproducibility Check" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- target: \`$TARGET\`" >> $GITHUB_STEP_SUMMARY
echo "- SOURCE_DATE_EPOCH: \`$SOURCE_DATE_EPOCH\`" >> $GITHUB_STEP_SUMMARY
echo "- sha256(build #1): \`$sha_one\`" >> $GITHUB_STEP_SUMMARY
echo "- sha256(build #2): \`$sha_two\`" >> $GITHUB_STEP_SUMMARY

release:
name: ${{ matrix.job.target }} (${{ matrix.job.os }}${{ matrix.job.native_build == true && ', native' || '' }})
needs: [prepare, build-contracts]
needs: [prepare, build-contracts, reproducibility-check]
runs-on: ${{ matrix.job.os }}
env:
PLATFORM_NAME: ${{ matrix.job.platform }}
Expand Down Expand Up @@ -118,6 +186,11 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Set SOURCE_DATE_EPOCH
shell: bash
run: |
echo "SOURCE_DATE_EPOCH=$(git log -1 --format=%ct)" >> $GITHUB_ENV

- name: Download contract artifacts
uses: actions/download-artifact@v4
with:
Expand Down Expand Up @@ -204,17 +277,22 @@ jobs:
# See: https://github.com/jemalloc/jemalloc/issues/467
echo "JEMALLOC_SYS_WITH_LG_PAGE=16" >> $GITHUB_ENV

- name: Verify vendored dependency archive
shell: bash
run: |
./scripts/release/verify-vendor-archive.sh --extract-check

- name: Build binary
if: ${{ matrix.job.native_build == false }}
shell: bash
run: |
cargo build -p katana --bin katana --profile performance --target ${{ matrix.job.target }}
./scripts/release/build-katana-vendored.sh --target "${{ matrix.job.target }}"

- name: Build binary ( w/ cairo-native )
if: ${{ matrix.job.native_build == true }}
shell: bash
run: |
cargo build -p katana --bin katana --profile performance --features native --target ${{ matrix.job.target }}
./scripts/release/build-katana-vendored.sh --target "${{ matrix.job.target }}" --native

- name: Archive binaries
id: artifacts
Expand Down
38 changes: 37 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,26 @@ on:
- "release/**"
paths:
- "Cargo.toml"
- "Cargo.lock"
- "bin/**/*.rs"
- "bin/**/Cargo.toml"
- "crates/**/*.rs"
- "crates/**/Cargo.toml"
- "scripts/release/*.sh"
- "third_party/cargo/**"
- ".github/workflows/test.yml"

pull_request:
types: [opened, synchronize, ready_for_review]
paths:
- "Cargo.toml"
- "Cargo.lock"
- "bin/**/*.rs"
- "bin/**/Cargo.toml"
- "crates/**/*.rs"
- "crates/**/Cargo.toml"
- "scripts/release/*.sh"
- "third_party/cargo/**"
- ".github/workflows/test.yml"

# Cancel in progress workflow when a new one is triggered by running in a concurrency group
Expand All @@ -42,8 +48,38 @@ jobs:
- uses: actions/checkout@v3
- run: scripts/rust_fmt.sh --check

vendor-consistency:
runs-on: ubuntu-latest
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.draft == false)
container:
image: ghcr.io/dojoengine/katana-dev:latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
# Workaround for https://github.com/actions/runner-images/issues/6775
- run: git config --global --add safe.directory "*"

- name: Verify vendored archive and manifest
run: make vendor-verify

- name: Enforce vendor refresh when Cargo.lock changes
if: github.event_name == 'pull_request'
run: |
BASE_SHA="${{ github.event.pull_request.base.sha }}"
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
CHANGED_FILES="$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")"

if echo "$CHANGED_FILES" | grep -q "^Cargo.lock$"; then
if ! echo "$CHANGED_FILES" | grep -Eq "^third_party/cargo/(vendor\.tar\.gz\.part-[0-9]+|vendor\.tar\.gz\.sha256|VENDOR_MANIFEST\.lock)$"; then
echo "Cargo.lock changed but vendored dependency artifacts were not refreshed."
echo "Run: make vendor-refresh"
exit 1
fi
fi

generate-test-artifacts:
needs: [fmt]
needs: [fmt, vendor-consistency]
runs-on: ubuntu-latest
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.draft == false)
container:
Expand Down
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ SCARB_REQUIRED_VERSIONS := $(sort $(SCARB_VERSION) $(AVNU_SCARB_VERSION) $(VRF_S

.DEFAULT_GOAL := usage
.SILENT: clean
.PHONY: usage help check-llvm native-deps native-deps-macos native-deps-linux native-deps-windows build-explorer contracts tee-sev-snp clean deps install-scarb fixtures snos-artifacts db-compat-artifacts generate-db-fixtures install-pyenv
.PHONY: usage help check-llvm native-deps native-deps-macos native-deps-linux native-deps-windows build-explorer contracts tee-sev-snp clean deps install-scarb fixtures snos-artifacts db-compat-artifacts generate-db-fixtures install-pyenv vendor-refresh vendor-verify

usage help:
@echo "Usage:"
Expand All @@ -55,6 +55,8 @@ usage help:
@echo " snos-artifacts: Prepare SNOS tests artifacts."
@echo " db-compat-artifacts: Prepare database compatibility test artifacts."
@echo " generate-db-fixtures: Generate spawn-and-move and simple DB fixtures (requires scarb + sozo)."
@echo " vendor-refresh: Refresh the vendored Cargo dependency archive and manifest."
@echo " vendor-verify: Verify vendored Cargo archive and Cargo.lock consistency."
@echo " native-deps-macos: Install cairo-native dependencies for macOS."
@echo " native-deps-linux: Install cairo-native dependencies for Linux."
@echo " native-deps-windows: Install cairo-native dependencies for Windows."
Expand Down Expand Up @@ -96,6 +98,12 @@ build-explorer:

contracts: install-scarb $(CONTRACTS_BUILD_DIR)

vendor-refresh:
@./scripts/release/update-vendor-archive.sh

vendor-verify:
@./scripts/release/verify-vendor-archive.sh --extract-check

tee-sev-snp:
@echo "Building AMD SEV-SNP TEE VM components..."
@if [ -n "$(KATANA_BINARY)" ]; then \
Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- [Cairo Native](#cairo-native)
- [Explorer](#explorer)
- [Testing](#testing)
- [Release Reproducibility](#release-reproducibility)

## Development Setup

Expand Down Expand Up @@ -102,3 +103,25 @@ Once setup is complete, you can run the tests using:
```bash
cargo nextest run
```

## Release Reproducibility

Katana release binaries are built from a vendored Cargo dependency archive committed in this repository:

- `third_party/cargo/vendor.tar.gz.part-*`
- `third_party/cargo/vendor.tar.gz.sha256`
- `third_party/cargo/VENDOR_MANIFEST.lock`

The archive is committed as split parts to stay under GitHub's per-file size limit.

When dependencies change, refresh these artifacts in the same PR:

```bash
make vendor-refresh
```

You can verify integrity and lockfile consistency locally with:

```bash
make vendor-verify
```
57 changes: 57 additions & 0 deletions docs/release-reproducibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Release Reproducibility

Katana release binaries use a vendored Cargo dependency archive to reduce non-determinism from network/package source drift.

## Vendored Artifacts

- `third_party/cargo/vendor.tar.gz.part-*`
- `third_party/cargo/vendor.tar.gz.sha256`
- `third_party/cargo/VENDOR_MANIFEST.lock`

The archive is stored as split parts to remain below GitHub's per-file blob limit.

The manifest records:

- SHA-256 of `Cargo.lock`
- SHA-256 of the dependency archive
- archive path metadata used by CI/release validation

## Updating Vendored Dependencies

After any dependency update (`cargo add`, `cargo update`, manifest edits), refresh vendored artifacts:

```bash
make vendor-refresh
```

Commit all of the following in the same PR:

- `Cargo.lock`
- `third_party/cargo/vendor.tar.gz.part-*`
- `third_party/cargo/vendor.tar.gz.sha256`
- `third_party/cargo/VENDOR_MANIFEST.lock`

## Validation

Run local verification:

```bash
make vendor-verify
```

Verification checks:

- archive checksum matches `vendor.tar.gz.sha256`
- manifest archive hash matches the archive
- manifest lock hash matches `Cargo.lock`
- archive extract sanity checks (`cargo-home` layout)

CI enforces this for pull requests and blocks drift.

## Release Workflow Behavior

`release.yml` now:

- validates vendored artifacts before building
- builds Katana with `--locked --offline --frozen` via `scripts/release/build-katana-vendored.sh`
- runs a reproducibility gate (two clean Linux amd64 builds with matching SHA-256)
Loading
Loading