Files
aitbc/apps/zk-circuits/compile_cached.py
oib 825f157749 Update Python version requirements and fix compatibility issues
- Bump minimum Python version from 3.11 to 3.13 across all apps
- Add Python 3.11-3.13 test matrix to CLI workflow
- Document Python 3.11+ requirement in .env.example
- Fix Starlette Broadcast removal with in-process fallback implementation
- Add _InProcessBroadcast class for tests when Starlette Broadcast is unavailable
- Refactor API key validators to read live settings instead of cached values
- Update database models with explicit
2026-02-24 18:41:08 +01:00

128 lines
3.9 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Cached ZK Circuit Compiler
Uses the ZK cache system to speed up iterative circuit development.
Only recompiles when source files have changed.
"""
import subprocess
import sys
import time
from pathlib import Path
from zk_cache import ZKCircuitCache
def compile_circuit_cached(circuit_file: str, output_dir: str = None, use_cache: bool = True) -> dict:
"""
Compile a ZK circuit with caching support
Args:
circuit_file: Path to the .circom circuit file
output_dir: Output directory for compiled artifacts (auto-generated if None)
use_cache: Whether to use caching
Returns:
Dict with compilation results
"""
circuit_path = Path(circuit_file)
if not circuit_path.exists():
raise FileNotFoundError(f"Circuit file not found: {circuit_file}")
# Auto-generate output directory if not specified
if output_dir is None:
circuit_name = circuit_path.stem
output_dir = f"build/{circuit_name}"
output_path = Path(output_dir)
cache = ZKCircuitCache()
result = {
'cached': False,
'compilation_time': 0.0,
'cache_hit': False,
'circuit_file': str(circuit_path),
'output_dir': str(output_path)
}
# Check cache first
if use_cache:
cached_result = cache.get_cached_artifacts(circuit_path, output_path)
if cached_result:
print(f"✅ Cache hit for {circuit_file} - skipping compilation")
result['cache_hit'] = True
result['compilation_time'] = cached_result.get('compilation_time', 0.0)
return result
print(f"🔧 Compiling {circuit_file}...")
# Create output directory
output_path.mkdir(parents=True, exist_ok=True)
# Build circom command
cmd = [
"circom", str(circuit_path),
"--r1cs", "--wasm", "--sym", "--c",
"-o", str(output_path)
]
# Execute compilation
start_time = time.time()
try:
subprocess.run(cmd, check=True, capture_output=True, text=True)
compilation_time = time.time() - start_time
# Cache successful compilation
if use_cache:
cache.cache_artifacts(circuit_path, output_path, compilation_time)
result['cached'] = True
result['compilation_time'] = compilation_time
print(f"✅ Compiled successfully in {compilation_time:.3f}s")
return result
except subprocess.CalledProcessError as e:
print(f"❌ Compilation failed: {e}")
result['error'] = str(e)
result['cached'] = False
return result
def main():
"""CLI interface for cached circuit compilation"""
import argparse
parser = argparse.ArgumentParser(description='Cached ZK Circuit Compiler')
parser.add_argument('circuit_file', help='Path to the .circom circuit file')
parser.add_argument('--output-dir', '-o', help='Output directory for compiled artifacts')
parser.add_argument('--no-cache', action='store_true', help='Disable caching')
parser.add_argument('--stats', action='store_true', help='Show cache statistics')
args = parser.parse_args()
if args.stats:
cache = ZKCircuitCache()
stats = cache.get_cache_stats()
print(f"Cache Statistics:")
print(f" Entries: {stats['entries']}")
print(f" Total Size: {stats['total_size_mb']:.2f} MB")
print(f" Cache Directory: {stats['cache_dir']}")
return
# Compile circuit
result = compile_circuit_cached(
args.circuit_file,
args.output_dir,
not args.no_cache
)
if result.get('cached') or result.get('cache_hit'):
if result.get('cache_hit'):
print("🎯 Used cached compilation")
else:
print(f"✅ Compiled successfully in {result['compilation_time']:.3f}s")
else:
print("❌ Compilation failed")
sys.exit(1)
if __name__ == "__main__":
main()