Skip to content
Closed
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
88 changes: 88 additions & 0 deletions .cursorrules
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
description: Generate minimal, self‑explaining Python that follows Clean Code.
globs:
- "**/*.py"
alwaysApply: true
---

## Goals

* Minimize lines changed and files touched.
* Code must read as prose; names and structure should eliminate the need for commentary.
* Prefer composable, pure functions; classes only when state or polymorphism is essential.
* Never sacrifice clarity for brevity.
* Keep line width ≤ 80 characters; minimize vertical length while maintaining readability.

## Documentation Policy (Strict)

Only write documentation that conveys information unobvious from the code itself.

Allowed (concise docstrings fewer than five lines):
* invariants or algebraic laws
* side‑effects or required ordering with external systems
* references to external specifications or RFCs

Forbidden:
* restating parameters, returns, or implementation steps
* boilerplate headings like Args, Parameters, Returns, Raises, Example
* inline `#` comments repeating what the code states

The cursor engine deletes, on sight:
1. Any triple‑quoted string whose first non‑blank line starts with `"""` followed by a
capital letter. If the total length exceeds five lines it is always removed.
2. Any inline comment beginning with `#` where the remaining text duplicates or
trivially describes identifiers on that line.

## Interaction Strategy

* First output a **PLAN** (high‑level steps, affected files), wait for confirmation,
then apply only the confirmed step. Create new files only when explicitly requested
or when necessary for code organization and LLM context management.
* Disable auto "iterate on lints" behaviour; fix linter issues only when explicitly
requested.
* Keep context lean: open and modify only user‑specified files; resync the code
index before large edits.
* Encourage Notepads for recurring prompts to keep chats short.

## Style & Structure

* Explicit names that encode intent; avoid abbreviations and useless prefixes/suffixes.
* snake\_case for functions and variables, PascalCase for classes.
* Module‑level constants in SCREAMING\_SNAKE.
* Each function does one thing, returns one thing, and is ≤ 25 lines.
* Keep dependency graph acyclic; utilities live in `utils.py`, not in callers.
* Split files when they exceed LLM context windows or become too complex.

## Language Features

* Default to Python 3.12.
* `from __future__ import annotations` for postponed type hints.
* Annotate public function signatures and class attributes.
* Use `dataclass` or `NamedTuple` for simple aggregates.
* Prefer `match` over ≥ 3‑branch `if` ladders.

## Error Handling

* Raise the narrowest builtin exception that communicates intent.
* Never swallow exceptions; re‑raise with context using `raise … from err`.
* Guard external I/O with try/except + logging; keep business logic free of prints.

## Testing Hooks

* Functions performing I/O accept injectable dependencies (file‑like objects or
strategy callables).
* Side‑effectful functions are named accordingly (e.g., `save_report`).

## Forbidden

* Wildcard imports, magic numbers, global mutable state, commented‑out code, TODOs.
* Generating documentation or comments that repeat the code.
* Docstrings that do not meet the **Allowed** criteria.
* Inline comments that merely narrate obvious behaviour.
* Creating new files without explicit request or clear necessity.
* Deleting or disabling code to make tests pass; fix the underlying issue instead.

## Transformations

During refactors the engine automatically strips any docstring or inline comment
violating these rules, and enforces the Interaction Strategy above.
61 changes: 61 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Test

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v3

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Set up Rust
uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2024-02-01 # Pin to a specific nightly for reproducibility
override: true
components: rustfmt, clippy
target: x86_64-unknown-linux-gnu

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential

- name: Create and activate virtual environment
run: |
python -m venv .venv
echo "VIRTUAL_ENV=$GITHUB_WORKSPACE/.venv" >> $GITHUB_ENV
echo "$GITHUB_WORKSPACE/.venv/bin" >> $GITHUB_PATH

- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install maturin pytest pytest-cov pytest-asyncio
pip install -e ".[test]"

- name: Build Rust extension
run: |
cd src/zklora/libs/zklora_halo2
maturin develop --release

- name: Run tests
run: |
# Run Python tests with coverage report in terminal
python -m pytest tests/ -v --cov=src/zklora --cov-report=term-missing

# Run Rust tests
cd src/zklora/libs/zklora_halo2
cargo test --release -- --nocapture
56 changes: 54 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
*venv
__pycache__
*.log
.pytest_cache/
.coverage
htmlcov/
coverage.xml
.coverage.*
pytest_output.txt
tarpaulin-report.html
cargo_test_output.txt

# Development environments
.vscode
Expand All @@ -21,8 +29,6 @@ data
lora_onnx_params
intermediate_activations
proof_artifacts
*.ezkl
*.srs
input.json
witness.json
proof.json
Expand All @@ -47,3 +53,49 @@ build/
*.egg
*.whl
.pypirc

# Test artifacts
.tox/
.pytest_cache/
*.pyc
__pycache__/
.hypothesis/
.coverage.*
coverage/
.coverage
coverage.xml
nosetests.xml
coverage.lcov
.tarpaulin-report.html

