Skip to content
Open
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
316 changes: 309 additions & 7 deletions Cargo.lock

Large diffs are not rendered by default.

11 changes: 8 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
[workspace]
members = [
"core"
members = [
"core",
"lowering",
"ir"
]
resolver = "2"

[workspace.package]
version = "0.3.0"
version = "0.5.3"
authors = ["Daniel Dominguez (Veridise) <daniel@veridise.com>"]
edition = "2024"
rust-version = "1.85"
readme = "README.md"
repository = "https://github.com/project-llzk/haloumi"
license-file = "LICENSE"
categories = ["compilers"]
keywords = ["halo2", "llzk", "haloumi"]

[workspace.dependencies]
ff = "0.13"
Expand All @@ -20,4 +24,5 @@ internment = "0.8.6"
num-bigint = "0.4"
log = "0.4"
eqv = "0.1"
bit-set = "0.8"

1 change: 1 addition & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ rust-version = {workspace = true}
readme = "README.md"
repository = {workspace = true}
license-file = {workspace = true}
categories = {workspace = true}

[dependencies]
ff.workspace = true
Expand Down
16 changes: 16 additions & 0 deletions core/src/constraints.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//! Types related to constraints.

use crate::{
felt::Felt,
query::Fixed,
table::{Any, Column},
};

/// Types of copy constraints.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum CopyConstraint {
/// A copy constraint between two cells.
Cells(Column<Any>, usize, Column<Any>, usize),
/// Constraints a fixed cell to a constant value.
Fixed(Column<Fixed>, usize, Felt),
}
67 changes: 63 additions & 4 deletions core/src/felt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,35 @@
use ff::PrimeField;
use internment::Intern;
use num_bigint::BigUint;
use std::ops::{Add, AddAssign, Deref, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign};
use std::ops::{Add, AddAssign, Deref, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign};

/// Interned value of the prime of a finite field.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Prime(Intern<BigUint>);

impl Prime {
/// Creates the prime from the given [`PrimeField`].
fn new<F: PrimeField>() -> Self {
pub fn new<F: PrimeField>() -> Self {
let f = -F::ONE;
Self(Intern::new(
BigUint::from_bytes_le(f.to_repr().as_ref()) + 1usize,
))
}

fn value(&self) -> &BigUint {
/// Returns the value of the prime.
pub fn value(&self) -> &BigUint {
self.0.as_ref()
}

fn minus_one(&self) -> Felt {
Felt::from_parts(self.value() - 1usize, *self)
}
}

impl std::fmt::Display for Prime {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.value())
}
}

/// Lightweight representation of a constant value.
Expand All @@ -42,6 +53,14 @@ impl Felt {
}
}

/// Creates a new felt from its raw parts.
pub fn from_parts(value: BigUint, prime: Prime) -> Self {
Self {
value: Intern::new(value),
prime,
}
}

/// Returns the value of the field prime.
pub fn prime(&self) -> Prime {
self.prime
Expand All @@ -64,6 +83,17 @@ impl Felt {
prime: self.prime,
}
}

/// Returns true if the felt represents -1 mod P.
pub fn is_minus_one(&self) -> bool {
*self == self.prime().minus_one()
}
}

impl<F: PrimeField> From<F> for Felt {
fn from(value: F) -> Self {
Self::new(value)
}
}

impl std::fmt::Debug for Felt {
Expand Down Expand Up @@ -111,6 +141,20 @@ impl Rem for Felt {
}
}

impl Rem<Prime> for Felt {
type Output = Self;

fn rem(self, prime: Prime) -> Self::Output {
if self.prime() == prime {
return self;
}
if self.prime() > prime {
return Self::from_parts(self.value.as_ref().clone(), prime);
}
Self::from_parts(self.as_ref() % prime.value(), prime)
}
}

impl RemAssign for Felt {
/// # Panics
///
Expand All @@ -120,6 +164,12 @@ impl RemAssign for Felt {
}
}

impl RemAssign<Prime> for Felt {
fn rem_assign(&mut self, rhs: Prime) {
*self = *self % rhs;
}
}

