feat(build): add scripts and Dockerfile to enable easy build on RPi

This commit is contained in:
Václav Pavlín 2026-01-15 14:59:12 +01:00
parent 0674fa2ac0
commit 8cd3be1cce
No known key found for this signature in database
GPG Key ID: B378FB31BB6D89A5
6 changed files with 1065 additions and 0 deletions

37
.dockerignore Normal file
View File

@ -0,0 +1,37 @@
# Docker build context ignore file
# Exclude files that don't need to be in the Docker build context
# Build artifacts
nomos-circuits-*/
prover-*/
verifier-*/
witness-generators/
proving-keys/
*.tar.gz
# Powers of Tau file (large, will be downloaded inside if needed)
*.ptau
# Circom build (will be done inside container)
circom/
# Generated circuit files
*_cpp/
*.r1cs
*.zkey
*_verification_key.json
# Git
.git/
.github/
# IDE
.vscode/
.idea/
*.swp
*.swo
# Cache
.docker-cache/
__pycache__/
*.pyc

View File

@ -43,6 +43,17 @@ host_arm64:
cmake .. -DTARGET_PLATFORM=aarch64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_arm64 && \
make -j$(nproc) -vvv && make install
host_linux_arm64_static:
rm -rf build_prover && mkdir build_prover && cd build_prover && \
cmake .. \
-DTARGET_PLATFORM=aarch64 \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=../package \
-DCMAKE_EXE_LINKER_FLAGS="-static -static-libstdc++ -static-libgcc -no-pie" \
-DOpenMP_gomp_LIBRARY=$(LIBGOMP_A) \
-DCMAKE_PREFIX_PATH=depends/gmp/package && \
make -j$(nproc) -vvv && make install
android:
rm -rf build_prover_android && mkdir build_prover_android && cd build_prover_android && \
cmake .. -DTARGET_PLATFORM=ANDROID -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_android -DBUILD_TESTS=OFF -DUSE_OPENMP=OFF && \

81
scripts/Dockerfile Normal file
View File

