Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZK-1337: Create http server which serves bindings functions #96

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
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
49 changes: 44 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ axum = { version = "0.7.7" }
byteorder = { version = "1.4.3" }
chacha20poly1305 = { version = "0.10.1", default-features = false }
clap = { version = "4.5.8" }
ctor = { version = "0.2.9" }
getrandom = { version = "0.2" }
halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2", tag = "v0.3.0", default-features = false }
halo2curves = { version = "0.6.0", default-features = false }
Expand All @@ -38,7 +39,10 @@ itertools = { version = "0.13.0" }
metrics = { version = "0.24.1", default-features = false }
metrics-exporter-prometheus = { version = "0.16.0", default-features = false }
num-bigint = { version = "0.4.3" }
once_cell = { version = "1.20.2" }
openssl = { version = "0.10.59" }
quote = { version = "1.0.38" }
proc-macro2 = { version = "1.0.93" }
rand = { version = "0.8.5" }
rayon = { version = "1.8" }
reqwest = { version = "0.12.5" }
Expand Down Expand Up @@ -67,9 +71,12 @@ wasm-bindgen-rayon = { version = "1.2.1" }
content-encryption = { path = "crates/content-encryption", default-features = false }
evm-utils = { path = "crates/evm-utils" }
halo2_solidity_verifier = { path = "crates/halo2-verifier" }
macros-core = { path = "crates/macros-core" }
macros = { path = "crates/macros" }
powers-of-tau = { path = "crates/powers-of-tau" }
shielder-account = { path = "crates/shielder-account" }
shielder-contract = { path = "crates/shielder-contract" }
shielder-relayer = { path = "crates/shielder-relayer" }
shielder-setup = { path = "crates/shielder-setup" }
type-conversions = { path = "crates/type-conversions" }
shielder_bindings = { path = "crates/shielder_bindings" }
Comment on lines +74 to +82
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's keep them sorted (I will look for some lint to check this automatically)

8 changes: 8 additions & 0 deletions crates/macros-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "macros-core"
Comment on lines +1 to +2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we really need yet another crate? why can't its content belong to macros?

version = "0.1.0"
edition = "2021"

[dependencies]
once_cell = { workspace = true }
serde_json = { workspace = true }
22 changes: 22 additions & 0 deletions crates/macros-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use std::sync::Mutex;

use once_cell::sync::Lazy;
use serde_json::Value;

pub type JsonFnPointer = fn(Value) -> Value;

/// A simple struct to hold info about an "exported" function.
#[derive(Debug, Clone)]
pub struct JsonizedFunction {
/// The function name as a string.
pub name: &'static str,
/// Pointer to the bridging function.
pub func: JsonFnPointer,
}

/// A global registry of exported functions.
///
/// By using `Lazy<Mutex<...>>`, we can push to this vector at compile time
/// (technically, it's “init-time” for each static), and read it later.
pub static EXPORTED_FUNCTIONS: Lazy<Mutex<Vec<JsonizedFunction>>> =
Lazy::new(|| Mutex::new(Vec::new()));
15 changes: 15 additions & 0 deletions crates/macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "macros"
version = "0.1.0"
edition = "2021"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can inherit many attributes from the workspace


[lib]
proc-macro = true

[dependencies]
ctor = { workspace = true }
macros-core = { workspace = true }
once_cell = { workspace = true }
proc-macro2 = { workspace = true }
quote = { workspace = true }
syn = { version = "1", features = ["full"] }
54 changes: 54 additions & 0 deletions crates/macros/src/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use proc_macro2::Ident;
use quote::{format_ident, quote};
use syn::{FnArg, Pat, Type};

/// Helper struct to store parsed argument information
pub struct ArgumentInfo {
pub name: Ident,
pub ty: Box<Type>,
}

/// Parse function arguments into a vector of ArgumentInfo
pub fn parse_arguments(
inputs: &syn::punctuated::Punctuated<FnArg, syn::token::Comma>,
) -> Vec<ArgumentInfo> {
let mut args = Vec::new();

for (i, arg) in inputs.iter().enumerate() {
if let FnArg::Typed(pat_type) = arg {
let arg_name = match &*pat_type.pat {
Pat::Ident(ident) => ident.ident.clone(),
_ => format_ident!("arg{}", i),
};
args.push(ArgumentInfo {
name: arg_name,
ty: pat_type.ty.clone(),
});
}
}

args
}

/// Generate Deserealizable struct definition for function arguments
pub fn generate_args_struct(
struct_name: &Ident,
args: &[ArgumentInfo],
) -> proc_macro2::TokenStream {
let fields = args.iter().map(|arg| {
let name = &arg.name;
let ty = &arg.ty;
quote! { pub #name: #ty }
});
let fields_ts = quote! {
#(#fields),*
};

quote! {
#[allow(non_camel_case_types)]
#[derive(::serde::Deserialize)]
struct #struct_name {
#fields_ts
}
}
}
39 changes: 39 additions & 0 deletions crates/macros/src/bridging.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use proc_macro2::Ident;
use quote::quote;

use crate::args::ArgumentInfo;

/// Generate bridging function that converts between JSON and native types
/// JSON is parsed into a Deserealizable struct, then the function is called
/// with the struct fields as arguments. The result is then serialized back
/// into JSON.
pub fn generate_bridging_fn(
fn_name: &Ident,
struct_name: &Ident,
args: &[ArgumentInfo],
ret_type: &proc_macro2::TokenStream,
call_path: proc_macro2::TokenStream,
) -> (proc_macro2::TokenStream, Ident) {
let arg_names: Vec<_> = args.iter().map(|arg| &arg.name).collect();
let bridging_name = quote::format_ident!("{}_json", fn_name);

(
quote! {
#[allow(non_snake_case)]
fn #bridging_name(input: ::serde_json::Value) -> ::serde_json::Value {
let args: #struct_name = match ::serde_json::from_value(input) {
Ok(val) => val,
Err(e) => {
return ::serde_json::json!({
"error": format!("Invalid input JSON: {}", e)
});
}
};

let result: #ret_type = #call_path(#( args.#arg_names ),*);
::serde_json::json!(result)
}
},
bridging_name,
)
}
Loading