# Binary files and compiled artifacts
*.so
*.dylib
*.dll
*.pyd
*.o
*.a
*.lib
*.exp
*.bin
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
*.dSYM/
*.su
*.idb
*.pdb
*.class
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
*.msi
*.msm
*.msp
11 changes: 11 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "zklora"
version = "0.1.0"
edition = "2021"

[lib]
name = "zklora"
path = "src/zklora/libs/zklora_halo2/src/lib.rs"

[workspace]
members = ["src/zklora/libs/zklora_halo2"]
60 changes: 60 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
[build-system]
requires = ["maturin>=1.0.0"]
build-backend = "maturin"

[project]
name = "zklora"
version = "0.1.0"
description = "Zero-knowledge proofs for LoRA using Halo2"
authors = [
{name = "ZKLoRA Team", email = "team@zklora.org"}
]
requires-python = ">=3.8"
dependencies = [
"numpy>=1.21.0",
"onnx>=1.12.0",
"onnxruntime>=1.12.0",
"blake3>=0.3.3",
"torch>=2.0.0",
"transformers>=4.30.0",
"peft>=0.4.0",
"merklelib>=0.2.2",
"merkly~=1.0.0",
]

[project.optional-dependencies]
test = [
"pytest>=7.0.0",
"pytest-asyncio>=0.18.0",
"pytest-cov>=3.0.0"
]

[tool.maturin]
python-source = "src"
features = ["pyo3/extension-module"]
module-name = "zklora.zklora_halo2"
bindings = "pyo3"
manifest-path = "src/zklora/libs/zklora_halo2/Cargo.toml"

[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
python_files = ["test_*.py"]
addopts = "--cov=src/zklora --cov-report=term-missing"

[tool.coverage.run]
source = ["src/zklora"]
omit = [
"tests/*",
"**/__init__.py",
]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise NotImplementedError",
"if __name__ == .__main__.:",
"pass",
"raise ImportError",
]
1 change: 0 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,6 @@ ZKLoRA is built upon these outstanding open source projects:
| [Transformers](https://github.com/huggingface/transformers) | State-of-the-art Natural Language Processing |
| [dusk-merkle](https://github.com/dusk-network/dusk-merkle) | Merkle tree implementation in Rust |
| [BLAKE3](https://github.com/BLAKE3-team/BLAKE3) | Cryptographic hash function |
| [EZKL](https://github.com/zkonduit/ezkl) | Zero-knowledge proof system for neural networks |
| [ONNX Runtime](https://github.com/microsoft/onnxruntime) | Cross-platform ML model inference |

<hr>
Expand Down
11 changes: 7 additions & 4 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
numpy
pytest
torch
transformers
numpy>=1.21.0
onnx>=1.12.0
onnxruntime>=1.12.0
pytest>=7.0.0
pytest-asyncio>=0.18.0
pytest-cov>=3.0.0
maturin>=1.0.0 # For building Rust extensions
33 changes: 33 additions & 0 deletions scripts/test_with_coverage.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash

# Exit on error and print commands
set -ex

# Ensure we're in the project root
cd "$(dirname "$0")/.."

# Install test dependencies if not already installed
if ! python -c "import pytest_cov" 2>/dev/null; then
pip install -e ".[test]"
fi

# Build Rust library first
echo "Building Rust library..."
cd src/zklora/libs/zklora_halo2
maturin develop --release
cd -

# Run Python tests with coverage
echo "Running Python tests with coverage..."
python -m pytest tests/ -v --cov=src/zklora --cov-report=xml --cov-report=term-missing

# Run Rust tests
echo "Running Rust tests..."
cd src/zklora/libs/zklora_halo2
cargo test --release -- --nocapture
cd -

# Print coverage report location
echo "Coverage reports:"
echo "- XML: coverage.xml"
echo "- HTML: htmlcov/index.html (if generated)"
39 changes: 39 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from setuptools import setup, find_packages
from setuptools.command.build_py import build_py
import subprocess
import sys

class BuildPyCommand(build_py):
def run(self):
# Build Rust library
subprocess.check_call([
"maturin", "build",
"--release",
"--bindings", "pyo3",
"--manifest-path", "src/zklora/libs/zklora_halo2/Cargo.toml",
"--strip"
])
build_py.run(self)

setup(
name="zklora",
version="0.1.0",
packages=find_packages(where="src", include=["zklora", "zklora.*"]),
package_dir={"": "src"},
install_requires=[
"numpy>=1.21.0",
"onnx>=1.12.0",
"onnxruntime>=1.12.0",
],
extras_require={
"test": [
"pytest>=7.0.0",
"pytest-asyncio>=0.18.0",
"pytest-cov>=3.0.0"
]
},
python_requires=">=3.8",
cmdclass={
'build_py': BuildPyCommand,
},
)
Loading
Loading