@ -0,0 +1,81 @@
# Dockerfile for building Logos Blockchain Circuits
# This provides an isolated build environment to avoid polluting the host system
#
# Usage:
# docker build -t logos-circuits-builder .
# docker run --rm -v $(pwd):/workspace logos-circuits-builder [OPTIONS]
#
# Or use the helper script:
# ./docker-build.sh [OPTIONS]
FROM ubuntu:22.04
# Avoid interactive prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive
# Install system dependencies
RUN apt-get update && apt-get install -y \
build-essential \
cmake \
libgmp-dev \
libsodium-dev \
nasm \
curl \
m4 \
nlohmann-json3-dev \
git \
xxd \
ca-certificates \
gnupg \
&& rm -rf /var/lib/apt/lists/*
# Install Node.js 20.x
RUN mkdir -p /etc/apt/keyrings \
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list \
&& apt-get update \
&& apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# Install snarkjs globally
RUN npm install -g snarkjs@latest
# Install Rust
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
ENV PATH="/root/.cargo/bin:${PATH}"
# Clone and build Circom
RUN git clone https://github.com/iden3/circom.git /opt/circom \
&& cd /opt/circom \
&& RUSTFLAGS="-A dead_code" cargo build --release \
&& RUSTFLAGS="-A dead_code" cargo install --path circom
# Verify installations
RUN circom --version && node --version && npm --version
# Set up working directory
WORKDIR /workspace
# Create entrypoint script
RUN echo '#!/bin/bash\n\
set -e\n\
cd /workspace\n\
\n\
# Mark all directories as safe for git (needed for mounted volumes with different ownership)\n\
# This is safe in a container context where we control the environment\n\
git config --global --add safe.directory "*"\n\
\n\
# Initialize git submodules if needed (including nested submodules like rapidsnark/depends/*)\n\
if [ -f .gitmodules ]; then\n\
git submodule update --init --recursive\n\
fi\n\
\n\
# Run the build script with provided arguments\n\
# Skip deps, circom, and snarkjs as they are already installed in the container\n\
exec ./scripts/build-local.sh --skip-deps --skip-circom --skip-snarkjs "$@"\n\
' > /entrypoint.sh && chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
# Default: run full build (pass --help to see options)
CMD []

103
scripts/README.md Normal file
View File

@ -0,0 +1,103 @@
# Scripts Directory
This directory contains build scripts for compiling the Logos Blockchain Circuits.
## Files
### [`build-local.sh`](build-local.sh)
The main local build script that replicates the GitHub Actions workflow for local execution on Linux. It handles the complete build pipeline including:
- Installing system dependencies (build-essential, cmake, libgmp-dev, etc.)
- Installing Rust and Circom compiler
- Installing Node.js and snarkjs
- Downloading Powers of Tau file (~3GB)
- Generating proving keys for all circuits (pol, poq, zksign, poc)
- Compiling witness generators
- Building prover and verifier from rapidsnark
- Creating the final release bundle
**Usage:**
```bash
./build-local.sh [OPTIONS]
```
**Options:**
| Option | Description |
|--------|-------------|
| `--version VERSION` | Set the version (default: v0.0.0-local) |
| `--skip-deps` | Skip installing system dependencies |
| `--skip-circom` | Skip Circom installation |
| `--skip-snarkjs` | Skip snarkjs installation |
| `--skip-ptau` | Skip Powers of Tau download |
| `--skip-proving-keys` | Skip proving key generation |
| `--skip-prover` | Skip prover/verifier compilation |
| `--skip-witness` | Skip witness generator compilation |
| `--circuit CIRCUIT` | Build only specified circuit (pol, poq, zksign, poc) |
| `--clean` | Clean all build artifacts before building |
| `--help` | Show help message |
### [`docker-build.sh`](docker-build.sh)
A wrapper script that runs the build inside a Docker container to avoid polluting your host system with dependencies.
**Usage:**
```bash
./docker-build.sh [OPTIONS]
```
All options are passed directly to `build-local.sh` inside the container.
**Examples:**
```bash
./docker-build.sh # Full build
./docker-build.sh --help # Show build-local.sh help
./docker-build.sh --circuit pol # Build only PoL circuit
./docker-build.sh --clean # Clean and rebuild
./docker-build.sh --skip-ptau # Skip Powers of Tau download
```
**Environment Variables:**
| Variable | Description |
|----------|-------------|
| `DOCKER_BUILD=0` | Skip rebuilding the Docker image |
| `DOCKER_NOCACHE=1` | Force rebuild Docker image without cache |
| `SKIP_INSTALL=true` | Install artifacts to `~/.nomos-circuits` after build |
### [`Dockerfile`](Dockerfile)
Defines the Docker build environment based on Ubuntu 22.04 with all required dependencies pre-installed:
- Build tools (gcc, cmake, make, nasm)
- Libraries (libgmp, libsodium, nlohmann-json)
- Node.js 20.x and snarkjs
- Rust and Circom compiler
The container automatically initializes git submodules and runs the build with `--skip-deps --skip-circom --skip-snarkjs` since these are pre-installed.
## Output
The build produces a tarball named `nomos-circuits-{VERSION}-{OS}-{ARCH}.tar.gz` containing:
```
nomos-circuits-v0.0.0-local-linux-x86_64/
├── VERSION
├── prover # Rapidsnark prover binary
├── verifier # Rapidsnark verifier binary
├── pol/
│ ├── witness_generator
│ ├── witness_generator.dat
│ ├── proving_key.zkey
│ └── verification_key.json
├── poq/
│ └── ...
├── zksign/
│ └── ...
└── poc/
└── ...
```
## Requirements
- **Local build:** Linux x86_64 or aarch64, root access for dependencies
- **Docker build:** Docker installed and running

707
scripts/build-local.sh Executable file
View File

@ -0,0 +1,707 @@
#!/usr/bin/env bash
#
# Local Build Script for Logos Blockchain Circuits
# This script replicates the GitHub Actions workflow for local execution on Linux.
#
# Usage:
# ./build-local.sh [OPTIONS]
#
# Options:
# --version VERSION Set the version (default: v0.0.0-local)
# --skip-deps Skip installing system dependencies
# --skip-circom Skip Circom installation (assumes circom is in PATH)
# --skip-snarkjs Skip snarkjs installation (assumes snarkjs is in PATH)
# --skip-ptau Skip Powers of Tau download (assumes file exists)
# --skip-proving-keys Skip proving key generation (assumes they exist)
# --skip-prover Skip prover/verifier compilation
# --skip-witness Skip witness generator compilation
# --circuit CIRCUIT Build only specified circuit (pol, poq, zksign, poc)
# --clean Clean all build artifacts before building
# --help Show this help message
#
# Requirements:
# - Linux x86_64
# - Root access (for installing dependencies) or pre-installed dependencies
# - Internet connection (for downloading dependencies)
#
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Logging functions
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Default configuration
VERSION="v0.0.0-local"
OS="linux"
# Auto-detect architecture
MACHINE_ARCH="$(uname -m)"
case "$MACHINE_ARCH" in
x86_64|amd64)
ARCH="x86_64"
;;
aarch64|arm64)
ARCH="aarch64"
;;
*)
ARCH="$MACHINE_ARCH"
;;
esac
PTAU_URL="https://storage.googleapis.com/zkevm/ptau/powersOfTau28_hez_final_17.ptau"
PTAU_FILE="powersOfTau28_hez_final_17.ptau"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Flags
SKIP_DEPS=false
SKIP_CIRCOM=false
SKIP_SNARKJS=false
SKIP_PTAU=false
SKIP_PROVING_KEYS=false
SKIP_PROVER=false
SKIP_WITNESS=false
CLEAN=false
SINGLE_CIRCUIT=""
# Circuit definitions
declare -A CIRCUITS=(
["pol"]="mantle/pol.circom:pol:PoL"
["poq"]="blend/poq.circom:poq:PoQ"
["zksign"]="mantle/signature.circom:signature:ZKSign"
["poc"]="mantle/poc.circom:poc:PoC"
)
# Parse command line arguments
parse_args() {
while [[ $# -gt 0 ]]; do
case $1 in
--version)
VERSION="$2"
shift 2
;;
--skip-deps)
SKIP_DEPS=true
shift
;;
--skip-circom)
SKIP_CIRCOM=true
shift
;;
--skip-snarkjs)
SKIP_SNARKJS=true
shift
;;
--skip-ptau)
SKIP_PTAU=true
shift
;;
--skip-proving-keys)
SKIP_PROVING_KEYS=true
shift
;;
--skip-prover)
SKIP_PROVER=true
shift
;;
--skip-witness)
SKIP_WITNESS=true
shift
;;
--circuit)
SINGLE_CIRCUIT="$2"
shift 2
;;
--clean)
CLEAN=true
shift
;;
--help)
head -n 25 "$0" | tail -n +2 | sed 's/^# //' | sed 's/^#//'
exit 0
;;
*)
log_error "Unknown option: $1"
exit 1
;;
esac
done
}
# Clean build artifacts
clean_artifacts() {
log_info "Cleaning build artifacts..."
# Clean circom build directories
rm -rf circom/ 2>/dev/null || true
# Clean rapidsnark build
if [[ -d "rapidsnark" ]]; then
cd rapidsnark
make clean 2>/dev/null || true
cd ..
fi
# Clean circuit build directories
for circuit_key in "${!CIRCUITS[@]}"; do
IFS=':' read -r circuit_path circuit_name display_name <<< "${CIRCUITS[$circuit_key]}"
circuit_dir=$(dirname "$circuit_path")
circuit_filestem=$(basename "$circuit_path" .circom)
rm -rf "${circuit_dir}/${circuit_filestem}_cpp" 2>/dev/null || true
rm -f "${circuit_dir}/${circuit_filestem}.r1cs" 2>/dev/null || true
rm -f "${circuit_dir}/${circuit_key}.zkey" 2>/dev/null || true
rm -f "${circuit_dir}/${circuit_key}-0.zkey" 2>/dev/null || true
rm -f "${circuit_dir}/${circuit_key}_verification_key.json" 2>/dev/null || true
done
# Clean bundle directories
rm -rf nomos-circuits-* 2>/dev/null || true
rm -rf prover-* 2>/dev/null || true
rm -rf verifier-* 2>/dev/null || true
rm -rf witness-generators/ 2>/dev/null || true
rm -rf proving-keys/ 2>/dev/null || true
log_success "Cleaned build artifacts"
}
# Check system requirements
check_requirements() {
log_info "Checking system requirements..."
# Check OS
if [[ "$(uname -s)" != "Linux" ]]; then
log_error "This script is designed for Linux. Detected: $(uname -s)"
exit 1
fi
# Check architecture
if [[ "$ARCH" != "x86_64" && "$ARCH" != "aarch64" ]]; then
log_warn "This script supports x86_64 and aarch64. Detected: $(uname -m)"
else
log_info "Detected architecture: $ARCH"
fi
log_success "System requirements check passed"
}
# Install system dependencies
install_dependencies() {
if [[ "$SKIP_DEPS" == true ]]; then
log_info "Skipping system dependency installation..."
return
fi
log_info "Installing system dependencies..."
# Detect package manager
if command -v apt-get &> /dev/null; then
sudo apt-get update -y
sudo apt-get install -y \
build-essential \
cmake \
libgmp-dev \
libsodium-dev \
nasm \
curl \
m4 \
nlohmann-json3-dev \
git
elif command -v dnf &> /dev/null; then
sudo dnf install -y \
gcc \
gcc-c++ \
make \
cmake \
gmp-devel \
libsodium-devel \
nasm \
curl \
m4 \
json-devel \
git
elif command -v pacman &> /dev/null; then
sudo pacman -S --noconfirm \
base-devel \
cmake \
gmp \
libsodium \
nasm \
curl \
m4 \
nlohmann-json \
git
else
log_error "Unsupported package manager. Please install dependencies manually:"
log_error " build-essential, cmake, libgmp-dev, libsodium-dev, nasm, curl, m4, nlohmann-json3-dev, git"
exit 1
fi
log_success "System dependencies installed"
}
# Install Rust and Circom
install_circom() {
if [[ "$SKIP_CIRCOM" == true ]]; then
log_info "Skipping Circom installation..."
if ! command -v circom &> /dev/null; then
log_error "circom not found in PATH. Please install it or remove --skip-circom"
exit 1
fi
return
fi
log_info "Installing Circom..."
# Check if Rust is installed
if ! command -v cargo &> /dev/null; then
log_info "Installing Rust..."
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source "$HOME/.cargo/env"
fi
# Clone and build Circom
if [[ ! -d "circom" ]]; then
git clone https://github.com/iden3/circom.git
fi
cd circom
RUSTFLAGS="-A dead_code" cargo build --release
RUSTFLAGS="-A dead_code" cargo install --path circom
cd ..
# Verify installation
circom --version
log_success "Circom installed successfully"
}
# Install Node.js and snarkjs
install_snarkjs() {
if [[ "$SKIP_SNARKJS" == true ]]; then
log_info "Skipping snarkjs installation..."
if ! command -v snarkjs &> /dev/null; then
log_error "snarkjs not found in PATH. Please install it or remove --skip-snarkjs"
exit 1
fi
return
fi
log_info "Installing snarkjs..."
# Check if Node.js is installed
if ! command -v node &> /dev/null; then
log_info "Installing Node.js..."
# Use NodeSource to install Node.js 20
if command -v apt-get &> /dev/null; then
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
elif command -v dnf &> /dev/null; then
curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
sudo dnf install -y nodejs
else
log_error "Please install Node.js 20 manually"
exit 1
fi
fi
# Install snarkjs globally
sudo npm install -g snarkjs@latest
# Verify installation
snarkjs --version || true
log_success "snarkjs installed successfully"
}
# Initialize git submodules
init_submodules() {
log_info "Initializing git submodules..."
git submodule update --init --recursive
log_success "Git submodules initialized"
}
# Download Powers of Tau file
download_ptau() {
if [[ "$SKIP_PTAU" == true ]]; then
log_info "Skipping Powers of Tau download..."
if [[ ! -f "$PTAU_FILE" ]]; then
log_error "Powers of Tau file not found: $PTAU_FILE"
exit 1
fi
return
fi
if [[ -f "$PTAU_FILE" ]]; then
log_info "Powers of Tau file already exists, skipping download..."
return
fi
log_info "Downloading Powers of Tau file (this may take a while, ~3GB)..."
curl -L -o "$PTAU_FILE" "$PTAU_URL"
log_success "Powers of Tau file downloaded"
}
# Generate proving key for a circuit
generate_proving_key() {
local circuit_key="$1"
if [[ ! -v CIRCUITS[$circuit_key] ]]; then
log_error "Unknown circuit: $circuit_key"
exit 1
fi
IFS=':' read -r circuit_path circuit_name display_name <<< "${CIRCUITS[$circuit_key]}"
local circuit_dir=$(dirname "$circuit_path")
local circuit_file=$(basename "$circuit_path")
local circuit_filestem=$(basename "$circuit_path" .circom)
log_info "Generating proving key for $display_name..."
cd "$circuit_dir"
# Generate R1CS
log_info " Generating R1CS constraints..."
circom --r1cs --O2 "$circuit_file"
# Determine the R1CS file name (some circuits have different names)
local r1cs_file="${circuit_filestem}.r1cs"
# Setup
log_info " Running Groth16 setup..."
snarkjs groth16 setup "$r1cs_file" "../$PTAU_FILE" "${circuit_key}-0.zkey"
# Contribute to ceremony
log_info " Contributing to ceremony..."
head -c 32 /dev/urandom | xxd -p -c 256 | snarkjs zkey contribute "${circuit_key}-0.zkey" "${circuit_key}.zkey" --name="LOCAL_BUILD" -v
# Export verification key
log_info " Exporting verification key..."
snarkjs zkey export verificationkey "${circuit_key}.zkey" "${circuit_key}_verification_key.json"
# Cleanup intermediate file
rm -f "${circuit_key}-0.zkey"
cd "$SCRIPT_DIR"
log_success "Proving key generated for $display_name"
}
# Generate all proving keys
generate_all_proving_keys() {
if [[ "$SKIP_PROVING_KEYS" == true ]]; then
log_info "Skipping proving key generation..."
return
fi
log_info "Generating proving keys for all circuits..."
local circuits_to_build
if [[ -n "$SINGLE_CIRCUIT" ]]; then
circuits_to_build=("$SINGLE_CIRCUIT")
else
circuits_to_build=("${!CIRCUITS[@]}")
fi
for circuit_key in "${circuits_to_build[@]}"; do
generate_proving_key "$circuit_key"
done
log_success "All proving keys generated"
}
# Compile witness generator for a circuit
compile_witness_generator() {
local circuit_key="$1"
if [[ ! -v CIRCUITS[$circuit_key] ]]; then
log_error "Unknown circuit: $circuit_key"
exit 1
fi
IFS=':' read -r circuit_path circuit_name display_name <<< "${CIRCUITS[$circuit_key]}"
local circuit_dir=$(dirname "$circuit_path")
local circuit_file=$(basename "$circuit_path")
local circuit_filestem=$(basename "$circuit_path" .circom)
local circuit_cpp_dir="${circuit_dir}/${circuit_filestem}_cpp"
log_info "Compiling witness generator for $display_name..."
cd "$circuit_dir"
# Generate C++ code for witness computation
log_info " Generating C++ code..."
circom --c --r1cs --no_asm --O2 "$circuit_file"
# Replace Makefile with our custom one
log_info " Copying custom Makefile..."
cp "$SCRIPT_DIR/.github/resources/witness-generator/Makefile" "${circuit_filestem}_cpp/Makefile"
# Compile the witness generator
log_info " Compiling..."
cd "${circuit_filestem}_cpp"
make PROJECT="$circuit_filestem" linux
cd "$SCRIPT_DIR"
log_success "Witness generator compiled for $display_name"
}
# Compile all witness generators
compile_all_witness_generators() {
if [[ "$SKIP_WITNESS" == true ]]; then
log_info "Skipping witness generator compilation..."
return
fi
log_info "Compiling witness generators for all circuits..."
local circuits_to_build
if [[ -n "$SINGLE_CIRCUIT" ]]; then
circuits_to_build=("$SINGLE_CIRCUIT")
else
circuits_to_build=("${!CIRCUITS[@]}")
fi
for circuit_key in "${circuits_to_build[@]}"; do
compile_witness_generator "$circuit_key"
done
log_success "All witness generators compiled"
}
# Download GMP archive if needed
download_gmp() {
local gmp_dir="rapidsnark/depends"
local gmp_file="gmp-6.2.1.tar.xz"
if [[ -f "$gmp_dir/$gmp_file" ]]; then
log_info "GMP archive already exists, skipping download..."
return
fi
log_info "Downloading GMP archive..."
mkdir -p "$gmp_dir"
curl -L -o "$gmp_dir/$gmp_file" "https://ftpmirror.gnu.org/gmp/gmp-6.2.1.tar.xz"
log_success "GMP archive downloaded"
}
# Compile prover and verifier
compile_prover_verifier() {
if [[ "$SKIP_PROVER" == true ]]; then
log_info "Skipping prover/verifier compilation..."
return
fi
log_info "Compiling prover and verifier..."
# Replace Makefile with our custom one
log_info " Replacing Makefile..."
cp ".github/resources/prover/Makefile" "rapidsnark/Makefile"
# Download GMP if needed
download_gmp
cd rapidsnark
# Build GMP (ignore exit code if already built)
log_info " Building GMP..."
./build_gmp.sh host || true
# Verify GMP is available
if [[ ! -d "depends/gmp/package" ]]; then
log_error "GMP package not found after build_gmp.sh"
exit 1
fi
# For ARM64, CMake expects package_aarch64 but build_gmp.sh host creates package
# Create symlink to fix the path mismatch
if [[ "$ARCH" == "aarch64" ]]; then
if [[ -d "depends/gmp/package" && ! -e "depends/gmp/package_aarch64" ]]; then
log_info " Creating symlink for ARM64 GMP package..."
ln -s package depends/gmp/package_aarch64
fi
fi
# Build prover and verifier based on architecture
log_info " Building prover and verifier (static) for $ARCH..."
if [[ "$ARCH" == "aarch64" ]]; then
make host_linux_arm64_static
else
make host_linux_x86_64_static
fi
cd "$SCRIPT_DIR"
log_success "Prover and verifier compiled"
}
# Create the unified release bundle
create_bundle() {
local bundle_name="nomos-circuits-${VERSION}-${OS}-${ARCH}"
log_info "Creating unified release bundle: $bundle_name"
# Create bundle directory structure
mkdir -p "${bundle_name}"/{pol,poq,zksign,poc}
# Create VERSION file
echo "$VERSION" > "${bundle_name}/VERSION"
# Copy prover and verifier
if [[ ! "$SKIP_PROVER" == true ]]; then
log_info " Copying prover and verifier..."
cp "rapidsnark/package/bin/prover" "${bundle_name}/prover"
cp "rapidsnark/package/bin/verifier" "${bundle_name}/verifier"
chmod +x "${bundle_name}/prover"
chmod +x "${bundle_name}/verifier"
fi
# Copy witness generators and proving keys for each circuit
local circuits_to_bundle
if [[ -n "$SINGLE_CIRCUIT" ]]; then
circuits_to_bundle=("$SINGLE_CIRCUIT")
else
circuits_to_bundle=("${!CIRCUITS[@]}")
fi
for circuit_key in "${circuits_to_bundle[@]}"; do
IFS=':' read -r circuit_path circuit_name display_name <<< "${CIRCUITS[$circuit_key]}"
local circuit_dir=$(dirname "$circuit_path")
local circuit_filestem=$(basename "$circuit_path" .circom)
local circuit_cpp_dir="${circuit_dir}/${circuit_filestem}_cpp"
log_info " Bundling $display_name..."
# Copy witness generator
if [[ ! "$SKIP_WITNESS" == true ]]; then
if [[ -f "${circuit_cpp_dir}/${circuit_filestem}" ]]; then
cp "${circuit_cpp_dir}/${circuit_filestem}" "${bundle_name}/${circuit_key}/witness_generator"
chmod +x "${bundle_name}/${circuit_key}/witness_generator"
fi
if [[ -f "${circuit_cpp_dir}/${circuit_filestem}.dat" ]]; then
cp "${circuit_cpp_dir}/${circuit_filestem}.dat" "${bundle_name}/${circuit_key}/witness_generator.dat"
fi
fi
# Copy proving key and verification key
if [[ ! "$SKIP_PROVING_KEYS" == true ]]; then
if [[ -f "${circuit_dir}/${circuit_key}.zkey" ]]; then
cp "${circuit_dir}/${circuit_key}.zkey" "${bundle_name}/${circuit_key}/proving_key.zkey"
fi
if [[ -f "${circuit_dir}/${circuit_key}_verification_key.json" ]]; then
cp "${circuit_dir}/${circuit_key}_verification_key.json" "${bundle_name}/${circuit_key}/verification_key.json"
fi
fi
done
# Create tarball
log_info " Creating tarball..."
tar -czf "${bundle_name}.tar.gz" "${bundle_name}"
log_success "Bundle created: ${bundle_name}.tar.gz"
# Print bundle contents
log_info "Bundle contents:"
tar -tzf "${bundle_name}.tar.gz" | head -50
}
# Print build summary
print_summary() {
echo ""
log_info "=========================================="
log_info "Build Summary"
log_info "=========================================="
log_info "Version: $VERSION"
log_info "OS: $OS"
log_info "Architecture: $ARCH"
echo ""
if [[ -n "$SINGLE_CIRCUIT" ]]; then
log_info "Built circuit: $SINGLE_CIRCUIT"
else
log_info "Built circuits: pol, poq, zksign, poc"
fi
echo ""
log_info "Skip flags:"
log_info " - Dependencies: $SKIP_DEPS"
log_info " - Circom: $SKIP_CIRCOM"
log_info " - snarkjs: $SKIP_SNARKJS"
log_info " - Powers of Tau: $SKIP_PTAU"
log_info " - Proving Keys: $SKIP_PROVING_KEYS"
log_info " - Prover/Verifier: $SKIP_PROVER"
log_info " - Witness Generators: $SKIP_WITNESS"
echo ""
local bundle_name="nomos-circuits-${VERSION}-${OS}-${ARCH}"
if [[ -f "${bundle_name}.tar.gz" ]]; then
local size=$(du -h "${bundle_name}.tar.gz" | cut -f1)
log_success "Output bundle: ${bundle_name}.tar.gz ($size)"
fi
log_info "=========================================="
}
# Main function
main() {
parse_args "$@"
echo ""
log_info "=========================================="
log_info "Logos Blockchain Circuits - Local Build"
log_info "=========================================="
log_info "Version: $VERSION"
log_info "Starting build process..."
echo ""
# Clean if requested
if [[ "$CLEAN" == true ]]; then
clean_artifacts
fi
# Check requirements
check_requirements
# Install dependencies
install_dependencies
# Initialize submodules
init_submodules
# Install Circom
install_circom
# Install snarkjs
install_snarkjs
# Download Powers of Tau
download_ptau
# Generate proving keys
generate_all_proving_keys
# Compile prover and verifier
compile_prover_verifier
# Compile witness generators
compile_all_witness_generators
# Create bundle
create_bundle
# Print summary
print_summary
log_success "Build completed successfully!"
}
# Run main function
main "$@"

126
scripts/docker-build.sh Executable file
View File

@ -0,0 +1,126 @@
#!/usr/bin/env bash
#
# Docker Build Script for Logos Blockchain Circuits
# This script builds and runs the circuit compilation in a Docker container
# to avoid polluting your host system.
#
# Usage:
# ./docker-build.sh [OPTIONS]
#
# Options:
# All options are passed directly to build-local.sh inside the container.
# See ./build-local.sh --help for available options.
#
# Examples:
# ./docker-build.sh # Full build
# ./docker-build.sh --help # Show build-local.sh help
# ./docker-build.sh --circuit pol # Build only PoL circuit
# ./docker-build.sh --clean # Clean and rebuild
# ./docker-build.sh --skip-ptau # Skip Powers of Tau download (if already exists)
#
# Advanced Options:
# DOCKER_BUILD=0 ./docker-build.sh # Skip rebuilding the Docker image
# DOCKER_NOCACHE=1 ./docker-build.sh # Force rebuild Docker image without cache
#
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Configuration
IMAGE_NAME="logos-circuits-builder"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"/..
DOCKER_BUILD="${DOCKER_BUILD:-1}"
DOCKER_NOCACHE="${DOCKER_NOCACHE:-0}"
SKIP_INSTALL=${SKIP_INSTALL:-false}
cd "$SCRIPT_DIR"
# Check if Docker is installed
if ! command -v docker &> /dev/null; then
log_error "Docker is not installed. Please install Docker first."
exit 1
fi
# Check if Docker daemon is running
if ! docker info &> /dev/null; then
log_error "Docker daemon is not running. Please start Docker first."
exit 1
fi
# Build the Docker image if needed
if [[ "$DOCKER_BUILD" == "1" ]]; then
log_info "Building Docker image: $IMAGE_NAME"
BUILD_ARGS=""
if [[ "$DOCKER_NOCACHE" == "1" ]]; then
BUILD_ARGS="--no-cache"
fi
ls
docker build $BUILD_ARGS -t "$IMAGE_NAME" -f ./scripts/Dockerfile .
log_success "Docker image built successfully"
else
log_info "Skipping Docker image build (DOCKER_BUILD=0)"
fi
# Run the build in Docker
log_info "Running build in Docker container..."
log_info "Arguments: $*"
# Use interactive mode if terminal is available, for better output
DOCKER_FLAGS="-it"
if [[ ! -t 0 ]]; then
DOCKER_FLAGS=""
fi
# Run the container with the workspace mounted
# --rm: Remove container after exit
# -v: Mount current directory to /workspace
# -v for ptau: Persist the Powers of Tau file to avoid re-downloading
docker run --rm $DOCKER_FLAGS \
-v "$SCRIPT_DIR:/workspace" \
-v "$SCRIPT_DIR/.docker-cache:/root/.cache" \
-e "TERM=${TERM:-xterm}" \
"$IMAGE_NAME" "$@"
log_success "Docker build completed!"
if [[ $SKIP_INSTALL == false ]]; then
log_info "Remember to install the built artifacts if needed."
exit 0
fi
DEFAULT_INSTALL_DIR="$HOME/.nomos-circuits"
log_info "Installing built artifacts to $DEFAULT_INSTALL_DIR"
mkdir -p "$DEFAULT_INSTALL_DIR"
# Default configuration
VERSION="v0.0.0-local"
OS="linux"
# Auto-detect architecture
MACHINE_ARCH="$(uname -m)"
case "$MACHINE_ARCH" in
x86_64|amd64)
ARCH="x86_64"
;;
aarch64|arm64)
ARCH="aarch64"
;;
*)
ARCH="$MACHINE_ARCH"
;;
esac
cp -r ./nomos-circuits-$VERSION-$OS-$ARCH/* "$DEFAULT_INSTALL_DIR/"