diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3f7b956b99..bde5ca6229 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -159,7 +159,7 @@ jobs: - name: Rerun doc generation with different args and copy into book directory if: >- - github.event_name == 'push' && + github.event_name == 'push' && github.ref == 'refs/heads/master' && matrix.rust_toolchain_version == needs.define-matrix.outputs.default_rust_version && matrix.os == needs.define-matrix.outputs.default_os @@ -171,7 +171,7 @@ jobs: - name: Deploy uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e if: >- - github.event_name == 'push' && + github.event_name == 'push' && github.ref == 'refs/heads/master' && matrix.rust_toolchain_version == needs.define-matrix.outputs.default_rust_version && matrix.os == needs.define-matrix.outputs.default_os diff --git a/.gitignore b/.gitignore index 640403cba1..9dbe11a2c8 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,7 @@ o1vm/resources/programs/mips/src o1vm/resources/programs/mips/bin CLAUDE.md + +# OCaml artefacts +_build +_opam \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 4bf33b10ba..5113bf4bb5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3142,6 +3142,15 @@ dependencies = [ "rand_core", ] +[[package]] +name = "raw-cpuid" +version = "11.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" +dependencies = [ + "bitflags 2.4.2", +] + [[package]] name = "rayon" version = "1.10.0" @@ -4723,6 +4732,7 @@ version = "0.1.0" dependencies = [ "anyhow", "clap 4.4.18", + "raw-cpuid", "wasm-pack", ] diff --git a/Makefile b/Makefile index 155f5ec7b3..daba5de115 100644 --- a/Makefile +++ b/Makefile @@ -247,4 +247,8 @@ build-web: ## Compile the Kimchi library into WebAssembly to be used in the brow --out-dir ${PLONK_WASM_WEB_OUTDIR} \ --rust-version ${NIGHTLY_RUST_VERSION} +.PHONY: build-ocaml-kimchi-stubs +build-ocaml-kimchi-stubs: ## Build the OCaml modules to call the Kimchi and Pasta primitives in Rust + dune build kimchi-stubs + .PHONY: all setup install-test-deps clean build release test-doc test-doc-with-coverage test test-with-coverage test-heavy test-heavy-with-coverage test-all test-all-with-coverage nextest nextest-with-coverage nextest-heavy nextest-heavy-with-coverage nextest-all nextest-all-with-coverage format lint generate-test-coverage-report generate-doc setup-riscv32-toolchain help fclean build-riscv32-programs build-mips-programs check-format diff --git a/README.md b/README.md index ee44d6ce0c..e83c9f9029 100644 --- a/README.md +++ b/README.md @@ -10,17 +10,24 @@ [![dependency status](https://deps.rs/repo/github/o1-labs/proof-systems/status.svg?style=flat-square)](https://deps.rs/repo/github/o1-labs/proof-systems) -This repository contains **kimchi**, a general-purpose zero-knowledge proof system for proving the correct execution of programs. +This repository contains **kimchi**, a general-purpose zero-knowledge proof +system for proving the correct execution of programs. -You can read more about this project on the [Kimchi book](https://o1-labs.github.io/proof-systems), or for a lighter introduction in this [blogpost](https://minaprotocol.com/blog/kimchi-the-latest-update-to-minas-proof-system). +You can read more about this project on the [Kimchi +book](https://o1-labs.github.io/proof-systems), or for a lighter introduction in +this +[blogpost](https://minaprotocol.com/blog/kimchi-the-latest-update-to-minas-proof-system). [See here for the rust documentation](https://o1-labs.github.io/proof-systems/rustdoc). ## User Warning -This project comes as is. We provide no guarantee of stability or support, as the crates closely follow the needs of the [Mina](<[https://](https://github.com/minaprotocol/mina)>) project. +This project comes as is. We provide no guarantee of stability or support, as +the crates closely follow the needs of the +[Mina](<[https://](https://github.com/minaprotocol/mina)>) project. -If you use this project in a production environment, it is your responsibility to perform a security audit to ensure that the software meets your requirements. +If you use this project in a production environment, it is your responsibility +to perform a security audit to ensure that the software meets your requirements. ## Performance @@ -52,7 +59,8 @@ At the time of this writing: The project is organized in the following way: -- [book/](book/). The mina book, RFCs, and specifications. [Available here in HTML](https://o1-labs.github.io/proof-systems). +- [book/](book/). The mina book, RFCs, and specifications. [Available here in + HTML](https://o1-labs.github.io/proof-systems). - [curves/](curves/). The elliptic curves we use (for now just the pasta curves). - [groupmap/](groupmap/). Used to convert elliptic curve elements to field elements. - [hasher/](hasher/). Interfaces for mina hashing. @@ -66,18 +74,20 @@ The project is organized in the following way: ## Contributing -Check [CONTRIBUTING.md](CONTRIBUTING.md) if you are interested in contributing to this project. +Check [CONTRIBUTING.md](CONTRIBUTING.md) if you are interested in contributing +to this project. ## Generate rustdoc locally -An effort is made to have the documentation being self-contained, referring to the mina book for more details when necessary. -You can build the rust documentation with +An effort is made to have the documentation being self-contained, referring to +the mina book for more details when necessary. You can build the rust +documentation with - + ```shell rustup install nightly -RUSTDOCFLAGS="--enable-index-page -Zunstable-options" cargo +nightly doc --all --no-deps +make generate-doc ``` You can visualize the documentation by opening the file `target/doc/index.html`. @@ -87,16 +97,36 @@ You can visualize the documentation by opening the file `target/doc/index.html`. - [CI](.github/workflows/ci.yml). - This workflow ensures that the entire project builds correctly, adheres to guidelines, and passes all necessary tests. + This workflow ensures that the entire project builds correctly, adheres to + guidelines, and passes all necessary tests. - [Nightly tests with the code coverage](.github/workflows/ci-nightly.yml). - This workflow runs all the tests per scheduler or on-demand, generates and attaches the code coverage report to the job's execution results. + This workflow runs all the tests per scheduler or on-demand, generates and + attaches the code coverage report to the job's execution results. - [Benchmarks](.github/workflows/benches.yml). - This workflow runs benchmarks when a pull request is labeled with "benchmark." It sets up the Rust and OCaml environments, installs necessary tools, and executes cargo criterion benchmarks on the kimchi crate. The benchmark results are then posted as a comment on the pull request for review. + This workflow runs benchmarks when a pull request is labeled with "benchmark." + It sets up the Rust and OCaml environments, installs necessary tools, and + executes cargo criterion benchmarks on the kimchi crate. The benchmark results + are then posted as a comment on the pull request for review. - [Deploy Specifications & Docs to GitHub Pages](.github/workflows/gh-page.yml). - When CI passes on master, the documentation built from the rust code will be available by this [link](https://o1-labs.github.io/proof-systems/rustdoc) and the book will be available by this [link](https://o1-labs.github.io/proof-systems). + When CI passes on master, the documentation built from the rust code will be + available by this [link](https://o1-labs.github.io/proof-systems/rustdoc) and + the book will be available by this + [link](https://o1-labs.github.io/proof-systems). - [MIPS Build and Package](.github/workflows/mips-build.yml) - This workflow runs the assembler and linker on the programs from the OpenMips test suite, and provides a link where you can download the artifacts (recommended if you don't have / can't install the required MIPS tooling). This workflow also runs the o1vm ELF parser on the artifacts to check that our parsing is working. Currently it is run via manual trigger only -- you can find the trigger in the [GitHub actions tab](https://github.com/o1-labs/proof-systems/actions/workflows/mips-build.yml) and the link to the artifacts will appear in logs of the `Upload Artifacts` stage. + This workflow runs the assembler and linker on the programs from the OpenMips + test suite, and provides a link where you can download the artifacts + (recommended if you don't have / can't install the required MIPS tooling). + This workflow also runs the o1vm ELF parser on the artifacts to check that our + parsing is working. Currently it is run via manual trigger only -- you can + find the trigger in the [GitHub actions + tab](https://github.com/o1-labs/proof-systems/actions/workflows/mips-build.yml) + and the link to the artifacts will appear in logs of the `Upload Artifacts` + stage. ## Nix for Dependencies (WIP) -If you have `nix` installed and in particular, `flakes` enabled, you can install the dependencies for these projects using nix. Simply `nix develop .` inside this directory to bring into scope `rustup`, `opam`, and `go` (along with a few other tools). You will have to manage the toolchains yourself using `rustup` and `opam`, in the current iteration. +If you have `nix` installed and in particular, `flakes` enabled, you can install +the dependencies for these projects using nix. Simply `nix develop .` inside +this directory to bring into scope `rustup`, `opam`, and `go` (along with a few +other tools). You will have to manage the toolchains yourself using `rustup` and +`opam`, in the current iteration. diff --git a/dune b/dune new file mode 100644 index 0000000000..5350117f8b --- /dev/null +++ b/dune @@ -0,0 +1,9 @@ +;; create a `dune-build-root` file that contains the dune workspace root + +(rule + (target dune-build-root) + (deps + ; no sandbox, we want the path to the _build directory + (sandbox none)) + (action + (system "printf \"%s\" $(realpath %{workspace_root}/..) > %{target}"))) diff --git a/dune-project b/dune-project new file mode 100644 index 0000000000..e22eecc024 --- /dev/null +++ b/dune-project @@ -0,0 +1,37 @@ +(lang dune 3.0) + +(generate_opam_files true) + +(source (github o1-labs/profo-systems)) +(license Apache-2.0) +(authors "O(1) Labs, LLC ") +(maintainers "O(1) Labs, LLC ") +(bug_reports "https://github.com/o1-labs/proof-systems/issues") +(homepage "https://github.com/o1-labs/proof-systems/") + +(package + (name kimchi_types) + (synopsis "OCaml bindings to types defined in Kimchi") + (depends + (dune (>= 3.0)) + (conf-rust (>= 0.1)) + ) +) + +(package + (name kimchi_bindings) + (synopsis "OCaml bindings to Kimchi") + (depends + (dune (>= 3.0)) + (conf-rust (>= 0.1)) + ) +) + +(package + (name pasta_bindings) + (synopsis "OCaml bindings to the Pasta curves") + (depends + (dune (>= 3.0)) + (conf-rust (>= 0.1)) + ) +) diff --git a/kimchi-stubs/.ocamlformat b/kimchi-stubs/.ocamlformat new file mode 100644 index 0000000000..1b2264a839 --- /dev/null +++ b/kimchi-stubs/.ocamlformat @@ -0,0 +1,46 @@ +profile=ocamlformat +quiet=false +max-iters=10 +comment-check=true +wrap-fun-args=true +wrap-comments=false +type-decl=compact +space-around-variants=true +space-around-records=true +space-around-lists=true +space-around-arrays=true +single-case=compact +sequence-style=separator +sequence-blank-line=preserve-one +parse-docstrings=false +parens-tuple=always +parens-ite=false +ocp-indent-compat=false +module-item-spacing=sparse +max-indent=68 +margin=80 +let-module=compact +let-binding-spacing=compact +let-and=compact +leading-nested-match-parens=false +infix-precedence=indent +indicate-nested-or-patterns=space +indicate-multiline-delimiters=space +if-then-else=compact +field-space=loose +exp-grouping=parens +dock-collection-brackets=false +doc-comments-tag-only=default +doc-comments-padding=2 +doc-comments=before +disable=false +cases-matching-exp-indent=normal +cases-exp-indent=4 +break-sequences=false +break-separators=before +break-infix-before-func=true +break-infix=wrap +break-fun-sig=wrap +break-fun-decl=wrap +break-cases=nested +assignment-operator=end-line diff --git a/kimchi-stubs/Cargo.toml b/kimchi-stubs/Cargo.toml index e5ae3d69a5..27b1474e09 100644 --- a/kimchi-stubs/Cargo.toml +++ b/kimchi-stubs/Cargo.toml @@ -41,3 +41,7 @@ mina-curves = { workspace = true } mina-poseidon = { workspace = true } o1-utils = { workspace = true } poly-commitment = { workspace = true, features = ["ocaml_types"] } + +[[bin]] +name = "main" +path = "src/bin/main.rs" diff --git a/kimchi-stubs/README.md b/kimchi-stubs/README.md new file mode 100644 index 0000000000..6cdbc1f9ae --- /dev/null +++ b/kimchi-stubs/README.md @@ -0,0 +1,11 @@ +# OCaml stubs for the Kimchi library + +This libary generates OCaml stubs that can be used in OCaml projects to call the +Kimchi primitives. + +## Setup dev environment + +``` +opam switch create ./ 4.14.0 +opam install ocamlformat merlin +``` diff --git a/kimchi-stubs/dune b/kimchi-stubs/dune new file mode 100644 index 0000000000..3e8d6efbc5 --- /dev/null +++ b/kimchi-stubs/dune @@ -0,0 +1,125 @@ +;; src/ contains no dune-related files + +(data_only_dirs src) + +;; Ignore target if it exists locally + +(dirs + :standard + \ + ../target + ../_riscv32-gnu-toolchain + ../_build + ../_opam + ../book) + +;; +;; Rules to set the optimisation flags for the rust compiler. +;; +;; By default, we compile with optimisations enabled. The instructions that +;; these generate may not be available on all CPU architectures; to build a +;; slower version that does not use these instructions, set the environment +;; variable `RUST_TARGET_FEATURE_OPTIMISATIONS=n`. +;; + +(rule + (enabled_if + (<> %{env:RUST_TARGET_FEATURE_OPTIMISATIONS=y} n)) + (targets rustflags.sexp) + (action + (with-stdout-to + rustflags.sexp + (echo "-C target-feature=+bmi2,+adx")))) + +(rule + (enabled_if + (= %{env:RUST_TARGET_FEATURE_OPTIMISATIONS=y} n)) + (targets rustflags.sexp) + (action + (with-stdout-to + rustflags.sexp + (echo "-C target-feature=-bmi2,-adx")))) + +;; +;; rules to build the static library for kimchi +;; + +;; note: to build Mina, nix will set `KIMCHI_STUBS` and ignore this rule + +(rule + (enabled_if + (= %{env:KIMCHI_STUBS=n} n)) + (targets libkimchi_stubs.a) + (deps + Cargo.toml + (source_tree src) + (source_tree ../) + (env_var KIMCHI_STUBS)) + (locks /cargo-lock) ;; lock for rustup + (action + (progn + (setenv + RUSTFLAGS + %{read:rustflags.sexp} + (run + cargo + build + -p + kimchi-stubs + --release + --target-dir + %{read:../dune-build-root}/cargo_kimchi_stubs)) + (run cp %{read:../dune-build-root}/cargo_kimchi_stubs/release/libkimchi_stubs.a .)))) + +;; +;; declare the libraries we're going to generate to match the bindings +;; + +(library + (public_name kimchi_types) + (name kimchi_types) + (modules kimchi_types) + (instrumentation + (backend bisect_ppx))) + +(library + (public_name pasta_bindings) + (name pasta_bindings) + (modules pasta_bindings) + (libraries kimchi_types) + (instrumentation + (backend bisect_ppx))) + +(library + (public_name kimchi_bindings) + (name kimchi_bindings) + (modules kimchi_bindings) + (libraries pasta_bindings kimchi_types) + (instrumentation + (backend bisect_ppx))) + +;; +;; generate the OCaml bindings +;; + +;; note: to build Mina, nix will set `KIMCHI_STUBS` and ignore this rule + +(rule + (targets kimchi_types.ml pasta_bindings.ml kimchi_bindings.ml) + (enabled_if + (= %{env:KIMCHI_STUBS=n} n)) + (mode promote) + (deps + .ocamlformat + Cargo.toml + (source_tree src) + (source_tree ../) + (env_var KIMCHI_STUBS)) + (locks /cargo-lock) ;; lock for rustup + (action + (progn + (setenv + CARGO_TARGET_DIR + "%{read:../dune-build-root}/cargo_kimchi_bindgen" + (run cargo run %{targets})) + (run ocamlformat -i %{targets})))) diff --git a/kimchi-stubs/kimchi_bindings.ml b/kimchi-stubs/kimchi_bindings.ml new file mode 100644 index 0000000000..8e2e05126c --- /dev/null +++ b/kimchi-stubs/kimchi_bindings.ml @@ -0,0 +1,592 @@ +(* This file is generated automatically with ocaml_gen. *) + +module FieldVectors = struct + module Fp = struct + type nonrec t + + type nonrec elt = Pasta_bindings.Fp.t + + external create : unit -> t = "caml_fp_vector_create" + + external length : t -> int = "caml_fp_vector_length" + + external emplace_back : t -> elt -> unit = "caml_fp_vector_emplace_back" + + external get : t -> int -> elt = "caml_fp_vector_get" + + external set : t -> int -> elt -> unit = "caml_fp_vector_set" + end + + module Fq = struct + type nonrec t + + type nonrec elt = Pasta_bindings.Fq.t + + external create : unit -> t = "caml_fq_vector_create" + + external length : t -> int = "caml_fq_vector_length" + + external emplace_back : t -> elt -> unit = "caml_fq_vector_emplace_back" + + external get : t -> int -> elt = "caml_fq_vector_get" + + external set : t -> int -> elt -> unit = "caml_fq_vector_set" + end +end + +module Protocol = struct + module Gates = struct + module Vector = struct + module Fp = struct + type nonrec t + + type nonrec elt = Pasta_bindings.Fp.t Kimchi_types.circuit_gate + + external create : unit -> t = "caml_pasta_fp_plonk_gate_vector_create" + + external add : t -> elt -> unit = "caml_pasta_fp_plonk_gate_vector_add" + + external get : t -> int -> elt = "caml_pasta_fp_plonk_gate_vector_get" + + external len : t -> int = "caml_pasta_fp_plonk_gate_vector_len" + + external wrap : t -> Kimchi_types.wire -> Kimchi_types.wire -> unit + = "caml_pasta_fp_plonk_gate_vector_wrap" + + external digest : int -> t -> bytes + = "caml_pasta_fp_plonk_gate_vector_digest" + + external to_json : int -> t -> string + = "caml_pasta_fp_plonk_circuit_serialize" + end + + module Fq = struct + type nonrec t + + type nonrec elt = Pasta_bindings.Fq.t Kimchi_types.circuit_gate + + external create : unit -> t = "caml_pasta_fq_plonk_gate_vector_create" + + external add : t -> elt -> unit = "caml_pasta_fq_plonk_gate_vector_add" + + external get : t -> int -> elt = "caml_pasta_fq_plonk_gate_vector_get" + + external len : t -> int = "caml_pasta_fq_plonk_gate_vector_len" + + external wrap : t -> Kimchi_types.wire -> Kimchi_types.wire -> unit + = "caml_pasta_fq_plonk_gate_vector_wrap" + + external digest : int -> t -> bytes + = "caml_pasta_fq_plonk_gate_vector_digest" + + external to_json : int -> t -> string + = "caml_pasta_fq_plonk_circuit_serialize" + end + end + end + + module SRS = struct + module Fp = struct + type nonrec t + + module Poly_comm = struct + type nonrec t = + Pasta_bindings.Fp.t Kimchi_types.or_infinity Kimchi_types.poly_comm + end + + external create : int -> t = "caml_fp_srs_create" + + external write : bool option -> t -> string -> unit = "caml_fp_srs_write" + + external read : int option -> string -> t option = "caml_fp_srs_read" + + external lagrange_commitment : + t + -> int + -> int + -> Pasta_bindings.Fq.t Kimchi_types.or_infinity Kimchi_types.poly_comm + = "caml_fp_srs_lagrange_commitment" + + external lagrange_commitments_whole_domain : + t + -> int + -> Pasta_bindings.Fq.t Kimchi_types.or_infinity Kimchi_types.poly_comm + array = "caml_fp_srs_lagrange_commitments_whole_domain" + + external add_lagrange_basis : t -> int -> unit + = "caml_fp_srs_add_lagrange_basis" + + external commit_evaluations : + t + -> int + -> Pasta_bindings.Fp.t array + -> Pasta_bindings.Fq.t Kimchi_types.or_infinity Kimchi_types.poly_comm + = "caml_fp_srs_commit_evaluations" + + external b_poly_commitment : + t + -> Pasta_bindings.Fp.t array + -> Pasta_bindings.Fq.t Kimchi_types.or_infinity Kimchi_types.poly_comm + = "caml_fp_srs_b_poly_commitment" + + external batch_accumulator_check : + t + -> Pasta_bindings.Fq.t Kimchi_types.or_infinity array + -> Pasta_bindings.Fp.t array + -> bool = "caml_fp_srs_batch_accumulator_check" + + external batch_accumulator_generate : + t + -> int + -> Pasta_bindings.Fp.t array + -> Pasta_bindings.Fq.t Kimchi_types.or_infinity array + = "caml_fp_srs_batch_accumulator_generate" + + external urs_h : t -> Pasta_bindings.Fq.t Kimchi_types.or_infinity + = "caml_fp_srs_h" + end + + module Fq = struct + type nonrec t + + external create : int -> t = "caml_fq_srs_create" + + external write : bool option -> t -> string -> unit = "caml_fq_srs_write" + + external read : int option -> string -> t option = "caml_fq_srs_read" + + external lagrange_commitment : + t + -> int + -> int + -> Pasta_bindings.Fp.t Kimchi_types.or_infinity Kimchi_types.poly_comm + = "caml_fq_srs_lagrange_commitment" + + external lagrange_commitments_whole_domain : + t + -> int + -> Pasta_bindings.Fp.t Kimchi_types.or_infinity Kimchi_types.poly_comm + array = "caml_fq_srs_lagrange_commitments_whole_domain" + + external add_lagrange_basis : t -> int -> unit + = "caml_fq_srs_add_lagrange_basis" + + external commit_evaluations : + t + -> int + -> Pasta_bindings.Fq.t array + -> Pasta_bindings.Fp.t Kimchi_types.or_infinity Kimchi_types.poly_comm + = "caml_fq_srs_commit_evaluations" + + external b_poly_commitment : + t + -> Pasta_bindings.Fq.t array + -> Pasta_bindings.Fp.t Kimchi_types.or_infinity Kimchi_types.poly_comm + = "caml_fq_srs_b_poly_commitment" + + external batch_accumulator_check : + t + -> Pasta_bindings.Fp.t Kimchi_types.or_infinity array + -> Pasta_bindings.Fq.t array + -> bool = "caml_fq_srs_batch_accumulator_check" + + external batch_accumulator_generate : + t + -> int + -> Pasta_bindings.Fq.t array + -> Pasta_bindings.Fp.t Kimchi_types.or_infinity array + = "caml_fq_srs_batch_accumulator_generate" + + external urs_h : t -> Pasta_bindings.Fp.t Kimchi_types.or_infinity + = "caml_fq_srs_h" + end + end + + module Index = struct + module Fp = struct + type nonrec t + + external create : + Gates.Vector.Fp.t + -> int + -> Pasta_bindings.Fp.t Kimchi_types.lookup_table array + -> Pasta_bindings.Fp.t Kimchi_types.runtime_table_cfg array + -> int + -> SRS.Fp.t + -> bool + -> t + = "caml_pasta_fp_plonk_index_create_bytecode" + "caml_pasta_fp_plonk_index_create" + + external max_degree : t -> int = "caml_pasta_fp_plonk_index_max_degree" + + external public_inputs : t -> int + = "caml_pasta_fp_plonk_index_public_inputs" + + external domain_d1_size : t -> int + = "caml_pasta_fp_plonk_index_domain_d1_size" + + external domain_d4_size : t -> int + = "caml_pasta_fp_plonk_index_domain_d4_size" + + external domain_d8_size : t -> int + = "caml_pasta_fp_plonk_index_domain_d8_size" + + external read : int option -> SRS.Fp.t -> string -> t + = "caml_pasta_fp_plonk_index_read" + + external write : bool option -> t -> string -> unit + = "caml_pasta_fp_plonk_index_write" + end + + module Fq = struct + type nonrec t + + external create : + Gates.Vector.Fq.t + -> int + -> Pasta_bindings.Fq.t Kimchi_types.lookup_table array + -> Pasta_bindings.Fq.t Kimchi_types.runtime_table_cfg array + -> int + -> SRS.Fq.t + -> bool + -> t + = "caml_pasta_fq_plonk_index_create_bytecode" + "caml_pasta_fq_plonk_index_create" + + external max_degree : t -> int = "caml_pasta_fq_plonk_index_max_degree" + + external public_inputs : t -> int + = "caml_pasta_fq_plonk_index_public_inputs" + + external domain_d1_size : t -> int + = "caml_pasta_fq_plonk_index_domain_d1_size" + + external domain_d4_size : t -> int + = "caml_pasta_fq_plonk_index_domain_d4_size" + + external domain_d8_size : t -> int + = "caml_pasta_fq_plonk_index_domain_d8_size" + + external read : int option -> SRS.Fq.t -> string -> t + = "caml_pasta_fq_plonk_index_read" + + external write : bool option -> t -> string -> unit + = "caml_pasta_fq_plonk_index_write" + end + end + + module VerifierIndex = struct + module Fp = struct + type nonrec t = + ( Pasta_bindings.Fp.t + , SRS.Fp.t + , Pasta_bindings.Fq.t Kimchi_types.or_infinity Kimchi_types.poly_comm + ) + Kimchi_types.VerifierIndex.verifier_index + + external create : Index.Fp.t -> t + = "caml_pasta_fp_plonk_verifier_index_create" + + external read : int option -> SRS.Fp.t -> string -> t + = "caml_pasta_fp_plonk_verifier_index_read" + + external write : bool option -> t -> string -> unit + = "caml_pasta_fp_plonk_verifier_index_write" + + external shifts : int -> Pasta_bindings.Fp.t array + = "caml_pasta_fp_plonk_verifier_index_shifts" + + external dummy : unit -> t = "caml_pasta_fp_plonk_verifier_index_dummy" + + external deep_copy : t -> t + = "caml_pasta_fp_plonk_verifier_index_deep_copy" + end + + module Fq = struct + type nonrec t = + ( Pasta_bindings.Fq.t + , SRS.Fq.t + , Pasta_bindings.Fp.t Kimchi_types.or_infinity Kimchi_types.poly_comm + ) + Kimchi_types.VerifierIndex.verifier_index + + external create : Index.Fq.t -> t + = "caml_pasta_fq_plonk_verifier_index_create" + + external read : int option -> SRS.Fq.t -> string -> t + = "caml_pasta_fq_plonk_verifier_index_read" + + external write : bool option -> t -> string -> unit + = "caml_pasta_fq_plonk_verifier_index_write" + + external shifts : int -> Pasta_bindings.Fq.t array + = "caml_pasta_fq_plonk_verifier_index_shifts" + + external dummy : unit -> t = "caml_pasta_fq_plonk_verifier_index_dummy" + + external deep_copy : t -> t + = "caml_pasta_fq_plonk_verifier_index_deep_copy" + end + end + + module Oracles = struct + module Fp = struct + type nonrec t = Pasta_bindings.Fp.t Kimchi_types.oracles + + external create : + Pasta_bindings.Fq.t Kimchi_types.or_infinity Kimchi_types.poly_comm + array + -> ( Pasta_bindings.Fp.t + , SRS.Fp.t + , Pasta_bindings.Fq.t Kimchi_types.or_infinity Kimchi_types.poly_comm + ) + Kimchi_types.VerifierIndex.verifier_index + -> ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.prover_proof + -> t = "fp_oracles_create_no_public" + + external create_with_public_evals : + Pasta_bindings.Fq.t Kimchi_types.or_infinity Kimchi_types.poly_comm + array + -> ( Pasta_bindings.Fp.t + , SRS.Fp.t + , Pasta_bindings.Fq.t Kimchi_types.or_infinity Kimchi_types.poly_comm + ) + Kimchi_types.VerifierIndex.verifier_index + -> ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.proof_with_public + -> t = "fp_oracles_create" + + external dummy : unit -> Pasta_bindings.Fp.t Kimchi_types.random_oracles + = "fp_oracles_dummy" + + external deep_copy : + Pasta_bindings.Fp.t Kimchi_types.random_oracles + -> Pasta_bindings.Fp.t Kimchi_types.random_oracles + = "fp_oracles_deep_copy" + end + + module Fq = struct + type nonrec t = Pasta_bindings.Fq.t Kimchi_types.oracles + + external create : + Pasta_bindings.Fp.t Kimchi_types.or_infinity Kimchi_types.poly_comm + array + -> ( Pasta_bindings.Fq.t + , SRS.Fq.t + , Pasta_bindings.Fp.t Kimchi_types.or_infinity Kimchi_types.poly_comm + ) + Kimchi_types.VerifierIndex.verifier_index + -> ( Pasta_bindings.Fp.t Kimchi_types.or_infinity + , Pasta_bindings.Fq.t ) + Kimchi_types.prover_proof + -> t = "fq_oracles_create_no_public" + + external create_with_public_evals : + Pasta_bindings.Fp.t Kimchi_types.or_infinity Kimchi_types.poly_comm + array + -> ( Pasta_bindings.Fq.t + , SRS.Fq.t + , Pasta_bindings.Fp.t Kimchi_types.or_infinity Kimchi_types.poly_comm + ) + Kimchi_types.VerifierIndex.verifier_index + -> ( Pasta_bindings.Fp.t Kimchi_types.or_infinity + , Pasta_bindings.Fq.t ) + Kimchi_types.proof_with_public + -> t = "fq_oracles_create" + + external dummy : unit -> Pasta_bindings.Fq.t Kimchi_types.random_oracles + = "fq_oracles_dummy" + + external deep_copy : + Pasta_bindings.Fq.t Kimchi_types.random_oracles + -> Pasta_bindings.Fq.t Kimchi_types.random_oracles + = "fq_oracles_deep_copy" + end + end + + module Proof = struct + module Fp = struct + external create : + Index.Fp.t + -> FieldVectors.Fp.t array + -> Pasta_bindings.Fp.t Kimchi_types.runtime_table array + -> Pasta_bindings.Fp.t array + -> Pasta_bindings.Fq.t Kimchi_types.or_infinity array + -> ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.proof_with_public = "caml_pasta_fp_plonk_proof_create" + + external create_and_verify : + Index.Fp.t + -> FieldVectors.Fp.t array + -> Pasta_bindings.Fp.t Kimchi_types.runtime_table array + -> Pasta_bindings.Fp.t array + -> Pasta_bindings.Fq.t Kimchi_types.or_infinity array + -> ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.proof_with_public + = "caml_pasta_fp_plonk_proof_create_and_verify" + + external example_with_lookup : + SRS.Fp.t + -> bool + -> Index.Fp.t + * Pasta_bindings.Fp.t + * ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.proof_with_public + = "caml_pasta_fp_plonk_proof_example_with_lookup" + + external example_with_ffadd : + SRS.Fp.t + -> bool + -> Index.Fp.t + * Pasta_bindings.Fp.t + * ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.proof_with_public + = "caml_pasta_fp_plonk_proof_example_with_ffadd" + + external example_with_xor : + SRS.Fp.t + -> bool + -> Index.Fp.t + * (Pasta_bindings.Fp.t * Pasta_bindings.Fp.t) + * ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.proof_with_public + = "caml_pasta_fp_plonk_proof_example_with_xor" + + external example_with_rot : + SRS.Fp.t + -> bool + -> Index.Fp.t + * (Pasta_bindings.Fp.t * Pasta_bindings.Fp.t) + * ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.proof_with_public + = "caml_pasta_fp_plonk_proof_example_with_rot" + + external example_with_foreign_field_mul : + SRS.Fp.t + -> bool + -> Index.Fp.t + * ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.proof_with_public + = "caml_pasta_fp_plonk_proof_example_with_foreign_field_mul" + + external example_with_range_check : + SRS.Fp.t + -> bool + -> Index.Fp.t + * ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.proof_with_public + = "caml_pasta_fp_plonk_proof_example_with_range_check" + + external example_with_range_check0 : + SRS.Fp.t + -> bool + -> Index.Fp.t + * ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.proof_with_public + = "caml_pasta_fp_plonk_proof_example_with_range_check0" + + external verify : + ( Pasta_bindings.Fp.t + , SRS.Fp.t + , Pasta_bindings.Fq.t Kimchi_types.or_infinity Kimchi_types.poly_comm + ) + Kimchi_types.VerifierIndex.verifier_index + -> ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.proof_with_public + -> bool = "caml_pasta_fp_plonk_proof_verify" + + external batch_verify : + ( Pasta_bindings.Fp.t + , SRS.Fp.t + , Pasta_bindings.Fq.t Kimchi_types.or_infinity Kimchi_types.poly_comm + ) + Kimchi_types.VerifierIndex.verifier_index + array + -> ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.proof_with_public + array + -> bool = "caml_pasta_fp_plonk_proof_batch_verify" + + external dummy : + unit + -> ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.proof_with_public = "caml_pasta_fp_plonk_proof_dummy" + + external deep_copy : + ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.proof_with_public + -> ( Pasta_bindings.Fq.t Kimchi_types.or_infinity + , Pasta_bindings.Fp.t ) + Kimchi_types.proof_with_public + = "caml_pasta_fp_plonk_proof_deep_copy" + end + + module Fq = struct + external create : + Index.Fq.t + -> FieldVectors.Fq.t array + -> Pasta_bindings.Fq.t Kimchi_types.runtime_table array + -> Pasta_bindings.Fq.t array + -> Pasta_bindings.Fp.t Kimchi_types.or_infinity array + -> ( Pasta_bindings.Fp.t Kimchi_types.or_infinity + , Pasta_bindings.Fq.t ) + Kimchi_types.proof_with_public = "caml_pasta_fq_plonk_proof_create" + + external verify : + ( Pasta_bindings.Fq.t + , SRS.Fq.t + , Pasta_bindings.Fp.t Kimchi_types.or_infinity Kimchi_types.poly_comm + ) + Kimchi_types.VerifierIndex.verifier_index + -> ( Pasta_bindings.Fp.t Kimchi_types.or_infinity + , Pasta_bindings.Fq.t ) + Kimchi_types.proof_with_public + -> bool = "caml_pasta_fq_plonk_proof_verify" + + external batch_verify : + ( Pasta_bindings.Fq.t + , SRS.Fq.t + , Pasta_bindings.Fp.t Kimchi_types.or_infinity Kimchi_types.poly_comm + ) + Kimchi_types.VerifierIndex.verifier_index + array + -> ( Pasta_bindings.Fp.t Kimchi_types.or_infinity + , Pasta_bindings.Fq.t ) + Kimchi_types.proof_with_public + array + -> bool = "caml_pasta_fq_plonk_proof_batch_verify" + + external dummy : + unit + -> ( Pasta_bindings.Fp.t Kimchi_types.or_infinity + , Pasta_bindings.Fq.t ) + Kimchi_types.proof_with_public = "caml_pasta_fq_plonk_proof_dummy" + + external deep_copy : + ( Pasta_bindings.Fp.t Kimchi_types.or_infinity + , Pasta_bindings.Fq.t ) + Kimchi_types.proof_with_public + -> ( Pasta_bindings.Fp.t Kimchi_types.or_infinity + , Pasta_bindings.Fq.t ) + Kimchi_types.proof_with_public + = "caml_pasta_fq_plonk_proof_deep_copy" + end + end +end diff --git a/kimchi-stubs/kimchi_types.ml b/kimchi-stubs/kimchi_types.ml new file mode 100644 index 0000000000..6bec0f01f8 --- /dev/null +++ b/kimchi-stubs/kimchi_types.ml @@ -0,0 +1,259 @@ +(* This file is generated automatically with ocaml_gen. *) +type nonrec 'f or_infinity = Infinity | Finite of ('f * 'f) + +type nonrec 'caml_f scalar_challenge = { inner : 'caml_f } [@@boxed] + +type nonrec 'caml_f random_oracles = + { joint_combiner : ('caml_f scalar_challenge * 'caml_f) option + ; beta : 'caml_f + ; gamma : 'caml_f + ; alpha_chal : 'caml_f scalar_challenge + ; alpha : 'caml_f + ; zeta : 'caml_f + ; v : 'caml_f + ; u : 'caml_f + ; zeta_chal : 'caml_f scalar_challenge + ; v_chal : 'caml_f scalar_challenge + ; u_chal : 'caml_f scalar_challenge + } + +type nonrec 'evals point_evaluations = { zeta : 'evals; zeta_omega : 'evals } + +type nonrec 'caml_f proof_evaluations = + { w : + 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + ; z : 'caml_f array point_evaluations + ; s : + 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + ; coefficients : + 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + * 'caml_f array point_evaluations + ; generic_selector : 'caml_f array point_evaluations + ; poseidon_selector : 'caml_f array point_evaluations + ; complete_add_selector : 'caml_f array point_evaluations + ; mul_selector : 'caml_f array point_evaluations + ; emul_selector : 'caml_f array point_evaluations + ; endomul_scalar_selector : 'caml_f array point_evaluations + ; range_check0_selector : 'caml_f array point_evaluations option + ; range_check1_selector : 'caml_f array point_evaluations option + ; foreign_field_add_selector : 'caml_f array point_evaluations option + ; foreign_field_mul_selector : 'caml_f array point_evaluations option + ; xor_selector : 'caml_f array point_evaluations option + ; rot_selector : 'caml_f array point_evaluations option + ; lookup_aggregation : 'caml_f array point_evaluations option + ; lookup_table : 'caml_f array point_evaluations option + ; lookup_sorted : 'caml_f array point_evaluations option array + ; runtime_lookup_table : 'caml_f array point_evaluations option + ; runtime_lookup_table_selector : 'caml_f array point_evaluations option + ; xor_lookup_selector : 'caml_f array point_evaluations option + ; lookup_gate_lookup_selector : 'caml_f array point_evaluations option + ; range_check_lookup_selector : 'caml_f array point_evaluations option + ; foreign_field_mul_lookup_selector : 'caml_f array point_evaluations option + } + +type nonrec 'caml_g poly_comm = + { unshifted : 'caml_g array; shifted : 'caml_g option } + +type nonrec ('caml_g, 'caml_f) recursion_challenge = + { chals : 'caml_f array; comm : 'caml_g poly_comm } + +type nonrec ('g, 'f) opening_proof = + { lr : ('g * 'g) array; delta : 'g; z1 : 'f; z2 : 'f; sg : 'g } + +type nonrec 'caml_g lookup_commitments = + { sorted : 'caml_g poly_comm array + ; aggreg : 'caml_g poly_comm + ; runtime : 'caml_g poly_comm option + } + +type nonrec 'caml_f runtime_table_cfg = + { id : int32; first_column : 'caml_f array } + +type nonrec 'caml_f lookup_table = { id : int32; data : 'caml_f array array } + +type nonrec 'caml_f runtime_table = { id : int32; data : 'caml_f array } + +type nonrec 'caml_g prover_commitments = + { w_comm : + 'caml_g poly_comm + * 'caml_g poly_comm + * 'caml_g poly_comm + * 'caml_g poly_comm + * 'caml_g poly_comm + * 'caml_g poly_comm + * 'caml_g poly_comm + * 'caml_g poly_comm + * 'caml_g poly_comm + * 'caml_g poly_comm + * 'caml_g poly_comm + * 'caml_g poly_comm + * 'caml_g poly_comm + * 'caml_g poly_comm + * 'caml_g poly_comm + ; z_comm : 'caml_g poly_comm + ; t_comm : 'caml_g poly_comm + ; lookup : 'caml_g lookup_commitments option + } + +type nonrec ('caml_g, 'caml_f) prover_proof = + { commitments : 'caml_g prover_commitments + ; proof : ('caml_g, 'caml_f) opening_proof + ; evals : 'caml_f proof_evaluations + ; ft_eval1 : 'caml_f + ; public : 'caml_f array + ; prev_challenges : ('caml_g, 'caml_f) recursion_challenge array + } + +type nonrec ('caml_g, 'caml_f) proof_with_public = + { public_evals : 'caml_f array point_evaluations option + ; proof : ('caml_g, 'caml_f) prover_proof + } + +type nonrec wire = { row : int; col : int } + +type nonrec gate_type = + | Zero + | Generic + | Poseidon + | CompleteAdd + | VarBaseMul + | EndoMul + | EndoMulScalar + | Lookup + | CairoClaim + | CairoInstruction + | CairoFlags + | CairoTransition + | RangeCheck0 + | RangeCheck1 + | ForeignFieldAdd + | ForeignFieldMul + | Xor16 + | Rot64 + +type nonrec lookup_pattern = Xor | Lookup | RangeCheck | ForeignFieldMul + +type nonrec lookup_patterns = + { xor : bool; lookup : bool; range_check : bool; foreign_field_mul : bool } + +type nonrec lookup_features = + { patterns : lookup_patterns + ; joint_lookup_used : bool + ; uses_runtime_tables : bool + } + +type nonrec feature_flag = + | RangeCheck0 + | RangeCheck1 + | ForeignFieldAdd + | ForeignFieldMul + | Xor + | Rot + | LookupTables + | RuntimeLookupTables + | LookupPattern of lookup_pattern + | TableWidth of int + | LookupsPerRow of int + +type nonrec 'f circuit_gate = + { typ : gate_type + ; wires : wire * wire * wire * wire * wire * wire * wire + ; coeffs : 'f array + } + +type nonrec curr_or_next = Curr | Next + +type nonrec 'f oracles = + { o : 'f random_oracles + ; p_eval : 'f * 'f + ; opening_prechallenges : 'f array + ; digest_before_evaluations : 'f + } + +module VerifierIndex = struct + module Lookup = struct + type nonrec lookups_used = Single | Joint + + type nonrec lookup_info = + { max_per_row : int; max_joint_size : int; features : lookup_features } + + type nonrec 't lookup_selectors = + { lookup : 't option + ; xor : 't option + ; range_check : 't option + ; ffmul : 't option + } + + type nonrec 'poly_comm t = + { joint_lookup_used : bool + ; lookup_table : 'poly_comm array + ; lookup_selectors : 'poly_comm lookup_selectors + ; table_ids : 'poly_comm option + ; lookup_info : lookup_info + ; runtime_tables_selector : 'poly_comm option + } + end + + type nonrec 'fr domain = { log_size_of_group : int; group_gen : 'fr } + + type nonrec 'poly_comm verification_evals = + { sigma_comm : 'poly_comm array + ; coefficients_comm : 'poly_comm array + ; generic_comm : 'poly_comm + ; psm_comm : 'poly_comm + ; complete_add_comm : 'poly_comm + ; mul_comm : 'poly_comm + ; emul_comm : 'poly_comm + ; endomul_scalar_comm : 'poly_comm + ; xor_comm : 'poly_comm option + ; range_check0_comm : 'poly_comm option + ; range_check1_comm : 'poly_comm option + ; foreign_field_add_comm : 'poly_comm option + ; foreign_field_mul_comm : 'poly_comm option + ; rot_comm : 'poly_comm option + } + + type nonrec ('fr, 'srs, 'poly_comm) verifier_index = + { domain : 'fr domain + ; max_poly_size : int + ; public : int + ; prev_challenges : int + ; srs : 'srs + ; evals : 'poly_comm verification_evals + ; shifts : 'fr array + ; lookup_index : 'poly_comm Lookup.t option + ; zk_rows : int + } +end diff --git a/kimchi-stubs/pasta_bindings.ml b/kimchi-stubs/pasta_bindings.ml new file mode 100644 index 0000000000..59a1619108 --- /dev/null +++ b/kimchi-stubs/pasta_bindings.ml @@ -0,0 +1,265 @@ +(* This file is generated automatically with ocaml_gen. *) + +module BigInt256 = struct + type nonrec t + + external of_numeral : string -> int -> int -> t = "caml_bigint_256_of_numeral" + + external of_decimal_string : string -> t = "caml_bigint_256_of_decimal_string" + + external num_limbs : unit -> int = "caml_bigint_256_num_limbs" + + external bytes_per_limb : unit -> int = "caml_bigint_256_bytes_per_limb" + + external div : t -> t -> t = "caml_bigint_256_div" + + external compare : t -> t -> int = "caml_bigint_256_compare" + + external print : t -> unit = "caml_bigint_256_print" + + external to_string : t -> string = "caml_bigint_256_to_string" + + external test_bit : t -> int -> bool = "caml_bigint_256_test_bit" + + external to_bytes : t -> bytes = "caml_bigint_256_to_bytes" + + external of_bytes : bytes -> t = "caml_bigint_256_of_bytes" + + external deep_copy : t -> t = "caml_bigint_256_deep_copy" +end + +module Fp = struct + type nonrec t + + external size_in_bits : unit -> int = "caml_pasta_fp_size_in_bits" + + external size : unit -> BigInt256.t = "caml_pasta_fp_size" + + external add : t -> t -> t = "caml_pasta_fp_add" + + external sub : t -> t -> t = "caml_pasta_fp_sub" + + external negate : t -> t = "caml_pasta_fp_negate" + + external mul : t -> t -> t = "caml_pasta_fp_mul" + + external div : t -> t -> t = "caml_pasta_fp_div" + + external inv : t -> t option = "caml_pasta_fp_inv" + + external square : t -> t = "caml_pasta_fp_square" + + external is_square : t -> bool = "caml_pasta_fp_is_square" + + external sqrt : t -> t option = "caml_pasta_fp_sqrt" + + external of_int : int -> t = "caml_pasta_fp_of_int" + + external to_string : t -> string = "caml_pasta_fp_to_string" + + external of_string : string -> t = "caml_pasta_fp_of_string" + + external print : t -> unit = "caml_pasta_fp_print" + + external print_rust : t -> unit = "caml_pasta_fp_print_rust" + + external copy : t -> t -> unit = "caml_pasta_fp_copy" + + external mut_add : t -> t -> unit = "caml_pasta_fp_mut_add" + + external mut_sub : t -> t -> unit = "caml_pasta_fp_mut_sub" + + external mut_mul : t -> t -> unit = "caml_pasta_fp_mut_mul" + + external mut_square : t -> unit = "caml_pasta_fp_mut_square" + + external compare : t -> t -> int = "caml_pasta_fp_compare" + + external equal : t -> t -> bool = "caml_pasta_fp_equal" + + external random : unit -> t = "caml_pasta_fp_random" + + external rng : int -> t = "caml_pasta_fp_rng" + + external to_bigint : t -> BigInt256.t = "caml_pasta_fp_to_bigint" + + external of_bigint : BigInt256.t -> t = "caml_pasta_fp_of_bigint" + + external two_adic_root_of_unity : unit -> t + = "caml_pasta_fp_two_adic_root_of_unity" + + external domain_generator : int -> t = "caml_pasta_fp_domain_generator" + + external to_bytes : t -> bytes = "caml_pasta_fp_to_bytes" + + external of_bytes : bytes -> t = "caml_pasta_fp_of_bytes" + + external deep_copy : t -> t = "caml_pasta_fp_deep_copy" +end + +module Fq = struct + type nonrec t + + external size_in_bits : unit -> int = "caml_pasta_fq_size_in_bits" + + external size : unit -> BigInt256.t = "caml_pasta_fq_size" + + external add : t -> t -> t = "caml_pasta_fq_add" + + external sub : t -> t -> t = "caml_pasta_fq_sub" + + external negate : t -> t = "caml_pasta_fq_negate" + + external mul : t -> t -> t = "caml_pasta_fq_mul" + + external div : t -> t -> t = "caml_pasta_fq_div" + + external inv : t -> t option = "caml_pasta_fq_inv" + + external square : t -> t = "caml_pasta_fq_square" + + external is_square : t -> bool = "caml_pasta_fq_is_square" + + external sqrt : t -> t option = "caml_pasta_fq_sqrt" + + external of_int : int -> t = "caml_pasta_fq_of_int" + + external to_string : t -> string = "caml_pasta_fq_to_string" + + external of_string : string -> t = "caml_pasta_fq_of_string" + + external print : t -> unit = "caml_pasta_fq_print" + + external print_rust : t -> unit = "caml_pasta_fq_print_rust" + + external copy : t -> t -> unit = "caml_pasta_fq_copy" + + external mut_add : t -> t -> unit = "caml_pasta_fq_mut_add" + + external mut_sub : t -> t -> unit = "caml_pasta_fq_mut_sub" + + external mut_mul : t -> t -> unit = "caml_pasta_fq_mut_mul" + + external mut_square : t -> unit = "caml_pasta_fq_mut_square" + + external compare : t -> t -> int = "caml_pasta_fq_compare" + + external equal : t -> t -> bool = "caml_pasta_fq_equal" + + external random : unit -> t = "caml_pasta_fq_random" + + external rng : int -> t = "caml_pasta_fq_rng" + + external to_bigint : t -> BigInt256.t = "caml_pasta_fq_to_bigint" + + external of_bigint : BigInt256.t -> t = "caml_pasta_fq_of_bigint" + + external two_adic_root_of_unity : unit -> t + = "caml_pasta_fq_two_adic_root_of_unity" + + external domain_generator : int -> t = "caml_pasta_fq_domain_generator" + + external to_bytes : t -> bytes = "caml_pasta_fq_to_bytes" + + external of_bytes : bytes -> t = "caml_pasta_fq_of_bytes" + + external deep_copy : t -> t = "caml_pasta_fq_deep_copy" +end + +module Vesta = struct + module BaseField = struct + type nonrec t = Fq.t + end + + module ScalarField = struct + type nonrec t = Fp.t + end + + module Affine = struct + type nonrec t = Fq.t Kimchi_types.or_infinity + end + + type nonrec t + + external one : unit -> t = "caml_vesta_one" + + external add : t -> t -> t = "caml_vesta_add" + + external sub : t -> t -> t = "caml_vesta_sub" + + external negate : t -> t = "caml_vesta_negate" + + external double : t -> t = "caml_vesta_double" + + external scale : t -> Fp.t -> t = "caml_vesta_scale" + + external random : unit -> t = "caml_vesta_random" + + external rng : int -> t = "caml_vesta_rng" + + external endo_base : unit -> Fq.t = "caml_vesta_endo_base" + + external endo_scalar : unit -> Fp.t = "caml_vesta_endo_scalar" + + external to_affine : t -> Fq.t Kimchi_types.or_infinity + = "caml_vesta_to_affine" + + external of_affine : Fq.t Kimchi_types.or_infinity -> t + = "caml_vesta_of_affine" + + external of_affine_coordinates : Fq.t -> Fq.t -> t + = "caml_vesta_of_affine_coordinates" + + external deep_copy : + Fq.t Kimchi_types.or_infinity -> Fq.t Kimchi_types.or_infinity + = "caml_vesta_affine_deep_copy" +end + +module Pallas = struct + module BaseField = struct + type nonrec t = Fp.t + end + + module ScalarField = struct + type nonrec t = Fq.t + end + + module Affine = struct + type nonrec t = Fp.t Kimchi_types.or_infinity + end + + type nonrec t + + external one : unit -> t = "caml_pallas_one" + + external add : t -> t -> t = "caml_pallas_add" + + external sub : t -> t -> t = "caml_pallas_sub" + + external negate : t -> t = "caml_pallas_negate" + + external double : t -> t = "caml_pallas_double" + + external scale : t -> Fq.t -> t = "caml_pallas_scale" + + external random : unit -> t = "caml_pallas_random" + + external rng : int -> t = "caml_pallas_rng" + + external endo_base : unit -> Fp.t = "caml_pallas_endo_base" + + external endo_scalar : unit -> Fq.t = "caml_pallas_endo_scalar" + + external to_affine : t -> Fp.t Kimchi_types.or_infinity + = "caml_pallas_to_affine" + + external of_affine : Fp.t Kimchi_types.or_infinity -> t + = "caml_pallas_of_affine" + + external of_affine_coordinates : Fp.t -> Fp.t -> t + = "caml_pallas_of_affine_coordinates" + + external deep_copy : + Fp.t Kimchi_types.or_infinity -> Fp.t Kimchi_types.or_infinity + = "caml_pallas_affine_deep_copy" +end diff --git a/kimchi-stubs/src/bin/main.rs b/kimchi-stubs/src/bin/main.rs new file mode 100644 index 0000000000..d1f27ce1c0 --- /dev/null +++ b/kimchi-stubs/src/bin/main.rs @@ -0,0 +1,491 @@ +use kimchi::{ + circuits::{ + expr::FeatureFlag, + lookup::{ + lookups::{LookupFeatures, LookupPattern, LookupPatterns}, + runtime_tables::caml::{CamlRuntimeTable, CamlRuntimeTableCfg}, + tables::caml::CamlLookupTable, + }, + }, + proof::{caml::CamlRecursionChallenge, PointEvaluations}, +}; +use kimchi_stubs::{ + // we must import all here, to have access to the derived functions + arkworks::{bigint_256::*, group_affine::*, group_projective::*, pasta_fp::*, pasta_fq::*}, + field_vector::{fp::*, fq::*}, + gate_vector::{fp::*, fq::*}, + oracles::{fp::*, fq::*, CamlOracles}, + pasta_fp_plonk_index::*, + pasta_fp_plonk_proof::*, + pasta_fp_plonk_verifier_index::*, + pasta_fq_plonk_index::*, + pasta_fq_plonk_proof::*, + pasta_fq_plonk_verifier_index::*, + plonk_verifier_index::{ + CamlLookupInfo, CamlLookupSelectors, CamlLookupVerifierIndex, CamlLookupsUsed, + CamlPlonkDomain, CamlPlonkVerificationEvals, CamlPlonkVerifierIndex, + }, + projective::{pallas::*, vesta::*}, + srs::{fp::*, fq::*}, + CamlCircuitGate, + CamlLookupCommitments, + CamlOpeningProof, + CamlPolyComm, + CamlProofEvaluations, + CamlProofWithPublic, + CamlProverCommitments, + CamlProverProof, + CamlRandomOracles, + CamlScalarChallenge, + CamlWire, + CurrOrNext, + GateType, +}; +use ocaml_gen::{decl_fake_generic, decl_func, decl_module, decl_type, decl_type_alias, Env}; +use std::{fs::File, io::Write}; + +fn main() { + let args: Vec = std::env::args().collect(); + + let env = &mut Env::default(); + + let header = "(* This file is generated automatically with ocaml_gen. *)\n"; + + if let Some(kimchi_types) = args.get(1) { + let mut file = File::create(kimchi_types).expect("could not create output file"); + write!(file, "{}", header).unwrap(); + let _ = env.new_module("Kimchi_types"); + generate_types_bindings(&mut file, env); + let _ = env.parent(); + } else { + let mut w = std::io::stdout(); + write!(w, "{}", header).unwrap(); + decl_module!(w, env, "Kimchi_types", { + generate_types_bindings(&mut w, env); + }); + }; + if let Some(pasta_bindings) = args.get(2) { + let mut file = File::create(pasta_bindings).expect("could not create output file"); + write!(file, "{}", header).unwrap(); + let _ = env.new_module("Pasta_bindings"); + generate_pasta_bindings(&mut file, env); + let _ = env.parent(); + } else { + let mut w = std::io::stdout(); + write!(w, "{}", header).unwrap(); + decl_module!(w, env, "Pasta_bindings", { + generate_pasta_bindings(&mut w, env); + }); + } + if let Some(kimchi_bindings) = args.get(3) { + let mut file = File::create(kimchi_bindings).expect("could not create output file"); + write!(file, "{}", header).unwrap(); + let _ = env.new_module("Kimchi_bindings"); + generate_kimchi_bindings(&mut file, env); + let _ = env.parent(); + } else { + let mut w = std::io::stdout(); + write!(w, "{}", header).unwrap(); + decl_module!(w, env, "Kimchi_bindings", { + generate_kimchi_bindings(&mut w, env); + }); + } +} + +fn generate_types_bindings(mut w: impl std::io::Write, env: &mut Env) { + decl_fake_generic!(T1, 0); + decl_fake_generic!(T2, 1); + decl_fake_generic!(T3, 2); + + decl_type!(w, env, CamlGroupAffine => "or_infinity"); + decl_type!(w, env, CamlScalarChallenge:: => "scalar_challenge"); + decl_type!(w, env, CamlRandomOracles:: => "random_oracles"); + decl_type!(w, env, PointEvaluations:: => "point_evaluations"); + decl_type!(w, env, CamlProofEvaluations:: => "proof_evaluations"); + decl_type!(w, env, CamlPolyComm:: => "poly_comm"); + decl_type!(w, env, CamlRecursionChallenge:: => "recursion_challenge"); + decl_type!(w, env, CamlOpeningProof:: => "opening_proof"); + decl_type!(w, env, CamlLookupCommitments:: => "lookup_commitments"); + + decl_type!(w, env, CamlRuntimeTableCfg:: => "runtime_table_cfg"); + decl_type!(w, env, CamlLookupTable:: => "lookup_table"); + decl_type!(w, env, CamlRuntimeTable:: => "runtime_table"); + decl_type!(w, env, CamlProverCommitments:: => "prover_commitments"); + decl_type!(w, env, CamlProverProof => "prover_proof"); + decl_type!(w, env, CamlProofWithPublic => "proof_with_public"); + + decl_type!(w, env, CamlWire => "wire"); + decl_type!(w, env, GateType => "gate_type"); + decl_type!(w, env, LookupPattern => "lookup_pattern"); + decl_type!(w, env, LookupPatterns => "lookup_patterns"); + decl_type!(w, env, LookupFeatures => "lookup_features"); + decl_type!(w, env, FeatureFlag => "feature_flag"); + decl_type!(w, env, CamlCircuitGate => "circuit_gate"); + + decl_type!(w, env, CurrOrNext => "curr_or_next"); + + decl_type!(w, env, CamlOracles => "oracles"); + decl_module!(w, env, "VerifierIndex", { + decl_module!(w, env, "Lookup", { + decl_type!(w, env, CamlLookupsUsed => "lookups_used"); + decl_type!(w, env, CamlLookupInfo => "lookup_info"); + decl_type!(w, env, CamlLookupSelectors => "lookup_selectors"); + decl_type!(w, env, CamlLookupVerifierIndex => "t"); + }); + decl_type!(w, env, CamlPlonkDomain => "domain"); + decl_type!(w, env, CamlPlonkVerificationEvals => "verification_evals"); + decl_type!(w, env, CamlPlonkVerifierIndex => "verifier_index"); + }); +} + +fn generate_pasta_bindings(mut w: impl std::io::Write, env: &mut Env) { + decl_fake_generic!(T1, 0); + decl_fake_generic!(T2, 1); + decl_fake_generic!(T3, 2); + + decl_module!(w, env, "BigInt256", { + decl_type!(w, env, CamlBigInteger256 => "t"); + + decl_func!(w, env, caml_bigint_256_of_numeral => "of_numeral"); + decl_func!(w, env, caml_bigint_256_of_decimal_string => "of_decimal_string"); + decl_func!(w, env, caml_bigint_256_num_limbs => "num_limbs"); + decl_func!(w, env, caml_bigint_256_bytes_per_limb => "bytes_per_limb"); + decl_func!(w, env, caml_bigint_256_div => "div"); + decl_func!(w, env, caml_bigint_256_compare => "compare"); + decl_func!(w, env, caml_bigint_256_print => "print"); + decl_func!(w, env, caml_bigint_256_to_string => "to_string"); + decl_func!(w, env, caml_bigint_256_test_bit => "test_bit"); + decl_func!(w, env, caml_bigint_256_to_bytes => "to_bytes"); + decl_func!(w, env, caml_bigint_256_of_bytes => "of_bytes"); + decl_func!(w, env, caml_bigint_256_deep_copy => "deep_copy"); + }); + + decl_module!(w, env, "Fp", { + decl_type!(w, env, CamlFp => "t"); + + decl_func!(w, env, caml_pasta_fp_size_in_bits => "size_in_bits"); + decl_func!(w, env, caml_pasta_fp_size => "size"); + decl_func!(w, env, caml_pasta_fp_add => "add"); + decl_func!(w, env, caml_pasta_fp_sub => "sub"); + decl_func!(w, env, caml_pasta_fp_negate => "negate"); + decl_func!(w, env, caml_pasta_fp_mul => "mul"); + decl_func!(w, env, caml_pasta_fp_div => "div"); + decl_func!(w, env, caml_pasta_fp_inv => "inv"); + decl_func!(w, env, caml_pasta_fp_square => "square"); + decl_func!(w, env, caml_pasta_fp_is_square => "is_square"); + decl_func!(w, env, caml_pasta_fp_sqrt => "sqrt"); + decl_func!(w, env, caml_pasta_fp_of_int => "of_int"); + decl_func!(w, env, caml_pasta_fp_to_string => "to_string"); + decl_func!(w, env, caml_pasta_fp_of_string => "of_string"); + decl_func!(w, env, caml_pasta_fp_print => "print"); + decl_func!(w, env, caml_pasta_fp_print_rust => "print_rust"); + decl_func!(w, env, caml_pasta_fp_copy => "copy"); + decl_func!(w, env, caml_pasta_fp_mut_add => "mut_add"); + decl_func!(w, env, caml_pasta_fp_mut_sub => "mut_sub"); + decl_func!(w, env, caml_pasta_fp_mut_mul => "mut_mul"); + decl_func!(w, env, caml_pasta_fp_mut_square => "mut_square"); + decl_func!(w, env, caml_pasta_fp_compare => "compare"); + decl_func!(w, env, caml_pasta_fp_equal => "equal"); + decl_func!(w, env, caml_pasta_fp_random => "random"); + decl_func!(w, env, caml_pasta_fp_rng => "rng"); + decl_func!(w, env, caml_pasta_fp_to_bigint => "to_bigint"); + decl_func!(w, env, caml_pasta_fp_of_bigint => "of_bigint"); + decl_func!(w, env, caml_pasta_fp_two_adic_root_of_unity => "two_adic_root_of_unity"); + decl_func!(w, env, caml_pasta_fp_domain_generator => "domain_generator"); + decl_func!(w, env, caml_pasta_fp_to_bytes => "to_bytes"); + decl_func!(w, env, caml_pasta_fp_of_bytes => "of_bytes"); + decl_func!(w, env, caml_pasta_fp_deep_copy => "deep_copy"); + }); + + decl_module!(w, env, "Fq", { + decl_type!(w, env, CamlFq => "t"); + + decl_func!(w, env, caml_pasta_fq_size_in_bits => "size_in_bits"); + decl_func!(w, env, caml_pasta_fq_size => "size"); + decl_func!(w, env, caml_pasta_fq_add => "add"); + decl_func!(w, env, caml_pasta_fq_sub => "sub"); + decl_func!(w, env, caml_pasta_fq_negate => "negate"); + decl_func!(w, env, caml_pasta_fq_mul => "mul"); + decl_func!(w, env, caml_pasta_fq_div => "div"); + decl_func!(w, env, caml_pasta_fq_inv => "inv"); + decl_func!(w, env, caml_pasta_fq_square => "square"); + decl_func!(w, env, caml_pasta_fq_is_square => "is_square"); + decl_func!(w, env, caml_pasta_fq_sqrt => "sqrt"); + decl_func!(w, env, caml_pasta_fq_of_int => "of_int"); + decl_func!(w, env, caml_pasta_fq_to_string => "to_string"); + decl_func!(w, env, caml_pasta_fq_of_string => "of_string"); + decl_func!(w, env, caml_pasta_fq_print => "print"); + decl_func!(w, env, caml_pasta_fq_print_rust => "print_rust"); + decl_func!(w, env, caml_pasta_fq_copy => "copy"); + decl_func!(w, env, caml_pasta_fq_mut_add => "mut_add"); + decl_func!(w, env, caml_pasta_fq_mut_sub => "mut_sub"); + decl_func!(w, env, caml_pasta_fq_mut_mul => "mut_mul"); + decl_func!(w, env, caml_pasta_fq_mut_square => "mut_square"); + decl_func!(w, env, caml_pasta_fq_compare => "compare"); + decl_func!(w, env, caml_pasta_fq_equal => "equal"); + decl_func!(w, env, caml_pasta_fq_random => "random"); + decl_func!(w, env, caml_pasta_fq_rng => "rng"); + decl_func!(w, env, caml_pasta_fq_to_bigint => "to_bigint"); + decl_func!(w, env, caml_pasta_fq_of_bigint => "of_bigint"); + decl_func!(w, env, caml_pasta_fq_two_adic_root_of_unity => "two_adic_root_of_unity"); + decl_func!(w, env, caml_pasta_fq_domain_generator => "domain_generator"); + decl_func!(w, env, caml_pasta_fq_to_bytes => "to_bytes"); + decl_func!(w, env, caml_pasta_fq_of_bytes => "of_bytes"); + decl_func!(w, env, caml_pasta_fq_deep_copy => "deep_copy"); + }); + + decl_module!(w, env, "Vesta", { + decl_module!(w, env, "BaseField", { + decl_type_alias!(w, env, "t" => CamlFq); + }); + + decl_module!(w, env, "ScalarField", { + decl_type_alias!(w, env, "t" => CamlFp); + }); + + decl_module!(w, env, "Affine", { + decl_type_alias!(w, env, "t" => CamlGroupAffine); + }); + + decl_type!(w, env, CamlGroupProjectiveVesta => "t"); + + decl_func!(w, env, caml_vesta_one => "one"); + decl_func!(w, env, caml_vesta_add => "add"); + decl_func!(w, env, caml_vesta_sub => "sub"); + decl_func!(w, env, caml_vesta_negate => "negate"); + decl_func!(w, env, caml_vesta_double => "double"); + decl_func!(w, env, caml_vesta_scale => "scale"); + decl_func!(w, env, caml_vesta_random => "random"); + decl_func!(w, env, caml_vesta_rng => "rng"); + decl_func!(w, env, caml_vesta_endo_base => "endo_base"); + decl_func!(w, env, caml_vesta_endo_scalar => "endo_scalar"); + decl_func!(w, env, caml_vesta_to_affine => "to_affine"); + decl_func!(w, env, caml_vesta_of_affine => "of_affine"); + decl_func!(w, env, caml_vesta_of_affine_coordinates => "of_affine_coordinates"); + decl_func!(w, env, caml_vesta_affine_deep_copy => "deep_copy"); + }); + + decl_module!(w, env, "Pallas", { + decl_module!(w, env, "BaseField", { + decl_type_alias!(w, env, "t" => CamlFp); + }); + + decl_module!(w, env, "ScalarField", { + decl_type_alias!(w, env, "t" => CamlFq); + }); + + decl_module!(w, env, "Affine", { + decl_type_alias!(w, env, "t" => CamlGroupAffine); + }); + + decl_type!(w, env, CamlGroupProjectivePallas => "t"); + + decl_func!(w, env, caml_pallas_one => "one"); + decl_func!(w, env, caml_pallas_add => "add"); + decl_func!(w, env, caml_pallas_sub => "sub"); + decl_func!(w, env, caml_pallas_negate => "negate"); + decl_func!(w, env, caml_pallas_double => "double"); + decl_func!(w, env, caml_pallas_scale => "scale"); + decl_func!(w, env, caml_pallas_random => "random"); + decl_func!(w, env, caml_pallas_rng => "rng"); + decl_func!(w, env, caml_pallas_endo_base => "endo_base"); + decl_func!(w, env, caml_pallas_endo_scalar => "endo_scalar"); + decl_func!(w, env, caml_pallas_to_affine => "to_affine"); + decl_func!(w, env, caml_pallas_of_affine => "of_affine"); + decl_func!(w, env, caml_pallas_of_affine_coordinates => "of_affine_coordinates"); + decl_func!(w, env, caml_pallas_affine_deep_copy => "deep_copy"); + }); +} + +fn generate_kimchi_bindings(mut w: impl std::io::Write, env: &mut Env) { + decl_module!(w, env, "FieldVectors", { + decl_module!(w, env, "Fp", { + decl_type!(w, env, CamlFpVector => "t"); + decl_type_alias!(w, env, "elt" => CamlFp); + + decl_func!(w, env, caml_fp_vector_create => "create"); + decl_func!(w, env, caml_fp_vector_length => "length"); + decl_func!(w, env, caml_fp_vector_emplace_back => "emplace_back"); + decl_func!(w, env, caml_fp_vector_get => "get"); + decl_func!(w, env, caml_fp_vector_set => "set"); + }); + + decl_module!(w, env, "Fq", { + decl_type!(w, env, CamlFqVector => "t"); + decl_type_alias!(w, env, "elt" => CamlFq); + + decl_func!(w, env, caml_fq_vector_create => "create"); + decl_func!(w, env, caml_fq_vector_length => "length"); + decl_func!(w, env, caml_fq_vector_emplace_back => "emplace_back"); + decl_func!(w, env, caml_fq_vector_get => "get"); + decl_func!(w, env, caml_fq_vector_set => "set"); + }); + }); + + decl_module!(w, env, "Protocol", { + decl_module!(w, env, "Gates", { + decl_module!(w, env, "Vector", { + decl_module!(w, env, "Fp", { + decl_type!(w, env, CamlPastaFpPlonkGateVector => "t"); + decl_type_alias!(w, env, "elt" => CamlCircuitGate); + + decl_func!(w, env, caml_pasta_fp_plonk_gate_vector_create => "create"); + decl_func!(w, env, caml_pasta_fp_plonk_gate_vector_add => "add"); + decl_func!(w, env, caml_pasta_fp_plonk_gate_vector_get => "get"); + decl_func!(w, env, caml_pasta_fp_plonk_gate_vector_len => "len"); + decl_func!(w, env, caml_pasta_fp_plonk_gate_vector_wrap => "wrap"); + decl_func!(w, env, caml_pasta_fp_plonk_gate_vector_digest => "digest"); + decl_func!(w, env, caml_pasta_fp_plonk_circuit_serialize => "to_json"); + }); + decl_module!(w, env, "Fq", { + decl_type!(w, env, CamlPastaFqPlonkGateVector => "t"); + decl_type_alias!(w, env, "elt" => CamlCircuitGate); + + decl_func!(w, env, caml_pasta_fq_plonk_gate_vector_create => "create"); + decl_func!(w, env, caml_pasta_fq_plonk_gate_vector_add => "add"); + decl_func!(w, env, caml_pasta_fq_plonk_gate_vector_get => "get"); + decl_func!(w, env, caml_pasta_fq_plonk_gate_vector_len => "len"); + decl_func!(w, env, caml_pasta_fq_plonk_gate_vector_wrap => "wrap"); + decl_func!(w, env, caml_pasta_fq_plonk_gate_vector_digest => "digest"); + decl_func!(w, env, caml_pasta_fq_plonk_circuit_serialize => "to_json"); + }); + }); + }); + + decl_module!(w, env, "SRS", { + decl_module!(w, env, "Fp", { + decl_type!(w, env, CamlFpSrs => "t"); + + decl_module!(w, env, "Poly_comm", { + decl_type_alias!(w, env, "t" => CamlPolyComm>); + }); + + decl_func!(w, env, caml_fp_srs_create => "create"); + decl_func!(w, env, caml_fp_srs_write => "write"); + decl_func!(w, env, caml_fp_srs_read => "read"); + decl_func!(w, env, caml_fp_srs_lagrange_commitment => "lagrange_commitment"); + decl_func!(w, env, caml_fp_srs_lagrange_commitments_whole_domain => "lagrange_commitments_whole_domain"); + decl_func!(w, env, caml_fp_srs_add_lagrange_basis=> "add_lagrange_basis"); + decl_func!(w, env, caml_fp_srs_commit_evaluations => "commit_evaluations"); + decl_func!(w, env, caml_fp_srs_b_poly_commitment => "b_poly_commitment"); + decl_func!(w, env, caml_fp_srs_batch_accumulator_check => "batch_accumulator_check"); + decl_func!(w, env, caml_fp_srs_batch_accumulator_generate => "batch_accumulator_generate"); + decl_func!(w, env, caml_fp_srs_h => "urs_h"); + }); + + decl_module!(w, env, "Fq", { + decl_type!(w, env, CamlFqSrs => "t"); + + decl_func!(w, env, caml_fq_srs_create => "create"); + decl_func!(w, env, caml_fq_srs_write => "write"); + decl_func!(w, env, caml_fq_srs_read => "read"); + decl_func!(w, env, caml_fq_srs_lagrange_commitment => "lagrange_commitment"); + decl_func!(w, env, caml_fq_srs_lagrange_commitments_whole_domain => "lagrange_commitments_whole_domain"); + decl_func!(w, env, caml_fq_srs_add_lagrange_basis=> "add_lagrange_basis"); + decl_func!(w, env, caml_fq_srs_commit_evaluations => "commit_evaluations"); + decl_func!(w, env, caml_fq_srs_b_poly_commitment => "b_poly_commitment"); + decl_func!(w, env, caml_fq_srs_batch_accumulator_check => "batch_accumulator_check"); + decl_func!(w, env, caml_fq_srs_batch_accumulator_generate => "batch_accumulator_generate"); + decl_func!(w, env, caml_fq_srs_h => "urs_h"); + }); + }); + + decl_module!(w, env, "Index", { + decl_module!(w, env, "Fp", { + decl_type!(w, env, CamlPastaFpPlonkIndex => "t"); + + decl_func!(w, env, caml_pasta_fp_plonk_index_create => "create"); + decl_func!(w, env, caml_pasta_fp_plonk_index_max_degree => "max_degree"); + decl_func!(w, env, caml_pasta_fp_plonk_index_public_inputs => "public_inputs"); + decl_func!(w, env, caml_pasta_fp_plonk_index_domain_d1_size => "domain_d1_size"); + decl_func!(w, env, caml_pasta_fp_plonk_index_domain_d4_size => "domain_d4_size"); + decl_func!(w, env, caml_pasta_fp_plonk_index_domain_d8_size => "domain_d8_size"); + decl_func!(w, env, caml_pasta_fp_plonk_index_read => "read"); + decl_func!(w, env, caml_pasta_fp_plonk_index_write => "write"); + }); + + decl_module!(w, env, "Fq", { + decl_type!(w, env, CamlPastaFqPlonkIndex => "t"); + + decl_func!(w, env, caml_pasta_fq_plonk_index_create => "create"); + decl_func!(w, env, caml_pasta_fq_plonk_index_max_degree => "max_degree"); + decl_func!(w, env, caml_pasta_fq_plonk_index_public_inputs => "public_inputs"); + decl_func!(w, env, caml_pasta_fq_plonk_index_domain_d1_size => "domain_d1_size"); + decl_func!(w, env, caml_pasta_fq_plonk_index_domain_d4_size => "domain_d4_size"); + decl_func!(w, env, caml_pasta_fq_plonk_index_domain_d8_size => "domain_d8_size"); + decl_func!(w, env, caml_pasta_fq_plonk_index_read => "read"); + decl_func!(w, env, caml_pasta_fq_plonk_index_write => "write"); + }); + }); + + decl_module!(w, env, "VerifierIndex", { + decl_module!(w, env, "Fp", { + decl_type_alias!(w, env, "t" => CamlPlonkVerifierIndex>); + + decl_func!(w, env, caml_pasta_fp_plonk_verifier_index_create => "create"); + decl_func!(w, env, caml_pasta_fp_plonk_verifier_index_read => "read"); + decl_func!(w, env, caml_pasta_fp_plonk_verifier_index_write => "write"); + decl_func!(w, env, caml_pasta_fp_plonk_verifier_index_shifts => "shifts"); + decl_func!(w, env, caml_pasta_fp_plonk_verifier_index_dummy => "dummy"); + decl_func!(w, env, caml_pasta_fp_plonk_verifier_index_deep_copy => "deep_copy"); + }); + + decl_module!(w, env, "Fq", { + decl_type_alias!(w, env, "t" => CamlPlonkVerifierIndex>); + + decl_func!(w, env, caml_pasta_fq_plonk_verifier_index_create => "create"); + decl_func!(w, env, caml_pasta_fq_plonk_verifier_index_read => "read"); + decl_func!(w, env, caml_pasta_fq_plonk_verifier_index_write => "write"); + decl_func!(w, env, caml_pasta_fq_plonk_verifier_index_shifts => "shifts"); + decl_func!(w, env, caml_pasta_fq_plonk_verifier_index_dummy => "dummy"); + decl_func!(w, env, caml_pasta_fq_plonk_verifier_index_deep_copy => "deep_copy"); + }); + }); + + decl_module!(w, env, "Oracles", { + decl_module!(w, env, "Fp", { + decl_type_alias!(w, env, "t" => CamlOracles); + + decl_func!(w, env, fp_oracles_create_no_public => "create"); + decl_func!(w, env, fp_oracles_create => "create_with_public_evals"); + decl_func!(w, env, fp_oracles_dummy => "dummy"); + decl_func!(w, env, fp_oracles_deep_copy => "deep_copy"); + }); + + decl_module!(w, env, "Fq", { + decl_type_alias!(w, env, "t" => CamlOracles); + + decl_func!(w, env, fq_oracles_create_no_public => "create"); + decl_func!(w, env, fq_oracles_create => "create_with_public_evals"); + decl_func!(w, env, fq_oracles_dummy => "dummy"); + decl_func!(w, env, fq_oracles_deep_copy => "deep_copy"); + }); + }); + + decl_module!(w, env, "Proof", { + decl_module!(w, env, "Fp", { + decl_func!(w, env, caml_pasta_fp_plonk_proof_create => "create"); + decl_func!(w, env, caml_pasta_fp_plonk_proof_create_and_verify => "create_and_verify"); + decl_func!(w, env, caml_pasta_fp_plonk_proof_example_with_lookup => "example_with_lookup"); + decl_func!(w, env, caml_pasta_fp_plonk_proof_example_with_ffadd => "example_with_ffadd"); + decl_func!(w, env, caml_pasta_fp_plonk_proof_example_with_xor => "example_with_xor"); + decl_func!(w, env, caml_pasta_fp_plonk_proof_example_with_rot => "example_with_rot"); + decl_func!(w, env, caml_pasta_fp_plonk_proof_example_with_foreign_field_mul => "example_with_foreign_field_mul"); + decl_func!(w, env, caml_pasta_fp_plonk_proof_example_with_range_check => "example_with_range_check"); + decl_func!(w, env, caml_pasta_fp_plonk_proof_example_with_range_check0 => "example_with_range_check0"); + decl_func!(w, env, caml_pasta_fp_plonk_proof_verify => "verify"); + decl_func!(w, env, caml_pasta_fp_plonk_proof_batch_verify => "batch_verify"); + decl_func!(w, env, caml_pasta_fp_plonk_proof_dummy => "dummy"); + decl_func!(w, env, caml_pasta_fp_plonk_proof_deep_copy => "deep_copy"); + }); + + decl_module!(w, env, "Fq", { + decl_func!(w, env, caml_pasta_fq_plonk_proof_create => "create"); + decl_func!(w, env, caml_pasta_fq_plonk_proof_verify => "verify"); + decl_func!(w, env, caml_pasta_fq_plonk_proof_batch_verify => "batch_verify"); + decl_func!(w, env, caml_pasta_fq_plonk_proof_dummy => "dummy"); + decl_func!(w, env, caml_pasta_fq_plonk_proof_deep_copy => "deep_copy"); + }); + }); + }); +} diff --git a/kimchi_bindings.opam b/kimchi_bindings.opam new file mode 100644 index 0000000000..652068a173 --- /dev/null +++ b/kimchi_bindings.opam @@ -0,0 +1,28 @@ +# This file is generated by dune, edit dune-project instead +opam-version: "2.0" +synopsis: "OCaml bindings to Kimchi" +maintainer: ["O(1) Labs, LLC "] +authors: ["O(1) Labs, LLC "] +license: "Apache-2.0" +homepage: "https://github.com/o1-labs/proof-systems/" +bug-reports: "https://github.com/o1-labs/proof-systems/issues" +depends: [ + "dune" {>= "3.0" & >= "3.0"} + "conf-rust" {>= "0.1"} + "odoc" {with-doc} +] +build: [ + ["dune" "subst"] {dev} + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] +] +dev-repo: "git+https://github.com/o1-labs/profo-systems.git" diff --git a/kimchi_types.opam b/kimchi_types.opam new file mode 100644 index 0000000000..8dec665c72 --- /dev/null +++ b/kimchi_types.opam @@ -0,0 +1,28 @@ +# This file is generated by dune, edit dune-project instead +opam-version: "2.0" +synopsis: "OCaml bindings to types defined in Kimchi" +maintainer: ["O(1) Labs, LLC "] +authors: ["O(1) Labs, LLC "] +license: "Apache-2.0" +homepage: "https://github.com/o1-labs/proof-systems/" +bug-reports: "https://github.com/o1-labs/proof-systems/issues" +depends: [ + "dune" {>= "3.0" & >= "3.0"} + "conf-rust" {>= "0.1"} + "odoc" {with-doc} +] +build: [ + ["dune" "subst"] {dev} + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] +] +dev-repo: "git+https://github.com/o1-labs/profo-systems.git" diff --git a/pasta_bindings.opam b/pasta_bindings.opam new file mode 100644 index 0000000000..fde0a68654 --- /dev/null +++ b/pasta_bindings.opam @@ -0,0 +1,28 @@ +# This file is generated by dune, edit dune-project instead +opam-version: "2.0" +synopsis: "OCaml bindings to the Pasta curves" +maintainer: ["O(1) Labs, LLC "] +authors: ["O(1) Labs, LLC "] +license: "Apache-2.0" +homepage: "https://github.com/o1-labs/proof-systems/" +bug-reports: "https://github.com/o1-labs/proof-systems/issues" +depends: [ + "dune" {>= "3.0" & >= "3.0"} + "conf-rust" {>= "0.1"} + "odoc" {with-doc} +] +build: [ + ["dune" "subst"] {dev} + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] +] +dev-repo: "git+https://github.com/o1-labs/profo-systems.git" diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 8f82b23698..ea1408d2b1 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -7,4 +7,5 @@ publish = false [dependencies] anyhow = "1.0" clap = { version = "4.4.6", features = ["derive"] } +raw-cpuid = "11" wasm-pack = "=0.12.1" diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 875da2b513..228bd9f944 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,5 +1,6 @@ use anyhow::{Context, Result}; use clap::{Parser, Subcommand, ValueEnum}; +use raw_cpuid::CpuId; use std::{ env, ffi::OsString, @@ -31,6 +32,16 @@ enum Commands { #[arg(long)] rust_version: Option, }, + + /// Build kimchi-stubs with optional CPU optimisations + BuildKimchiStubs { + /// Target directory for cargo build artifacts + #[arg(long)] + target_dir: Option, + + #[arg(long, short, action, default_value_t = false)] + offline: bool, + }, } #[derive(Copy, Clone, PartialEq, Eq, ValueEnum)] @@ -59,11 +70,83 @@ fn main() -> Result<()> { target, rust_version, } => build_wasm(out_dir, *target, rust_version.as_deref()), + Commands::BuildKimchiStubs { + target_dir, + offline, + } => build_kimchi_stubs(target_dir.as_deref(), *offline), } } type RustVersion<'a> = Option<&'a str>; +fn build_kimchi_stubs(target_dir: Option<&str>, offline: bool) -> Result<()> { + // Optimisations are enabled by default, but can be disabled by setting the + // `RUST_TARGET_FEATURE_OPTIMISATIONS` environment variable to any other + // value than "y". + let optimisations_enabled = env::var("RUST_TARGET_FEATURE_OPTIMISATIONS") + .map(|v| ["y", "1", "true"].contains(&v.to_lowercase().as_str())) + .unwrap_or(true); + + let cpu_supports_adx_bmi2 = { + let cpuid = CpuId::new(); + cpuid + .get_extended_feature_info() + .map_or(false, |f| f.has_adx() && f.has_bmi2()) + }; + + // If optimisations are enabled and the CPU supports ADX and BMI2, we enable + // those features. + let rustflags = match (optimisations_enabled, cpu_supports_adx_bmi2) { + (true, true) => { + // If optimisations are enabled and the CPU supports ADX and BMI2, + // we enable them. + Some("-C target-feature=+bmi2,+adx".to_string()) + } + (false, true) => { + // If optimisations are disabled but the CPU supports ADX and BMI2, + // we explicitly disable them. + Some("-C target-feature=-bmi2,-adx".to_string()) + } + (true, false) => { + // If the CPU does not support ADX and BMI2, we do not set any + // target features. It could be handled in the `else` branch, but we + // want to be explicit. If the CPU does not support these features, but + // we still add the -bmi2 and -adx flags, it will cause a build warning + // we want to avoid on the user console. + None + } + (false, false) => None, + }; + + let target_dir = target_dir.unwrap_or("target/kimchi_stubs_build"); + + let mut cmd = Command::new("cargo"); + cmd.args(&[ + "build", + "--release", + "-p", + "kimchi-stubs", + "--target-dir", + target_dir, + ]); + + if offline { + cmd.arg("--offline"); + } + + if let Some(rustflags) = rustflags { + cmd.env("RUSTFLAGS", rustflags); + } + + let status = cmd.status().context("Failed to build kimchi-stubs")?; + + if !status.success() { + anyhow::bail!("kimchi-stubs build failed"); + } + + Ok(()) +} + fn build_wasm(out_dir: &str, target: Target, rust_version: RustVersion) -> Result<()> { const RUSTFLAGS: &str = "-C target-feature=+atomics,+bulk-memory,+mutable-globals -C link-arg=--max-memory=4294967296";