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
25 changes: 25 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Applies to every docker build rooted at the repo (apps/backend-relayer and
# scripts/docker-local/Dockerfile.deployer both use the repo as context).

node_modules
**/node_modules

contracts/stellar/target
contracts/evm/out
contracts/evm/cache

apps/frontend/.next
apps/backend-relayer/dist

.git
.github

.chains.env
.chains.anvil.log
.chains.anvil.pid
.relayer.log
.postgres.log

**/.env
**/.env.local
**/.env.test
153 changes: 153 additions & 0 deletions .github/workflows/contracts-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
name: Publish Contracts Bundle

# Builds Stellar WASMs, EVM artifacts, and the deposit verifier key, then
# publishes them as a tarball on two GitHub releases:

on:
push:
branches: [main]
paths:
- "contracts/**"
- "proof_circuits/**"
- "scripts/build_circuits.sh"
- ".github/workflows/contracts-release.yml"
workflow_dispatch:

permissions:
contents: write

concurrency:
group: contracts-release
cancel-in-progress: false

jobs:
build-and-release:
name: Build + release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Set short sha
id: sha
run: echo "short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"

# ── toolchains ──────────────────────────────────────────────────
- uses: dtolnay/rust-toolchain@stable

- name: Install wasm32v1-none target
run: rustup target add wasm32v1-none

- name: Cache cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
contracts/stellar/target
key: ${{ runner.os }}-cargo-stellar-${{ hashFiles('contracts/stellar/Cargo.lock') }}

- name: Install Stellar CLI
run: |
curl -Ls https://github.com/stellar/stellar-cli/releases/download/v23.3.0/stellar-cli-23.3.0-x86_64-unknown-linux-gnu.tar.gz -o /tmp/stellar-cli.tar.gz
mkdir -p "$HOME/.local/bin"
tar -xzf /tmp/stellar-cli.tar.gz -C "$HOME/.local/bin" stellar
chmod +x "$HOME/.local/bin/stellar"
echo "$HOME/.local/bin" >> "$GITHUB_PATH"

- uses: foundry-rs/foundry-toolchain@v1

# ── builds ──────────────────────────────────────────────────────
- name: Build Stellar WASMs
working-directory: contracts/stellar
run: |
stellar contract build --package verifier
stellar contract build --package merkle-manager
stellar contract build --package ad-manager
stellar contract build --package order-portal

- name: Build EVM artifacts
working-directory: contracts/evm
env:
FOUNDRY_PROFILE: default
run: forge build --silent

- name: Build deposit circuit VK
run: scripts/build_circuits.sh proof_circuits/deposits

# ── bundle ──────────────────────────────────────────────────────
# Layout mirrors the on-disk paths the docker-local deployer expects
# (deploy.ts reads from these directories verbatim), so the frontend
# dev just extracts the tarball into a bind-mount root.
- name: Assemble bundle
id: bundle
run: |
set -euo pipefail
STAGE="$RUNNER_TEMP/bundle"
WASM_DIR="$STAGE/contracts/stellar/target/wasm32v1-none/release"
EVM_OUT="$STAGE/contracts/evm/out"
VK_DIR="$STAGE/proof_circuits/deposits/target"
mkdir -p "$WASM_DIR" "$EVM_OUT" "$VK_DIR"

cp contracts/stellar/target/wasm32v1-none/release/ad_manager.wasm "$WASM_DIR/"
cp contracts/stellar/target/wasm32v1-none/release/order_portal.wasm "$WASM_DIR/"
cp contracts/stellar/target/wasm32v1-none/release/merkle_manager.wasm "$WASM_DIR/"
cp contracts/stellar/target/wasm32v1-none/release/verifier.wasm "$WASM_DIR/"

# Copy only the artifacts the deployer actually loads.
for c in OrderPortal AdManager MerkleManager Verifier wNativeToken ERC20Mock; do
mkdir -p "$EVM_OUT/${c}.sol"
cp contracts/evm/out/${c}.sol/*.json "$EVM_OUT/${c}.sol/"
done

cp proof_circuits/deposits/target/vk "$VK_DIR/vk"

TARBALL="$RUNNER_TEMP/contracts-bundle.tar.gz"
tar -C "$STAGE" -czf "$TARBALL" contracts proof_circuits

# Emit a manifest for quick eyeballing from the release page.
MANIFEST="$RUNNER_TEMP/contracts-bundle.manifest.txt"
{
echo "commit: $GITHUB_SHA"
echo "built: $(date -u +%FT%TZ)"
echo "size: $(du -h "$TARBALL" | cut -f1)"
echo "sha256: $(sha256sum "$TARBALL" | cut -d' ' -f1)"
echo
tar -tzf "$TARBALL"
} > "$MANIFEST"

echo "tarball=$TARBALL" >> "$GITHUB_OUTPUT"
echo "manifest=$MANIFEST" >> "$GITHUB_OUTPUT"

# ── immutable per-sha release ───────────────────────────────────
- name: Release contracts-${{ steps.sha.outputs.short }}
uses: softprops/action-gh-release@v2
with:
tag_name: contracts-${{ steps.sha.outputs.short }}
name: Contracts @ ${{ steps.sha.outputs.short }}
body: |
Bundled WASMs, EVM artifacts, and deposit VK built from `${{ github.sha }}`.

Consumed by `scripts/docker-local/up.sh` (defaults to `contracts-latest`;
pin this tag by exporting `CONTRACTS_BUNDLE_TAG=contracts-${{ steps.sha.outputs.short }}`).
files: |
${{ steps.bundle.outputs.tarball }}
${{ steps.bundle.outputs.manifest }}
make_latest: "false"

# ── rolling pointer for docker-local ────────────────────────────
- name: Update contracts-latest
uses: softprops/action-gh-release@v2
with:
tag_name: contracts-latest
name: Contracts (latest main)
body: |
Rolling pointer to the most recent contracts build from `main`.
Current commit: ${{ github.sha }}

`scripts/docker-local/up.sh` pulls this tarball by default.
files: |
${{ steps.bundle.outputs.tarball }}
${{ steps.bundle.outputs.manifest }}
make_latest: "false"
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
node_modules
target
target
scripts/docker-local/.artifacts/
scripts/docker-local/.env
19 changes: 19 additions & 0 deletions scripts/docker-local/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copy to `.env` next to docker-compose.yaml and fill in the addresses you
# want the local stack to fund. Both fields are optional — leave blank to
# skip that chain.
#
# cp scripts/docker-local/.env.example scripts/docker-local/.env
# $EDITOR scripts/docker-local/.env
# bash scripts/docker-local/up.sh

# Your MetaMask (or similar) address on anvil. Receives 100 ETH + 1,000,000
# TT (ERC20Mock test token) on first deploy.
DEV_EVM_ADDRESS=

# Your Stellar account G-strkey. Friendbot-funded with ~10k XLM on the
# local quickstart.
DEV_STELLAR_ADDRESS=

# Pin a specific contracts build (immutable per-sha release). Defaults to
# `contracts-latest` if unset.
# CONTRACTS_BUNDLE_TAG=contracts-abc1234
62 changes: 62 additions & 0 deletions scripts/docker-local/Dockerfile.deployer
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# syntax=docker/dockerfile:1.7
#
# Slim deployer image for the local docker stack.
#
# Only the runtime deploy toolkit is baked in (stellar CLI + node + pnpm).
# Contract artifacts (WASMs, EVM ABIs, deposit VK) are NOT built here — they
# are pulled by `up.sh` from the `contracts-latest` GitHub Release and
# bind-mounted into the container at the paths deploy.ts expects.
#
# Image build is ~1 min on a cold cache; rebuilds happen only when
# workspace manifests or the deploy scripts change.

FROM node:20-slim

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
curl \
jq \
&& rm -rf /var/lib/apt/lists/*

# Stellar CLI — runtime `contract deploy` / `contract invoke` only.
ARG STELLAR_CLI_VERSION=23.3.0
ARG STELLAR_CLI_SHA256=b3a5455d7113a53a8bd0f1ba0148a14b7aa7a46ee2f49c3b9277424775b309ad
RUN url="https://github.com/stellar/stellar-cli/releases/download/v${STELLAR_CLI_VERSION}/stellar-cli-${STELLAR_CLI_VERSION}-x86_64-unknown-linux-gnu.tar.gz" \
&& curl -fsSL "$url" -o /tmp/stellar.tgz \
&& echo "${STELLAR_CLI_SHA256} /tmp/stellar.tgz" | sha256sum -c - \
&& tar -xzf /tmp/stellar.tgz -C /usr/local/bin stellar \
&& chmod +x /usr/local/bin/stellar \
&& rm /tmp/stellar.tgz

RUN corepack enable && corepack prepare pnpm@10.10.0 --activate

WORKDIR /repo

# Cache-friendly pnpm install — manifests first, then the workspace sources
# the deployer actually executes.
COPY pnpm-workspace.yaml pnpm-lock.yaml package.json ./
COPY apps/backend-relayer/package.json apps/backend-relayer/
COPY apps/frontend/package.json apps/frontend/
COPY packages/proofbridge_mmr/package.json packages/proofbridge_mmr/
COPY scripts/relayer-e2e/package.json scripts/relayer-e2e/
COPY scripts/cross-chain-e2e/package.json scripts/cross-chain-e2e/
COPY contracts/stellar/tests/fixtures/package.json contracts/stellar/tests/fixtures/

RUN pnpm fetch --ignore-scripts

# Sources needed at runtime: backend-relayer for prisma schema/migrations,
# packages/* for workspace links, scripts/* for the deploy + seed CLIs.
COPY apps/backend-relayer apps/backend-relayer
COPY packages packages
COPY scripts scripts

RUN pnpm install --frozen-lockfile --offline --ignore-scripts \
&& pnpm --filter backend-relayer exec prisma generate

COPY scripts/docker-local/entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
Loading
Loading