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
17 changes: 17 additions & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ members = [
"poseidon",
"poseidon/export_test_vectors",
"saffron",
"saffron-stubs",
"signer",
"tools/kimchi-visu",
"turshi",
Expand Down Expand Up @@ -109,7 +110,7 @@ o1vm = { path = "./o1vm", version = "0.1.0" }
optimism = { path = "./optimism", version = "0.1.0" }
plonk_wasm = { path = "./plonk-wasm", version = "0.1.0" }
poly-commitment = { path = "./poly-commitment", version = "0.1.0" }
saffron = { path = "./poly-commitment", version = "0.1.0" }
saffron = { path = "./saffron", version = "0.1.0" }
signer = { path = "./signer", version = "0.1.0" }
turshi = { path = "./turshi", version = "0.1.0" }
utils = { path = "./utils", version = "0.1.0" }
Expand Down
25 changes: 25 additions & 0 deletions saffron-stubs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[package]
name = "saffron-stubs"
version = "0.1.0"
authors = ["[email protected]"]
description = "OCaml stubs for Saffron"
repository = "https://github.com/MinaProtocol/mina"
license = "MIT/Apache-2.0"
edition = "2021"

[lib]
name = "saffron_stubs"
# Important: do not ask to build a dynamic library.
# On MacOS arm64, ocaml-rs.v0.2.2 causes build issues.
# On the Saffron side, a fake and empty dllsaffron_stubs.so file is used.
crate-type = ["lib", "staticlib"]

[dependencies]
kimchi = { workspace = true, features = ["ocaml_types"] }
kimchi-stubs.workspace = true
libc.workspace = true
ocaml = { workspace = true, features = ["no-caml-startup"] }
ocaml-gen.workspace = true
poly-commitment.workspace = true
rand.workspace = true
saffron = { workspace = true, features = ["ocaml_types"] }
29 changes: 29 additions & 0 deletions saffron-stubs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# OCaml stubs for the Saffron codebase

This library will be used to call the Rust code defined in the crate
[saffron](./saffron) in the Caml codebase of Saffron.

The bindings uses ocaml-gen to facilite the bindings of structures like
`ReadProof` and ocaml-rs to generate the C and Caml boilerplate.

The user can run `make release` (resp.`make build` to add debug symbols) from
the top-level of the workspace. A static library `libsaffron_stubs.a` will be
generated with all the symbols the Caml codebase of Saffron can used. The static
file will be available under `target/release/libsaffron_stubs.a` (resp
`target/debug/libsaffron_stubs.a`). The exposed symbols can be inspected using
`nm`. The `nm` tool can be useful to debug errors like `undefined references
[...]`.

Using the build system `dune`, the user can ask to generate the static library using:
```
(rule
(target libsaffron_stubs.a)
(action
(progn
(run
cargo
build
-p
saffron-stubs
--release))))
```
57 changes: 57 additions & 0 deletions saffron-stubs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use kimchi::{circuits::domains::EvaluationDomains, groupmap::GroupMap};
use kimchi_stubs::{
arkworks::{CamlFp, CamlGVesta},
srs::fp::CamlFpSrs,
};
use poly_commitment::SRS;
use saffron::{
read_proof::{self, caml::CamlReadProof, ReadProof},
BaseField, Curve, ScalarField,
};

#[ocaml_gen::func]
#[ocaml::func]
pub fn caml_saffron_read_prove(
caml_srs: CamlFpSrs,
caml_data: Vec<CamlFp>,
caml_query: Vec<CamlFp>,
caml_answer: Vec<CamlFp>,
caml_data_comm: CamlGVesta,
) -> CamlReadProof {
let srs = caml_srs.0;
let data: Vec<ScalarField> = caml_data.into_iter().map(|x| x.into()).collect();
let query: Vec<ScalarField> = caml_query.into_iter().map(|x| x.into()).collect();
let answer: Vec<ScalarField> = caml_answer.into_iter().map(|x| x.into()).collect();
let data_comm: Curve = caml_data_comm.into();

let srs_size = srs.max_poly_size();
let domain = EvaluationDomains::<ScalarField>::create(srs_size).unwrap();

let group_map = GroupMap::<BaseField>::setup();

let mut rng = rand::thread_rng();
let read_proof = read_proof::prove(
&srs, domain, &group_map, &mut rng, &data, &query, &answer, &data_comm,
);
read_proof.into()
}

#[ocaml_gen::func]
#[ocaml::func]
pub fn caml_saffron_read_verify(
caml_srs: CamlFpSrs,
caml_data_comm: CamlGVesta,
caml_proof: CamlReadProof,
) -> bool {
let srs = caml_srs.0;
let data_comm: Curve = caml_data_comm.into();
let proof: ReadProof = caml_proof.into();

let mut rng = rand::thread_rng();
let srs_size = srs.max_poly_size();
let domain = EvaluationDomains::<ScalarField>::create(srs_size).unwrap();

let group_map = GroupMap::<BaseField>::setup();

read_proof::verify(&srs, domain, &group_map, &mut rng, &data_comm, &proof)
}
8 changes: 6 additions & 2 deletions saffron/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ readme = "README.md"
edition = "2021"
license = "Apache-2.0"

# [lib]
# path = "src/lib.rs"
[lib]
path = "src/lib.rs"

[[bin]]
name = "saffron"
Expand All @@ -25,9 +25,12 @@ ark-serialize = { workspace = true, features = ["derive"] }
clap = { workspace = true, features = ["derive"] }
hex.workspace = true
kimchi.workspace = true
kimchi-stubs = { workspace = true, optional = true }
mina-curves.workspace = true
mina-poseidon.workspace = true
o1-utils.workspace = true
ocaml = { workspace = true, optional = true }
ocaml-gen = { workspace = true, optional = true }
poly-commitment.workspace = true
rand.workspace = true
rayon.workspace = true
Expand Down Expand Up @@ -65,3 +68,4 @@ harness = false

[features]
bench = []
ocaml_types = ["kimchi-stubs", "ocaml", "ocaml-gen"]
2 changes: 0 additions & 2 deletions saffron/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,3 @@ pub type BaseField = Fq;

pub type CurveFqSponge = DefaultFqSponge<VestaParameters, PlonkSpongeConstantsKimchi>;
pub type CurveFrSponge = DefaultFrSponge<ScalarField, PlonkSpongeConstantsKimchi>;

//pub type ScalarSponge = DefaultFrSponge<Fp, SpongeParams>;
46 changes: 46 additions & 0 deletions saffron/src/read_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,3 +370,49 @@ mod tests {
assert!(!res_2, "Soundness: Malformed proof #2 must NOT verify");
}
}