impl Sub for Felt {
type Output = Self;

Expand Down Expand Up @@ -188,14 +238,23 @@ impl MulAssign for Felt {
}
}

impl Neg for Felt {
type Output = Self;

fn neg(self) -> Self::Output {
self.replace(self.prime().value() - self.as_ref())
}
}

impl std::fmt::Display for Felt {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_ref())
}
}

#[allow(missing_docs)]
#[cfg(test)]
mod tests {
pub mod tests {

use super::*;
use ff::PrimeField;
Expand Down
1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#![deny(missing_docs)]

pub mod cmp;
pub mod constraints;
pub mod eqv;
pub mod error;
pub mod expressions;
Expand Down
24 changes: 21 additions & 3 deletions core/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,40 @@ mod sealed {
pub trait QueryKind: sealed::QK {}

/// Marker for fixed cell queries.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Fixed;

impl sealed::QK for Fixed {}
impl QueryKind for Fixed {}

impl std::fmt::Debug for Fixed {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Fix")
}
}

/// Marker for advice cell queries.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Advice;

impl sealed::QK for Advice {}
impl QueryKind for Advice {}

impl std::fmt::Debug for Advice {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Adv")
}
}

/// Marker for instance cell queries.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Instance;

impl sealed::QK for Instance {}
impl QueryKind for Instance {}

impl std::fmt::Debug for Instance {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Ins")
}
}
22 changes: 19 additions & 3 deletions core/src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub trait ColumnType: std::fmt::Debug + Copy + Clone + PartialEq + Eq + std::has
}

/// Erased column type.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub enum Any {
/// Fixed type.
Fixed,
Expand All @@ -30,6 +30,16 @@ pub enum Any {
Instance,
}

impl std::fmt::Debug for Any {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Fixed => write!(f, "Fix"),
Self::Advice => write!(f, "Adv"),
Self::Instance => write!(f, "Ins"),
}
}
}

impl ColumnType for Any {
fn query_cell<F: Field, E: ExprBuilder<F>>(&self, index: usize, at: Rotation) -> E {
match self {
Expand Down Expand Up @@ -59,12 +69,18 @@ impl ColumnType for Instance {
}

/// A column with a type.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Column<C: ColumnType> {
index: usize,
column_type: C,
}

impl<C: ColumnType + std::fmt::Debug> std::fmt::Debug for Column<C> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}:{}", self.column_type, self.index)
}
}

impl<C: ColumnType> Column<C> {
/// Creates a new column.
pub fn new(index: usize, column_type: C) -> Self {
Expand Down Expand Up @@ -157,7 +173,7 @@ impl TryFrom<Column<Any>> for Column<Instance> {
}

/// Represents a cell in the table.
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
pub struct Cell {
/// The index of the region this cell belongs to.
pub region_index: RegionIndex,
Expand Down
35 changes: 35 additions & 0 deletions ir/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[package]
name = "haloumi-ir"
description = "Intermediate representation of the haloumi framework."
categories = {workspace = true}
version = {workspace = true}
authors = {workspace = true}
edition = {workspace = true}
rust-version = {workspace = true}
readme = "README.md"
repository = {workspace = true}
license-file = {workspace = true}
keywords = {workspace = true}

[dependencies]
ff.workspace = true
log.workspace = true
thiserror.workspace = true
internment.workspace = true
eqv.workspace = true
haloumi-core = { path = "../core", version = "0.5.3"}
haloumi-lowering = { path = "../lowering", version = "0.5.3" }
num-bigint.workspace = true
bit-set.workspace = true

[dev-dependencies]
rstest = "0.26"
similar-asserts = "1.7"
ff = { workspace = true, features = ["derive"] }
halo2curves = "0.9"
quickcheck = "1"
quickcheck_macros = "1"
mockall = "0.14"

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage,coverage_nightly)'] }
3 changes: 3 additions & 0 deletions ir/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# haloumi-ir

Intermediate representation of the haloumi framework.
Loading