From 7d8355f58b7a7c6a547979000b8e1d650813bb75 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Mon, 20 May 2024 11:44:40 -0600 Subject: [PATCH 1/2] feat: miniature DSL --- Cargo.lock | 43 ++++++++++++++++- Cargo.toml | 1 + src/compiler/dsl.rs | 112 ++++++++++++++++++++++++++++++++++++++++++++ src/compiler/mod.rs | 61 ++++++++++++++++++++++++ src/lib.rs | 1 + 5 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 src/compiler/dsl.rs create mode 100644 src/compiler/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 3e27985..4168814 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,7 +45,7 @@ dependencies = [ "ark-serialize", "ark-std", "derivative", - "hashbrown", + "hashbrown 0.13.2", "itertools", "num-traits", "zeroize", @@ -104,7 +104,7 @@ dependencies = [ "ark-serialize", "ark-std", "derivative", - "hashbrown", + "hashbrown 0.13.2", ] [[package]] @@ -194,6 +194,18 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "futures" version = "0.3.30" @@ -325,6 +337,22 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", +] + [[package]] name = "itertools" version = "0.10.5" @@ -387,6 +415,16 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -508,6 +546,7 @@ dependencies = [ "ark-poly", "ark-std", "num-bigint", + "petgraph", "pretty_assertions", "rand", "rstest", diff --git a/Cargo.toml b/Cargo.toml index 528b50f..1dc395f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ repository ="https://github.com/thor314/ronkathon" version ="0.1.0" [dependencies] +petgraph ="0.6.5" rand ="0.8.5" num-bigint={ version="0.4.3", default-features=false } ark-std ={ version="0.4.0", default-features=false } diff --git a/src/compiler/dsl.rs b/src/compiler/dsl.rs new file mode 100644 index 0000000..9d8df0d --- /dev/null +++ b/src/compiler/dsl.rs @@ -0,0 +1,112 @@ +use super::*; + +#[derive(Clone, Copy, Debug)] +pub enum Variable { + Public(u32), + Private(u32), +} + +#[derive(Clone, Copy, Debug)] +pub enum Expression { + Add(ExpL, ExpR), + Mul(ExpL, ExpR), +} + +impl Add for Variable { + type Output = Expression; + + fn add(self, rhs: Self) -> Self::Output { Expression::Add(self, rhs) } +} + +impl Add> for Variable { + type Output = Expression>; + + fn add(self, rhs: Expression) -> Self::Output { Expression::Add(self, rhs) } +} + +impl Add for Expression { + type Output = Expression, Variable>; + + fn add(self, rhs: Variable) -> Self::Output { Expression::Add(self, rhs) } +} + +impl Add> for Expression { + type Output = Expression, Expression>; + + fn add(self, rhs: Expression) -> Self::Output { Expression::Add(self, rhs) } +} + +impl Mul for Variable { + type Output = Expression; + + fn mul(self, rhs: Self) -> Self::Output { Expression::Mul(self, rhs) } +} + +impl Mul> for Variable { + type Output = Expression>; + + fn mul(self, rhs: Expression) -> Self::Output { Expression::Mul(self, rhs) } +} + +impl Mul for Expression { + type Output = Expression, Variable>; + + fn mul(self, rhs: Variable) -> Self::Output { Expression::Mul(self, rhs) } +} + +impl Mul> for Expression { + type Output = Expression, Expression>; + + fn mul(self, rhs: Expression) -> Self::Output { Expression::Mul(self, rhs) } +} + +impl Display for Variable { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Variable::Public(val) => write!(f, "{}", val), + Variable::Private(val) => write!(f, "{}", val), + } + } +} + +impl Display for Expression { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Expression::Add(left, right) => write!(f, "({} + {})", left, right), + Expression::Mul(left, right) => write!(f, "({} * {})", left, right), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn writing_a_program() { + // Create two variables + let a = Variable::Public(7); + let b = Variable::Private(3); + + // Create basic expressions with these variables + let add_ab = a + b; + println!("{}", add_ab); + assert_eq!(format!("{}", add_ab), "(7 + 3)"); + + let mul_ab = a * b; + println!("{}", mul_ab); + assert_eq!(format!("{}", mul_ab), "(7 * 3)"); + + // Check that we can add a variable to an expression + println!("{}", a + mul_ab); + assert_eq!(format!("{}", a + mul_ab), "(7 + (7 * 3))"); + + // Check that we can add an expression to a variable + println!("{}", mul_ab + a); + assert_eq!(format!("{}", mul_ab + a), "((7 * 3) + 7)"); + + // Check that we can add two expressions together + println!("{}", add_ab + mul_ab); + assert_eq!(format!("{}", add_ab + mul_ab), "((7 + 3) + (7 * 3))"); + } +} diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs new file mode 100644 index 0000000..d10d37a --- /dev/null +++ b/src/compiler/mod.rs @@ -0,0 +1,61 @@ +//! The compiler for `ronkathon` circuits. + +// TODO: Remove this once the module is fleshed out. +#![allow(missing_docs)] +use petgraph::graph::{DiGraph, NodeIndex}; + +// TODO: Goal, allow someone to use this library to write rust to generate arithmetic circuits +// basically. +// ``` +// use ronkathon::compiler::*; +// +// fn main() { +// let a: Input = Variable::public(7); +// let b: Input = Variable::private(3); +// let b: Expression = a * c; +// } +// ``` +// So we can do things like `impl Add`, `impl Mul` for variables and make them into gates? +use super::*; + +pub mod dsl; + +pub struct Wire { + pub input: Connection, + pub output: Connection, +} + +pub enum Connection { + Input(Publicity), + Output, + Internal, +} + +pub enum Publicity { + Public(u32), + Private(u32), +} + +pub enum Operation { + Add, + Mul, + Sub, +} + +// TODO: Want to make it so gates own a reference for who they are connected to, and circuits own +// the gates. This way gates cannot be improperly connected to other gates. +pub struct Gate { + pub left: Wire, + pub right: Wire, + pub output: Wire, + pub op: Operation, +} + +pub struct Circuit { + pub gates: DiGraph, +} + +impl Circuit { + pub fn new() -> Self { Self { gates: DiGraph::new() } } +} + diff --git a/src/lib.rs b/src/lib.rs index 4fda8be..e910535 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,6 +21,7 @@ #![feature(generic_const_exprs)] #![warn(missing_docs)] +pub mod compiler; pub mod curve; pub mod field; pub mod kzg; From d3258c10baf4c6078aca1e71f2009a928470a884 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Mon, 20 May 2024 12:04:45 -0600 Subject: [PATCH 2/2] wip: cleanup + notes --- Cargo.lock | 43 ++-------------------------- Cargo.toml | 1 - src/compiler/dsl.rs | 70 ++++++++++++++++++++++++++------------------- src/compiler/mod.rs | 60 ++++++++++++++++++-------------------- 4 files changed, 71 insertions(+), 103 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4168814..3e27985 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,7 +45,7 @@ dependencies = [ "ark-serialize", "ark-std", "derivative", - "hashbrown 0.13.2", + "hashbrown", "itertools", "num-traits", "zeroize", @@ -104,7 +104,7 @@ dependencies = [ "ark-serialize", "ark-std", "derivative", - "hashbrown 0.13.2", + "hashbrown", ] [[package]] @@ -194,18 +194,6 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - [[package]] name = "futures" version = "0.3.30" @@ -337,22 +325,6 @@ dependencies = [ "ahash", ] -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "indexmap" -version = "2.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" -dependencies = [ - "equivalent", - "hashbrown 0.14.5", -] - [[package]] name = "itertools" version = "0.10.5" @@ -415,16 +387,6 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" -[[package]] -name = "petgraph" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" -dependencies = [ - "fixedbitset", - "indexmap", -] - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -546,7 +508,6 @@ dependencies = [ "ark-poly", "ark-std", "num-bigint", - "petgraph", "pretty_assertions", "rand", "rstest", diff --git a/Cargo.toml b/Cargo.toml index 1dc395f..528b50f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,6 @@ repository ="https://github.com/thor314/ronkathon" version ="0.1.0" [dependencies] -petgraph ="0.6.5" rand ="0.8.5" num-bigint={ version="0.4.3", default-features=false } ark-std ={ version="0.4.0", default-features=false } diff --git a/src/compiler/dsl.rs b/src/compiler/dsl.rs index 9d8df0d..03eca76 100644 --- a/src/compiler/dsl.rs +++ b/src/compiler/dsl.rs @@ -1,9 +1,15 @@ use super::*; #[derive(Clone, Copy, Debug)] -pub enum Variable { - Public(u32), - Private(u32), +pub enum Input { + Variable(Variable), + Public(usize), + Private(usize), +} + +#[derive(Clone, Copy, Debug)] +pub struct Variable { + pub label: usize, } #[derive(Clone, Copy, Debug)] @@ -12,64 +18,65 @@ pub enum Expression { Mul(ExpL, ExpR), } -impl Add for Variable { - type Output = Expression; +impl Add for Input { + type Output = Expression; fn add(self, rhs: Self) -> Self::Output { Expression::Add(self, rhs) } } -impl Add> for Variable { - type Output = Expression>; +impl Add> for Input { + type Output = Expression>; fn add(self, rhs: Expression) -> Self::Output { Expression::Add(self, rhs) } } -impl Add for Expression { - type Output = Expression, Variable>; +impl Add for Expression { + type Output = Expression, Input>; - fn add(self, rhs: Variable) -> Self::Output { Expression::Add(self, rhs) } + fn add(self, rhs: Input) -> Self::Output { Expression::Add(self, rhs) } } -impl Add> for Expression { - type Output = Expression, Expression>; +impl Add> for Expression { + type Output = Expression, Expression>; - fn add(self, rhs: Expression) -> Self::Output { Expression::Add(self, rhs) } + fn add(self, rhs: Expression) -> Self::Output { Expression::Add(self, rhs) } } -impl Mul for Variable { - type Output = Expression; +impl Mul for Input { + type Output = Expression; fn mul(self, rhs: Self) -> Self::Output { Expression::Mul(self, rhs) } } -impl Mul> for Variable { - type Output = Expression>; +impl Mul> for Input { + type Output = Expression>; fn mul(self, rhs: Expression) -> Self::Output { Expression::Mul(self, rhs) } } -impl Mul for Expression { - type Output = Expression, Variable>; +impl Mul for Expression { + type Output = Expression, Input>; - fn mul(self, rhs: Variable) -> Self::Output { Expression::Mul(self, rhs) } + fn mul(self, rhs: Input) -> Self::Output { Expression::Mul(self, rhs) } } -impl Mul> for Expression { - type Output = Expression, Expression>; +impl Mul> for Expression { + type Output = Expression, Expression>; - fn mul(self, rhs: Expression) -> Self::Output { Expression::Mul(self, rhs) } + fn mul(self, rhs: Expression) -> Self::Output { Expression::Mul(self, rhs) } } -impl Display for Variable { +impl Display for Input { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - Variable::Public(val) => write!(f, "{}", val), - Variable::Private(val) => write!(f, "{}", val), + Input::Variable(val) => write!(f, "x_{}", val.label), + Input::Public(val) => write!(f, "{}", val), + Input::Private(val) => write!(f, "{}", val), } } } -impl Display for Expression { +impl Display for Expression { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { Expression::Add(left, right) => write!(f, "({} + {})", left, right), @@ -85,8 +92,9 @@ mod tests { #[test] fn writing_a_program() { // Create two variables - let a = Variable::Public(7); - let b = Variable::Private(3); + let a = Input::Public(7); + let b = Input::Private(3); + let x = Input::Variable(Variable { label: 0 }); // Create basic expressions with these variables let add_ab = a + b; @@ -108,5 +116,9 @@ mod tests { // Check that we can add two expressions together println!("{}", add_ab + mul_ab); assert_eq!(format!("{}", add_ab + mul_ab), "((7 + 3) + (7 * 3))"); + + // Check that we can multiply an expression by a variable + println!("{}", mul_ab * x); + assert_eq!(format!("{}", mul_ab * x), "((7 * 3) * x_0)"); } } diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs index d10d37a..7b97878 100644 --- a/src/compiler/mod.rs +++ b/src/compiler/mod.rs @@ -2,7 +2,6 @@ // TODO: Remove this once the module is fleshed out. #![allow(missing_docs)] -use petgraph::graph::{DiGraph, NodeIndex}; // TODO: Goal, allow someone to use this library to write rust to generate arithmetic circuits // basically. @@ -16,46 +15,43 @@ use petgraph::graph::{DiGraph, NodeIndex}; // } // ``` // So we can do things like `impl Add`, `impl Mul` for variables and make them into gates? + +use std::array; + +// Above seems done. Now we need to have a way to unravel a collection of expressions into a +// circuit that may have the same inputs and outputs as the expressions. Inputs are going to be +// the terminal variables found by fully unravelling expressions and they should be named. The +// fully ravelled expressions are the outputs, and they can also be named use super::*; pub mod dsl; +pub use dsl::*; -pub struct Wire { - pub input: Connection, - pub output: Connection, -} - -pub enum Connection { - Input(Publicity), - Output, - Internal, +#[derive(Debug, Clone, Copy)] +pub struct Circuit { + pub inputs: [Input; INPUTS], } -pub enum Publicity { - Public(u32), - Private(u32), -} +impl Circuit { + pub fn new() -> Self { + Self { inputs: array::from_fn(|label| Input::Variable(Variable { label })) } + } -pub enum Operation { - Add, - Mul, - Sub, + pub const fn input(&self, label: usize) -> Input { self.inputs[label] } } -// TODO: Want to make it so gates own a reference for who they are connected to, and circuits own -// the gates. This way gates cannot be improperly connected to other gates. -pub struct Gate { - pub left: Wire, - pub right: Wire, - pub output: Wire, - pub op: Operation, -} +#[cfg(test)] +mod tests { + use super::*; -pub struct Circuit { - pub gates: DiGraph, -} + #[test] + fn creating_a_circuit() { + let circuit = Circuit::<3>::new(); + let x_0 = circuit.input(0); + let x_1 = circuit.input(1); + let x_2 = circuit.input(2); -impl Circuit { - pub fn new() -> Self { Self { gates: DiGraph::new() } } + let expr = x_0 * x_1 + x_2; + println!("{}", expr); + } } -