#[cfg(feature = "ocaml_types")]
pub mod caml {
use super::*;
use kimchi_stubs::arkworks::{group_affine::CamlGVesta, pasta_fp::CamlFp};
use poly_commitment::ipa::caml::CamlOpeningProof;

#[derive(ocaml::IntoValue, ocaml::FromValue, ocaml_gen::Struct)]
pub struct CamlReadProof {
pub query_comm: CamlGVesta,
pub answer_comm: CamlGVesta,
pub quotient_comm: CamlGVesta,
pub data_eval: CamlFp,
pub query_eval: CamlFp,
pub answer_eval: CamlFp,
pub opening_proof: CamlOpeningProof<CamlGVesta, CamlFp>,
}

impl From<ReadProof> for CamlReadProof {
fn from(proof: ReadProof) -> Self {
Self {
query_comm: proof.query_comm.into(),
answer_comm: proof.answer_comm.into(),
quotient_comm: proof.quotient_comm.into(),
data_eval: proof.data_eval.into(),
query_eval: proof.query_eval.into(),
answer_eval: proof.answer_eval.into(),
opening_proof: proof.opening_proof.into(),
}
}
}

impl From<CamlReadProof> for ReadProof {
fn from(proof: CamlReadProof) -> Self {
Self {
query_comm: proof.query_comm.into(),
answer_comm: proof.answer_comm.into(),
quotient_comm: proof.quotient_comm.into(),
data_eval: proof.data_eval.into(),
query_eval: proof.query_eval.into(),
answer_eval: proof.answer_eval.into(),
opening_proof: proof.opening_proof.into(),
}
}
}
}
31 changes: 31 additions & 0 deletions saffron/src/storage_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,34 @@ mod tests {
}
}
}

#[cfg(feature = "ocaml_types")]
pub mod caml {
use super::*;
use kimchi_stubs::arkworks::{group_affine::CamlGVesta, pasta_fp::CamlFp};
use poly_commitment::ipa::caml::CamlOpeningProof;

#[derive(ocaml::IntoValue, ocaml::FromValue, ocaml_gen::Struct)]
pub struct CamlStorageProof {
pub combined_data_eval: CamlFp,
pub opening_proof: CamlOpeningProof<CamlGVesta, CamlFp>,
}

impl From<StorageProof> for CamlStorageProof {
fn from(proof: StorageProof) -> Self {
Self {
combined_data_eval: proof.combined_data_eval.into(),
opening_proof: proof.opening_proof.into(),
}
}
}

impl From<CamlStorageProof> for StorageProof {
fn from(proof: CamlStorageProof) -> Self {
Self {
combined_data_eval: proof.combined_data_eval.into(),
opening_proof: proof.opening_proof.into(),
}
}
}
}
Loading