mirror of
https://github.com/logos-co/nomos-specs.git
synced 2025-02-02 02:25:02 +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
|
||||
scipy==1.11.4
|
||||
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