mirror of
https://github.com/logos-co/nomos-specs.git
synced 2025-02-02 10:34:50 +00:00
feat(cl/noir): provide an ergonomic Noir api for use within Python.
This commit is contained in:
parent
9390d481ba
commit
99d8f1a4a7
25
coordination-layer/README.md
Normal file
25
coordination-layer/README.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Coordination Layer
|
||||||
|
|
||||||
|
This module provides the executable specifications of the Coordination Layer (CL).
|
||||||
|
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
We are currently experimenting with the Noir Language. In order to run the specification, you will need to install Noir.
|
||||||
|
|
||||||
|
Follow the instructions here:
|
||||||
|
https://noir-lang.org/docs/getting_started/installation/
|
||||||
|
|
||||||
|
Verify the installation by running
|
||||||
|
|
||||||
|
```bash
|
||||||
|
noirup
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
From the repository root run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m unittest -v coordination-layer/test_*
|
||||||
|
```
|
0
coordination-layer/__init__.py
Normal file
0
coordination-layer/__init__.py
Normal file
4
coordination-layer/noir/.gitignore
vendored
Normal file
4
coordination-layer/noir/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
crates/*/Prover.toml
|
||||||
|
crates/*/Verifier.toml
|
||||||
|
proofs/*.proof
|
||||||
|
target/*
|
2
coordination-layer/noir/Nargo.toml
Normal file
2
coordination-layer/noir/Nargo.toml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[workspace]
|
||||||
|
members = ["crates/bigger"]
|
18
coordination-layer/noir/README.md
Normal file
18
coordination-layer/noir/README.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Noir Circuits
|
||||||
|
|
||||||
|
this directory holds all the circuits written in Noir, used by the CL specification.
|
||||||
|
|
||||||
|
Each circuit is it's own nargo package under the `crates/` directory.
|
||||||
|
|
||||||
|
## Creating a new circuit
|
||||||
|
|
||||||
|
1. inside `crates/`, run `nargo new <circuit name>`
|
||||||
|
2. update `./Nargo.toml` to include the new circuit in the workspace
|
||||||
|
|
||||||
|
## Testing circuits
|
||||||
|
|
||||||
|
Under `./noir`, simple run.
|
||||||
|
|
||||||
|
```
|
||||||
|
nargo test
|
||||||
|
```
|
7
coordination-layer/noir/crates/bigger/Nargo.toml
Normal file
7
coordination-layer/noir/crates/bigger/Nargo.toml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[package]
|
||||||
|
name = "bigger"
|
||||||
|
type = "bin"
|
||||||
|
authors = [""]
|
||||||
|
compiler_version = ">=0.22.0"
|
||||||
|
|
||||||
|
[dependencies]
|
19
coordination-layer/noir/crates/bigger/src/main.nr
Normal file
19
coordination-layer/noir/crates/bigger/src/main.nr
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
fn main(x: u32, y: pub u32) {
|
||||||
|
assert(x > y);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bigger() {
|
||||||
|
main(3, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test(should_fail)]
|
||||||
|
fn test_equal() {
|
||||||
|
main(2, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test(should_fail)]
|
||||||
|
fn test_smaller() {
|
||||||
|
main(1, 2);
|
||||||
|
}
|
71
coordination-layer/noir_constraint.py
Normal file
71
coordination-layer/noir_constraint.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
"""
|
||||||
|
This module provides the interface for loading, proving and verifying constraints written in noir.
|
||||||
|
|
||||||
|
The assumptions of this module:
|
||||||
|
- noir constraints are defined as a noir package in `./noir/crates/<constraint>/`
|
||||||
|
- ./noir is relative to this file
|
||||||
|
- noir constraints have already been compiled.
|
||||||
|
|
||||||
|
For ergonomics, one should provide python wrappers that understands the API of
|
||||||
|
the corresponding constraint.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import sh
|
||||||
|
import portalocker
|
||||||
|
import tempfile
|
||||||
|
import toml
|
||||||
|
|
||||||
|
NOIR_DIR = Path(__file__).resolve().parent / "noir"
|
||||||
|
LOCK_FILE = NOIR_DIR / ".CL.lock"
|
||||||
|
CONSTRAINTS_DIR = NOIR_DIR / "crates"
|
||||||
|
|
||||||
|
NARGO = sh.Command("nargo")
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Proof:
|
||||||
|
proof: str
|
||||||
|
|
||||||
|
|
||||||
|
class NoirConstraint:
|
||||||
|
def __init__(self, name: str):
|
||||||
|
self.name = name
|
||||||
|
assert self.noir_package_dir.exists() and self.noir_package_dir.is_dir()
|
||||||
|
self._prepare()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def noir_package_dir(self):
|
||||||
|
return CONSTRAINTS_DIR / self.name
|
||||||
|
|
||||||
|
def prove(self, params: dict):
|
||||||
|
with portalocker.TemporaryFileLock(LOCK_FILE):
|
||||||
|
with open(self.noir_package_dir / "Prover.toml", "w") as prover_f:
|
||||||
|
toml.dump(params, prover_f)
|
||||||
|
|
||||||
|
prove_res = self._nargo("prove", _return_cmd=True)
|
||||||
|
assert prove_res.exit_code == 0
|
||||||
|
|
||||||
|
with open(NOIR_DIR / "proofs" / f"{self.name}.proof", "r") as proof:
|
||||||
|
return Proof(proof.read())
|
||||||
|
|
||||||
|
def verify(self, params: dict, proof: Proof):
|
||||||
|
with portalocker.TemporaryFileLock(LOCK_FILE):
|
||||||
|
with open(self.noir_package_dir / "Verifier.toml", "w") as verifier_f:
|
||||||
|
toml.dump(params, verifier_f)
|
||||||
|
|
||||||
|
with open(NOIR_DIR / "proofs" / f"{self.name}.proof", "w") as proof_file:
|
||||||
|
proof_file.write(proof.proof)
|
||||||
|
verify_res = self._nargo("verify", _ok_code=[0, 1], _return_cmd=True)
|
||||||
|
return verify_res.exit_code == 0
|
||||||
|
|
||||||
|
def _nargo(self, *args, **kwargs):
|
||||||
|
return NARGO(*args, **kwargs, _cwd=self.noir_package_dir)
|
||||||
|
|
||||||
|
def _prepare(self):
|
||||||
|
check = self._nargo("check", _return_cmd=True)
|
||||||
|
assert check.exit_code == 0
|
||||||
|
compile = self._nargo("compile", _return_cmd=True)
|
||||||
|
assert compile.exit_code == 0
|
20
coordination-layer/test_noir_constraint.py
Normal file
20
coordination-layer/test_noir_constraint.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
from .noir_constraint import NoirConstraint
|
||||||
|
|
||||||
|
|
||||||
|
class TestNoirCoinstraint(TestCase):
|
||||||
|
def test_bigger(self):
|
||||||
|
# simple constraint that proves we know a number bigger than the provided
|
||||||
|
# public input.
|
||||||
|
bigger = NoirConstraint("bigger")
|
||||||
|
|
||||||
|
# x is the secret input, y is the public input
|
||||||
|
proof = bigger.prove({"x": "5", "y": "3"})
|
||||||
|
|
||||||
|
# The proof that we know an `x` that is bigger than `y` should verify
|
||||||
|
# Note, we must provide the public input that was used in the proof.
|
||||||
|
assert bigger.verify({"y": "3"}, proof)
|
||||||
|
|
||||||
|
# If we change the public input, the proof fails to verify.
|
||||||
|
assert not bigger.verify({"y": "4"}, proof)
|
@ -6,4 +6,7 @@ pycparser==2.21
|
|||||||
pysphinx==0.0.1
|
pysphinx==0.0.1
|
||||||
scipy==1.11.4
|
scipy==1.11.4
|
||||||
black==23.12.1
|
black==23.12.1
|
||||||
sympy==1.12
|
sympy==1.12
|
||||||
|
sh==2.0.6
|
||||||
|
toml==0.10.2
|
||||||
|
portalocker==2.8.2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user