diff --git a/.github/workflows/ci-llzk.yml b/.github/workflows/ci-llzk.yml new file mode 100644 index 000000000..151fb4fa5 --- /dev/null +++ b/.github/workflows/ci-llzk.yml @@ -0,0 +1,31 @@ +name: CI (circom-to-llzk) +on: + push: + branches: [ llzk ] + pull_request: + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - uses: cachix/install-nix-action@9280e7aca88deada44c930f1e2c78e21c3ae3edd # v31.7.0 + with: + install_url: https://releases.nixos.org/nix/nix-2.31.2/install + github_access_token: "${{ secrets.GITHUB_TOKEN }}" + - name: Set Git credentials + run: | + git config --global 'url.https://api@github.com/'.insteadOf 'https://github.com/' + git config --global 'url.https://ssh@github.com/'.insteadOf 'ssh://git@github.com/' + git config --global 'url.https://git@github.com/'.insteadOf 'git@github.com:' + - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 + with: + name: veridise-public + authToken: '${{ secrets.CACHIX_PUBLIC_TOKEN }}' + - name: Build and test ${{ matrix.derivation }} + run: nix --print-build-logs build diff --git a/.gitignore b/.gitignore index b400bb37e..f9b59dc91 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,7 @@ type_analysis/target/ .idea/ .vscode/ .DS_Store + +# Nix package build +/result +/build-tools diff --git a/Cargo.lock b/Cargo.lock index bf95bb67d..7e51963e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,12 +1,12 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" -version = "0.7.18" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -20,6 +20,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + [[package]] name = "ascii-canvas" version = "3.0.0" @@ -29,6 +41,37 @@ dependencies = [ "term", ] +[[package]] +name = "assert_cmd" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd389a4b2970a01282ee455294913c0a43724daedcd1a24c3eb0ec1c1320b66" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "libc", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + +[[package]] +name = "assert_fs" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652f6cb1f516886fcfee5e7a5c078b9ade62cfcb889524efe5a64d682dd27a9" +dependencies = [ + "anstyle", + "doc-comment", + "globwalk", + "predicates", + "predicates-core", + "predicates-tree", + "tempfile", +] + [[package]] name = "atty" version = "0.2.14" @@ -46,6 +89,26 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bindgen" +version = "0.71.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" +dependencies = [ + "bitflags 2.9.4", + "cexpr", + "clang-sys", + "itertools", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.106", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -67,6 +130,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" + [[package]] name = "block-buffer" version = "0.10.2" @@ -76,17 +145,56 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bstr" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "caseless" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6fd507454086c8edfd769ca6ada439193cdb209c7681712ef6275cccbfe5d8" +dependencies = [ + "unicode-normalization", +] + [[package]] name = "cc" -version = "1.0.79" +version = "1.2.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] [[package]] name = "cfg-if" @@ -99,14 +207,24 @@ name = "circom" version = "2.2.2" dependencies = [ "ansi_term", + "anyhow", + "assert_cmd", + "assert_fs", "clap", "compiler", "constraint_generation", "constraint_writers", "dag", - "exitcode", + "glob", + "lazy_static", + "llzk", + "melior", + "melior-macro", + "mlir-sys", "parser", "program_structure", + "rand 0.9.2", + "regex", "type_analysis", "wast", ] @@ -120,6 +238,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "2.34.0" @@ -128,13 +257,22 @@ checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "ansi_term", "atty", - "bitflags", + "bitflags 1.3.2", "strsim", "textwrap", "unicode-width", "vec_map", ] +[[package]] +name = "cmake" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +dependencies = [ + "cc", +] + [[package]] name = "code_producers" version = "2.2.2" @@ -176,6 +314,20 @@ dependencies = [ "program_structure", ] +[[package]] +name = "comrak" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fefab951771fc3beeed0773ce66a4f7b706273fc6c4c95b08dd1615744abcf5" +dependencies = [ + "caseless", + "entities", + "memchr", + "slug", + "typed-arena", + "unicode_categories", +] + [[package]] name = "constant_tracking" version = "2.0.0" @@ -215,6 +367,15 @@ dependencies = [ "json", ] +[[package]] +name = "convert_case" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "cpufeatures" version = "0.2.2" @@ -224,6 +385,31 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "crunchy" version = "0.2.2" @@ -251,12 +437,24 @@ dependencies = [ "program_structure", ] +[[package]] +name = "deunicode" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04" + [[package]] name = "diff" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + [[package]] name = "digest" version = "0.10.3" @@ -288,6 +486,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "either" version = "1.7.0" @@ -303,32 +507,33 @@ dependencies = [ "log", ] +[[package]] +name = "entities" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" + [[package]] name = "errno" -version = "0.3.1" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ - "errno-dragonfly", "libc", - "windows-sys 0.48.0", + "windows-sys 0.61.0", ] [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "fastrand" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] -name = "exitcode" -version = "1.1.2" +name = "find-msvc-tools" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193" +checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" [[package]] name = "fixedbitset" @@ -354,7 +559,49 @@ checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.7+wasi-0.2.4", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "globset" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax 0.8.6", +] + +[[package]] +name = "globwalk" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" +dependencies = [ + "bitflags 2.9.4", + "ignore", + "walkdir", ] [[package]] @@ -368,7 +615,7 @@ dependencies = [ "pest_derive", "serde", "serde_json", - "thiserror", + "thiserror 1.0.31", ] [[package]] @@ -392,6 +639,22 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +[[package]] +name = "ignore" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata", + "same-file", + "walkdir", + "winapi-util", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -421,7 +684,7 @@ checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", - "rustix", + "rustix 0.37.19", "windows-sys 0.48.0", ] @@ -461,7 +724,7 @@ dependencies = [ "lalrpop-util", "petgraph", "regex", - "regex-syntax", + "regex-syntax 0.6.27", "string_cache", "term", "tiny-keccak", @@ -479,9 +742,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ "spin", ] @@ -494,9 +757,19 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.144" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] [[package]] name = "libm" @@ -510,6 +783,48 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "llzk" +version = "0.1.0" +source = "git+https://github.com/Veridise/llzk-rs#c6c769b4def0c714d7f09d356ea0d1ce8c966c3f" +dependencies = [ + "llzk-sys", + "log", + "melior", + "melior-macro", + "mlir-sys", + "paste", +] + +[[package]] +name = "llzk-sys" +version = "0.1.0" +source = "git+https://github.com/Veridise/llzk-rs#c6c769b4def0c714d7f09d356ea0d1ce8c966c3f" +dependencies = [ + "anyhow", + "llzk-sys-build-support", + "mlir-sys", +] + +[[package]] +name = "llzk-sys-build-support" +version = "0.1.0" +source = "git+https://github.com/Veridise/llzk-rs#c6c769b4def0c714d7f09d356ea0d1ce8c966c3f" +dependencies = [ + "anyhow", + "bindgen", + "cc", + "cmake", + "glob", + "tempfile", +] + [[package]] name = "lock_api" version = "0.4.9" @@ -522,12 +837,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "lz_fnv" @@ -535,11 +847,52 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bbb1b0dbe51f0976eaa466f4e0bdc11856fe8008aee26f30ccec8de15b28e38" +[[package]] +name = "melior" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "849459b46a3754be7d0d21b85a866a2a057c0e0a3b8096d8615d21e61e0479ab" +dependencies = [ + "melior-macro", + "mlir-sys", +] + +[[package]] +name = "melior-macro" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d62bfbdc193acc4ee577b027ef9be3a4f8c383bc4388e76f618d021f49ef4330" +dependencies = [ + "comrak", + "convert_case", + "proc-macro2", + "quote", + "regex", + "syn 2.0.106", + "tblgen", + "unindent", +] + [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "mlir-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9348dd263d2680d657635d9dd084cdcd785d7486a41332ffa4c926d5882b54" +dependencies = [ + "bindgen", +] [[package]] name = "new_debug_unreachable" @@ -547,6 +900,16 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num-bigint-dig" version = "0.8.4" @@ -559,7 +922,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand", + "rand 0.8.5", "serde", "smallvec", ] @@ -605,9 +968,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "parking_lot" @@ -647,13 +1010,19 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pest" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69486e2b8c2d2aeb9762db7b4e00b0331156393555cff467f4163ff06821eef8" dependencies = [ - "thiserror", + "thiserror 1.0.31", "ucd-trie", ] @@ -677,7 +1046,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] @@ -722,11 +1091,48 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "predicates" +version = "3.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" +dependencies = [ + "anstyle", + "difflib", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" + +[[package]] +name = "predicates-tree" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.106", +] + [[package]] name = "proc-macro2" -version = "1.0.42" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -747,13 +1153,19 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.20" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" version = "0.8.5" @@ -761,8 +1173,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -772,7 +1194,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -781,7 +1213,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.9", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", ] [[package]] @@ -790,7 +1231,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -799,20 +1240,32 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom", + "getrandom 0.2.9", "redox_syscall", - "thiserror", + "thiserror 1.0.31", ] [[package]] name = "regex" -version = "1.6.0" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax 0.8.6", +] + +[[package]] +name = "regex-automata" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.6", ] [[package]] @@ -821,6 +1274,18 @@ version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +[[package]] +name = "regex-syntax" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustc-hex" version = "2.1.0" @@ -833,14 +1298,27 @@ version = "0.37.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", - "linux-raw-sys", + "linux-raw-sys 0.3.7", "windows-sys 0.48.0", ] +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags 2.9.4", + "errno", + "libc", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.0", +] + [[package]] name = "rustversion" version = "1.0.12" @@ -853,6 +1331,15 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -873,7 +1360,7 @@ checksum = "75743a150d003dd863b51dc809bcad0d73f2102c53632f1e954e738192a3413f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] @@ -898,12 +1385,28 @@ dependencies = [ "digest", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "siphasher" version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +[[package]] +name = "slug" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "882a80f72ee45de3cc9a5afeb2da0331d58df69e4e7d8eeb5d3c7784ae67e724" +dependencies = [ + "deunicode", + "wasm-bindgen", +] + [[package]] name = "smallvec" version = "1.13.2" @@ -912,9 +1415,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "spin" -version = "0.5.2" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "string_cache" @@ -946,6 +1449,42 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tblgen" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836472eafcc544aa0167f880c0998d4a77b422d22100186e67fc6daf35cab94c" +dependencies = [ + "bindgen", + "cc", + "paste", + "thiserror 2.0.16", +] + +[[package]] +name = "tempfile" +version = "3.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84fa4d11fadde498443cca10fd3ac23c951f0dc59e080e9f4b93d4df4e4eea53" +dependencies = [ + "fastrand", + "getrandom 0.3.3", + "once_cell", + "rustix 1.1.2", + "windows-sys 0.61.0", +] + [[package]] name = "term" version = "0.7.0" @@ -966,6 +1505,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "termtree" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" + [[package]] name = "textwrap" version = "0.11.0" @@ -981,7 +1526,16 @@ version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.31", +] + +[[package]] +name = "thiserror" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +dependencies = [ + "thiserror-impl 2.0.16", ] [[package]] @@ -992,7 +1546,18 @@ checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", ] [[package]] @@ -1013,6 +1578,21 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "type_analysis" version = "2.2.2" @@ -1022,6 +1602,12 @@ dependencies = [ "program_structure", ] +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + [[package]] name = "typenum" version = "1.15.0" @@ -1040,6 +1626,21 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + [[package]] name = "unicode-width" version = "0.1.9" @@ -1052,6 +1653,18 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "unindent" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" + [[package]] name = "vec_map" version = "0.8.2" @@ -1064,12 +1677,103 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.106", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" + [[package]] name = "wast" version = "39.0.0" @@ -1112,6 +1816,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + [[package]] name = "windows-sys" version = "0.45.0" @@ -1130,6 +1840,15 @@ dependencies = [ "windows-targets 0.48.0", ] +[[package]] +name = "windows-sys" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -1243,3 +1962,9 @@ name = "windows_x86_64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" diff --git a/README.md b/README.md index 2d5f31b13..8aaabc6c6 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ Basic background on Zero-knowledge proofs can be found on [Background section](h # Install +Set path variables for the [LLZK dependency](https://github.com/Veridise/llzk-rs?tab=readme-ov-file#building-tips) Refer to [Installation section](https://docs.circom.io/getting-started/installation/) ## :warning: Deprecation note diff --git a/circom/Cargo.toml b/circom/Cargo.toml index 7fbd1ae28..ac6cf1db4 100644 --- a/circom/Cargo.toml +++ b/circom/Cargo.toml @@ -22,5 +22,19 @@ compiler = { path = "../compiler" } dag = { path = "../dag" } clap = "2.33.0" ansi_term = "0.12.1" +anyhow = "1" wast = "39.0.0" -exitcode = "1.1.2" +mlir-sys = "0.5.0" +melior = "0.25.0" +melior-macro = "0.18.0" +llzk = { git = "https://github.com/Veridise/llzk-rs", package = "llzk" } + +[dev-dependencies] +assert_cmd = "2.0" +assert_fs = "1.1" +regex = "1.11" +lazy_static = "1.5" +rand = "0.9" + +[build-dependencies] +glob = "0.3.3" diff --git a/circom/build.rs b/circom/build.rs new file mode 100644 index 000000000..04c33b603 --- /dev/null +++ b/circom/build.rs @@ -0,0 +1,50 @@ +use std::env; +use std::fs::File; +use std::path::Path; +use std::io::Write; +use std::fs::{copy, create_dir_all}; +use glob::glob; + +/// Generates the file `discovered_tests.in` in the output directory, containing +/// test functions for each `.circom` file found in the `tests/` directory. +/// Each test function is named based on the file path, with slashes replaced +/// by underscores, and is set up to call `lit_test` with the file's contents. +fn main() { + let out_dir = env::var("OUT_DIR").unwrap(); + let dest_path = Path::new(&out_dir).join("discovered_tests.in"); + let mut test_code = "".to_string(); + + for entry in glob("tests/**/*.circom").expect("Failed to read glob pattern") { + let path = entry.unwrap(); + create_dir_all(Path::new(&out_dir).join(path.parent().unwrap())).unwrap(); + copy(path.clone(), Path::new(&out_dir).join(path.clone())).unwrap(); + let test_name = path + .to_str() + .unwrap() + .replace('/', "_") + .replace(".circom", "") + .replace('-', "_") + .to_lowercase(); + + test_code = format!( + " + {} + + #[test] + fn {}() -> LitResult<()> {{ + lit_test(include_str!(\"{}\"), \"{}\") + }}", + test_code, + test_name, + path.to_str().unwrap(), + test_name + ); + } + + generate_file(dest_path, test_code.as_bytes()); +} + +fn generate_file>(path: P, text: &[u8]) { + let mut f = File::create(path).unwrap(); + f.write_all(text).unwrap() +} diff --git a/circom/src/input_user.rs b/circom/src/input_user.rs index f89d04c26..ec4afbfe7 100644 --- a/circom/src/input_user.rs +++ b/circom/src/input_user.rs @@ -2,9 +2,11 @@ use std::path::PathBuf; pub struct Input { pub input_program: PathBuf, + pub out_dump_parse: PathBuf, pub out_r1cs: PathBuf, pub out_json_constraints: PathBuf, pub out_json_substitutions: PathBuf, + pub out_llzk_code: PathBuf, pub out_wat_code: PathBuf, pub out_wasm_code: PathBuf, pub out_wasm_name: String, @@ -15,7 +17,9 @@ pub struct Input { pub out_c_dat: PathBuf, pub out_sym: PathBuf, //pub field: &'static str, + pub dump_parse_flag: bool, pub c_flag: bool, + pub llzk_flag: bool, pub wasm_flag: bool, pub wat_flag: bool, pub no_asm_flag: bool, @@ -43,6 +47,7 @@ const R1CS: &'static str = "r1cs"; const WAT: &'static str = "wat"; const WASM: &'static str = "wasm"; const CPP: &'static str = "cpp"; +const LLZK: &'static str = "llzk"; const JS: &'static str = "js"; const DAT: &'static str = "dat"; const SYM: &'static str = "sym"; @@ -65,12 +70,14 @@ impl Input { file_name = format!("{}_c", file_name) }; let output_c_path = Input::build_folder(&output_path, &file_name, CPP); + let output_llzk_path = Input::build_folder(&output_path, &file_name, LLZK); let output_js_path = Input::build_folder(&output_path, &file_name, JS); let o_style = input_processing::get_simplification_style(&matches)?; let link_libraries = input_processing::get_link_libraries(&matches); Result::Ok(Input { //field: P_BN128, input_program: input, + out_dump_parse: Input::build_output(&output_path, &file_name, "txt"), out_r1cs: Input::build_output(&output_path, &file_name, R1CS), out_wat_code: Input::build_output(&output_js_path, &file_name, WAT), out_wasm_code: Input::build_output(&output_js_path, &file_name, WASM), @@ -80,6 +87,7 @@ impl Input { out_c_run_name: file_name.clone(), out_c_code: Input::build_output(&output_c_path, &file_name, CPP), out_c_dat: Input::build_output(&output_c_path, &file_name, DAT), + out_llzk_code: Input::build_output(&output_llzk_path, &file_name, LLZK), out_sym: Input::build_output(&output_path, &file_name, SYM), out_json_constraints: Input::build_output( &output_path, @@ -91,9 +99,11 @@ impl Input { &format!("{}_substitutions", file_name), JSON, ), + dump_parse_flag: input_processing::get_dump_parse(&matches), wat_flag:input_processing::get_wat(&matches), wasm_flag: input_processing::get_wasm(&matches), c_flag: c_flag, + llzk_flag: input_processing::get_llzk(&matches), no_asm_flag:input_processing::get_no_asm(&matches), r1cs_flag: input_processing::get_r1cs(&matches), sym_flag: input_processing::get_sym(&matches), @@ -161,18 +171,27 @@ impl Input { self.out_c_run_name.clone() } + pub fn dump_parse_file(&self) -> &str { + self.out_dump_parse.to_str().unwrap() + } pub fn c_file(&self) -> &str { self.out_c_code.to_str().unwrap() } pub fn dat_file(&self) -> &str { self.out_c_dat.to_str().unwrap() } + pub fn llzk_file(&self) -> &str { + self.out_llzk_code.to_str().unwrap() + } pub fn json_constraints_file(&self) -> &str { self.out_json_constraints.to_str().unwrap() } pub fn json_substitutions_file(&self) -> &str { self.out_json_substitutions.to_str().unwrap() } + pub fn dump_parse_flag(&self) -> bool { + self.dump_parse_flag + } pub fn wasm_flag(&self) -> bool { self.wasm_flag } @@ -182,6 +201,9 @@ impl Input { pub fn c_flag(&self) -> bool { self.c_flag } + pub fn llzk_flag(&self) -> bool { + self.llzk_flag + } pub fn no_asm_flag(&self) -> bool { self.no_asm_flag } @@ -311,10 +333,18 @@ mod input_processing { matches.is_present("no_asm") } + pub fn get_dump_parse(matches: &ArgMatches) -> bool { + matches.is_present("print_dump_parse") + } + pub fn get_c(matches: &ArgMatches) -> bool { matches.is_present("print_c") } + pub fn get_llzk(matches: &ArgMatches) -> bool { + matches.is_present("print_llzk_ir") + } + pub fn get_main_inputs_log(matches: &ArgMatches) -> bool { matches.is_present("main_inputs_log") } @@ -496,6 +526,13 @@ mod input_processing { .display_order(330) .help("Adds directory to library search path"), ) + .arg( + Arg::with_name("print_dump_parse") + .long("dump_parse") + .takes_value(false) + .display_order(89) + .help("Parses the circuit and dumps the program archive"), + ) .arg( Arg::with_name("print_c") .long("c") @@ -504,6 +541,13 @@ mod input_processing { .display_order(150) .help("Compiles the circuit to C++"), ) + .arg( + Arg::with_name("print_llzk_ir") + .long("llzk") + .takes_value(false) + .display_order(91) + .help("Compiles the circuit to LLZK-IR"), + ) .arg( Arg::with_name("parallel_simplification") .long("parallel") diff --git a/circom/src/llzk_backend.rs b/circom/src/llzk_backend.rs new file mode 100644 index 000000000..c0aef2d7d --- /dev/null +++ b/circom/src/llzk_backend.rs @@ -0,0 +1,115 @@ +use std::{ + fs::{self, File}, + io::Write, + os::raw::c_void, + path::Path, +}; +use ansi_term::Color; +use anyhow::Result; +use program_structure::{ + file_definition::{FileID, FileLibrary, FileLocation}, + program_archive::ProgramArchive, +}; +use melior::{ + self, + ir::{operation::OperationLike as _, Location, Module, ValueLike}, +}; +use llzk::prelude::LlzkContext; + +/// Stores necessary context for generating LLZK IR along with the generated `Module`. +/// 'ast: lifetime of the circom AST element +/// 'llzk: lifetime of the `LlzkContext` and generated `Module` +pub struct LlzkCodegen<'ast, 'llzk> { + files: &'ast FileLibrary, + context: &'llzk LlzkContext, + module: Module<'llzk>, +} + +/// Helper for generating LLZK IR from a circom `ProgramArchive`. +impl<'ast, 'llzk> LlzkCodegen<'ast, 'llzk> { + /// Creates a new LLZK code generator to generate code for the given `ProgramArchive`. + pub fn new(context: &'llzk LlzkContext, program_archive: &'ast ProgramArchive) -> Self { + let files = &program_archive.file_library; + let filename = files.get_filename_or_default(program_archive.get_file_id_main()); + let main_file_location = Location::new(&context, &filename, 0, 0); + let module = llzk::dialect::module::llzk_module(main_file_location); + Self { files, context, module } + } + + /// Convert circom location information to MLIR location. + pub fn get_location(&self, file_id: FileID, file_location: FileLocation) -> Location<'llzk> { + let filename = self.files.get_filename_or_default(&file_id); + let line = self.files.get_line(file_location.start, file_id).unwrap_or(0); + let column = self.files.get_column(file_location.start, file_id).unwrap_or(0); + Location::new(&self.context, &filename, line, column) + } + + /// Verify the generated `Module`. + pub fn verify(&self) -> bool { + self.module.as_operation().verify() + } + + /// Write the generated `Module` to a file. + pub fn write_to_file(&self, filename: &str) -> Result<(), ()> { + let out_path = Path::new(filename); + // Ensure parent directories exist + if let Some(parent) = out_path.parent() { + fs::create_dir_all(parent).map_err(|_err| {})?; + } + let mut file = File::create(out_path).map_err(|_err| {})?; + + unsafe extern "C" fn callback(string_ref: mlir_sys::MlirStringRef, user_data: *mut c_void) { + let file = &mut *(user_data as *mut File); + let slice = std::slice::from_raw_parts(string_ref.data as *const u8, string_ref.length); + let _ = file.write_all(slice).unwrap(); + } + + unsafe { + // TODO: may need to switch to bytecode at some point. Or add an option for it. + // mlir_sys::mlirOperationWriteBytecode( + mlir_sys::mlirOperationPrint( + self.module.as_operation().to_raw(), + Some(callback), + &mut file as *mut File as *mut c_void, + ); + } + println!("{} {}", Color::Green.paint("Written successfully:"), filename); + Result::Ok(()) + } +} + +/// A trait to produce LLZK IR from the `ProgramArchive` nodes. +pub trait ProduceLLZK { + /// Produces LLZK IR from the circom `ProgramArchive` AST element. + /// 'ret: lifetime of the returned `ValueLike` object + /// 'ast: lifetime of the circom AST element + /// 'llzk: lifetime of the `LlzkContext` and generated `Module` + fn produce_llzk_ir<'ret, 'ast: 'ret, 'llzk: 'ret>( + &'ast self, + codegen: &LlzkCodegen<'ast, 'llzk>, + ) -> Result + 'ret>>; +} + +impl ProduceLLZK for ProgramArchive { + fn produce_llzk_ir<'ret, 'ast: 'ret, 'llzk: 'ret>( + &'ast self, + codegen: &LlzkCodegen<'ast, 'llzk>, + ) -> Result + 'ret>> { + todo!("Not yet implemented") + } +} + +/// Generate LLZK IR from the given `ProgramArchive` and write it to a file with the given filename. +pub fn generate_llzk(program_archive: &ProgramArchive, filename: &str) -> Result<(), ()> { + let ctx = LlzkContext::new(); + let codegen = LlzkCodegen::new(&ctx, program_archive); + + // TODO: uncomment when implemented + // program_archive.produce_llzk_ir(&codegen).expect("Failed to generate LLZK IR"); + + // Verify the module and write it to file + assert!(codegen.verify()); + codegen.write_to_file(filename).expect("Failed to write LLZK code"); + + return Result::Ok(()); +} diff --git a/circom/src/main.rs b/circom/src/main.rs index 40e2b2a01..ee0a77a3c 100644 --- a/circom/src/main.rs +++ b/circom/src/main.rs @@ -3,6 +3,7 @@ mod execution_user; mod input_user; mod parser_user; mod type_analysis_user; +mod llzk_backend; const VERSION: &'static str = env!("CARGO_PKG_VERSION"); @@ -27,6 +28,15 @@ fn start() -> Result<(), ()> { let mut program_archive = parser_user::parse_project(&user_input)?; type_analysis_user::analyse_project(&mut program_archive)?; + // Dump the ProgramArchive if requested + if user_input.dump_parse_flag() { + write_to_file(format!("{:#?}", program_archive), user_input.dump_parse_file())?; + } + // Generate LLZK IR output if requested + if user_input.llzk_flag() { + return llzk_backend::generate_llzk(&program_archive, user_input.llzk_file()); + } + let config = ExecutionConfig { no_rounds: user_input.no_rounds(), flag_p: user_input.parallel_simplification_flag(), @@ -69,3 +79,14 @@ fn start() -> Result<(), ()> { compilation_user::compile(compilation_config)?; Result::Ok(()) } + +fn write_to_file>(contents: C, filename: &str) -> Result<(), ()> { + let out_path = std::path::Path::new(filename); + // Ensure parent directories exist + if let Some(parent) = out_path.parent() { + std::fs::create_dir_all(parent).map_err(|_err| {})?; + } + std::fs::write(out_path, contents).map_err(|_err| {})?; + println!("{} {}", Colour::Green.paint("Written successfully:"), filename); + Result::Ok(()) +} diff --git a/circom/tests/lit.cfg.py b/circom/tests/lit.cfg.py new file mode 100644 index 000000000..33f843471 --- /dev/null +++ b/circom/tests/lit.cfg.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +# Modified version of +# https://raw.githubusercontent.com/llvm/llvm-project/main/mlir/examples/standalone/test/lit.cfg.py +# from LLVM, which is licensed under Apache 2.0 with LLVM Exceptions. + +# -*- Python -*- + +import os +import platform +import re +import subprocess +import tempfile + +import lit.formats +import lit.util +from lit.llvm import llvm_config +from lit.llvm.subst import FindTool, ToolSubst + +# Configuration file for the 'lit' test runner. + +assert hasattr(config, "llvm_tools_dir") +assert hasattr(config, "circom_bin_dir") +assert hasattr(config, "extra_suffixes") +assert hasattr(config, "test_exec_root") +assert hasattr(config, "available_features") +# assert hasattr(config, 'test_source_root') + +# name: The name of this test suite. +config.name = "circom" + +config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell) + +# suffixes: A list of file extensions to treat as test files. +config.suffixes = [".circom"] +config.suffixes.extend(config.extra_suffixes) + +# test_source_root: The root path where tests are located. + +# excludes: A list of directories to exclude from the testsuite. The 'Inputs' +# subdirectories contain auxiliary inputs for various tests in their parent +# directories. +config.excludes = ["Inputs", "CMakeLists.txt", "README.txt", "LICENSE.txt"] + + +# Set up environment variables + +llvm_config.with_system_environment(["HOME", "INCLUDE", "LIB", "TMP", "TEMP"]) + +llvm_config.use_default_substitutions() +llvm_config.with_environment("PATH", config.circom_bin_dir, append_path=True) +llvm_config.with_environment("PATH", config.llvm_tools_dir, append_path=True) +llvm_config.with_environment("FILECHECK_OPTS", "--dump-input-filter=all") + +tool_dirs = [config.circom_bin_dir, config.circom_src_dir] +tools = ["circom"] + +# Set up variable substitutions +llvm_config.add_tool_substitutions(tools, tool_dirs) +config.substitutions.append(("%PATH%", config.environment["PATH"])) diff --git a/circom/tests/lit.rs b/circom/tests/lit.rs new file mode 100644 index 000000000..7b909be4c --- /dev/null +++ b/circom/tests/lit.rs @@ -0,0 +1,125 @@ +#![allow(dead_code)] + +use std::fs::{self, File}; +use std::path::{Path, PathBuf}; +use assert_cmd::Command; +use assert_fs::{NamedTempFile, prelude::FileWriteStr}; +use lazy_static::lazy_static; +use regex::Regex; +use rand::{distr::Alphanumeric, Rng}; + +const TEST_INPUT: &'static str = "%s"; +const TMP_FILE: &'static str = "%t"; +const CIRCOM: &'static str = "%circom"; + +type LitResult = Result>; + +fn marked_xfail(content: &str) -> bool { + lazy_static! { + static ref RE: Regex = Regex::new(r"^//\s*XFAIL:.*$").unwrap(); + } + for line in content.lines() { + if RE.is_match(line) { + return true; + } + } + return false; +} + +fn extract_run(content: &str) -> &str { + lazy_static! { + static ref RE: Regex = Regex::new(r"^//\s*RUN:(.*)$").unwrap(); + } + for line in content.lines() { + if let Some(captures) = RE.captures(line) { + if let Some(group) = captures.get(1) { + return group.as_str(); + } + } + } + panic!("Unsupported test encountered. RUN declaration missing!") +} + +fn write_test(content: &str, name: &str) -> LitResult { + let file = NamedTempFile::new(format!("{}.circom", name).as_str())?; + file.write_str(content)?; + Ok(file) +} + +struct LitTest<'a> { + expected_failure: bool, + run_command: &'a str, + test_input: NamedTempFile, + name: &'a str, +} + +impl<'a> LitTest<'a> { + pub fn create(content: &'a str, name: &'a str) -> LitResult { + Ok(LitTest { + expected_failure: marked_xfail(content), + run_command: extract_run(content), + test_input: write_test(content, name)?, + name, + }) + } + + fn execute_expecting_success(&self, cmd: &mut Command) -> LitResult<()> { + cmd.assert().success(); + Ok(()) + } + + fn execute_expecting_failure(&self, cmd: &mut Command) -> LitResult<()> { + cmd.assert().failure(); + Ok(()) + } + + fn prepare_test(&self) -> LitResult<(String, PathBuf)> { + let temp = Path::new(env!("CARGO_TARGET_TMPDIR")); + let postfix: String = + rand::rng().sample_iter(&Alphanumeric).take(10).map(char::from).collect(); + let tmp_file = temp.join(Path::new(format!("{}.{}", self.name, postfix).as_str())); + File::create(tmp_file.clone())?; + let cmd = self + .run_command + .replace( + TEST_INPUT, + format!("\"{}\"", self.test_input.path().to_str().unwrap()).as_str(), + ) + .replace(TMP_FILE, format!("\"{}\"", tmp_file.to_str().unwrap()).as_str()) + .replace(CIRCOM, env!("CARGO_BIN_EXE_circom")); + + Ok((cmd, tmp_file)) + } + + fn cleanup_test(&self, tmp_file: &Path) -> LitResult<()> { + if tmp_file.exists() { + if tmp_file.is_file() { + fs::remove_file(tmp_file)?; + } else if tmp_file.is_dir() { + fs::remove_dir_all(tmp_file)?; + } + } + Ok(()) + } + + pub fn execute(&self) -> LitResult<()> { + let (cmd, tmp_file) = self.prepare_test()?; + let mut sh = Command::new("sh"); + sh.arg("-c").arg(cmd); + if self.expected_failure { + self.execute_expecting_failure(&mut sh) + } else { + self.execute_expecting_success(&mut sh) + }?; + self.cleanup_test(&tmp_file) + } +} + +/// Emulates a lit test +#[inline] +fn lit_test(content: &str, name: &str) -> LitResult<()> { + LitTest::create(content, name)?.execute() +} + +// build.rs generates this file with the discovered circom tests in this crate +include!(concat!(env!("OUT_DIR"), "/discovered_tests.in")); diff --git a/circom/tests/lit.site.cfg.py b/circom/tests/lit.site.cfg.py new file mode 100644 index 000000000..9621a2a38 --- /dev/null +++ b/circom/tests/lit.site.cfg.py @@ -0,0 +1,44 @@ +import os +import shutil +import subprocess +import tempfile +from pathlib import Path + +# test_source_root: The root path where tests are located. +config.test_source_root = Path(__file__).parent + +config.llvm_tools_dir = subprocess.check_output( + ["llvm-config", "--bindir"], text=True +).rstrip() +config.available_features = {"circom"} + +circom_path = config.test_source_root.parent / "target" / "debug" / "circom" +circom_path = circom_path.resolve() if circom_path.exists() else None +assert circom_path is not None, "circom not found on PATH" + + +config.circom_bin_dir = str(Path(circom_path).parent) +config.circom_src_dir = str(config.test_source_root.parent) + +config.extra_suffixes = [".txt"] + +import lit.llvm + +lit.llvm.initialize(lit_config, config) + + +def _run_lit(): + # Let the main config do the real work. + lit_config.load_config(config, config.test_source_root / "lit.cfg.py") + + +# test_exec_root: The root path where tests should be run. +override_test_exec_root = os.environ.get("CIRCOM_TEST_RUN", None) +if override_test_exec_root is None: + with tempfile.TemporaryDirectory(prefix="circom_integration_test") as test_exec_root: + config.test_exec_root = test_exec_root + _run_lit() +else: + assert Path(override_test_exec_root).is_dir() + config.test_exec_root = override_test_exec_root + _run_lit() diff --git a/circom/tests/simple/dump_parse.circom b/circom/tests/simple/dump_parse.circom new file mode 100644 index 000000000..76105efce --- /dev/null +++ b/circom/tests/simple/dump_parse.circom @@ -0,0 +1,326 @@ +// REQUIRES: circom +// RUN: rm -rf %t && mkdir %t && %circom --dump_parse -o %t %s | sed -n 's/.*Written successfully:.* \(.*\)/\1/p' | xargs cat | FileCheck %s --match-full-lines + +pragma circom 2.0.0; + +template HelloWorld() { + signal input a; + signal output b; + + b <== a; +} + +component main = HelloWorld(); +//CHECK-LABEL: ProgramArchive { +//CHECK-NEXT : id_max: 8, +//CHECK-NEXT : file_id_main: [[FD:[0-9]+]], +//CHECK-LABEL: file_library: FileLibrary { +//CHECK-NEXT : files: SimpleFiles { +//CHECK-NEXT : files: [ +//CHECK-NEXT : SimpleFile { +//CHECK-NEXT : name: "", +//CHECK-NEXT : source: "", +//CHECK-NEXT : line_starts: [ +//CHECK-NEXT : 0, +//CHECK-NEXT : ], +//CHECK-NEXT : }, +//CHECK-NEXT : SimpleFile { +//CHECK-NEXT : name: {{.*}} +//CHECK-NEXT : source: {{.*}} +// COM: (--match-full-lines ensures this matches to the end to avoid match +// COM: problems caused by 'source' containing the full content of this file) +//CHECK-NEXT : line_starts: [ +// COM: (skip the long list of "line_starts") +//CHECK-LABEL: functions: {}, +//CHECK-LABEL: templates: { +//CHECK-NEXT : "HelloWorld": TemplateData { +//CHECK-NEXT : file_id: [[FD]], +//CHECK-NEXT : name: "HelloWorld", +//CHECK-NEXT : body: Block { +//CHECK-NEXT : meta: Meta { +//CHECK-NEXT : elem_id: [[[0-9]+]], +//CHECK-NEXT : start: [[[0-9]+]], +//CHECK-NEXT : end: [[[0-9]+]], +//CHECK-NEXT : location: [[[0-9]+]]..[[[0-9]+]], +//CHECK-NEXT : file_id: Some( +//CHECK-NEXT : [[FD]], +//CHECK-NEXT : ), +//CHECK-NEXT : component_inference: None, +//CHECK-NEXT : type_knowledge: TypeKnowledge { +//CHECK-NEXT : reduces_to: None, +//CHECK-NEXT : }, +//CHECK-NEXT : memory_knowledge: MemoryKnowledge { +//CHECK-NEXT : concrete_dimensions: None, +//CHECK-NEXT : full_length: None, +//CHECK-NEXT : abstract_memory_address: None, +//CHECK-NEXT : }, +//CHECK-NEXT : }, +//CHECK-NEXT : stmts: [ +//CHECK-NEXT : InitializationBlock { +//CHECK-NEXT : meta: Meta { +//CHECK-NEXT : elem_id: [[[0-9]+]], +//CHECK-NEXT : start: [[[0-9]+]], +//CHECK-NEXT : end: [[[0-9]+]], +//CHECK-NEXT : location: [[[0-9]+]]..[[[0-9]+]], +//CHECK-NEXT : file_id: Some( +//CHECK-NEXT : [[FD]], +//CHECK-NEXT : ), +//CHECK-NEXT : component_inference: None, +//CHECK-NEXT : type_knowledge: TypeKnowledge { +//CHECK-NEXT : reduces_to: None, +//CHECK-NEXT : }, +//CHECK-NEXT : memory_knowledge: MemoryKnowledge { +//CHECK-NEXT : concrete_dimensions: None, +//CHECK-NEXT : full_length: None, +//CHECK-NEXT : abstract_memory_address: None, +//CHECK-NEXT : }, +//CHECK-NEXT : }, +//CHECK-NEXT : xtype: Var, +//CHECK-NEXT : initializations: [], +//CHECK-NEXT : }, +//CHECK-NEXT : InitializationBlock { +//CHECK-NEXT : meta: Meta { +//CHECK-NEXT : elem_id: [[[0-9]+]], +//CHECK-NEXT : start: [[[0-9]+]], +//CHECK-NEXT : end: [[[0-9]+]], +//CHECK-NEXT : location: [[[0-9]+]]..[[[0-9]+]], +//CHECK-NEXT : file_id: Some( +//CHECK-NEXT : [[FD]], +//CHECK-NEXT : ), +//CHECK-NEXT : component_inference: None, +//CHECK-NEXT : type_knowledge: TypeKnowledge { +//CHECK-NEXT : reduces_to: None, +//CHECK-NEXT : }, +//CHECK-NEXT : memory_knowledge: MemoryKnowledge { +//CHECK-NEXT : concrete_dimensions: None, +//CHECK-NEXT : full_length: None, +//CHECK-NEXT : abstract_memory_address: None, +//CHECK-NEXT : }, +//CHECK-NEXT : }, +//CHECK-NEXT : xtype: Component, +//CHECK-NEXT : initializations: [], +//CHECK-NEXT : }, +//CHECK-NEXT : InitializationBlock { +//CHECK-NEXT : meta: Meta { +//CHECK-NEXT : elem_id: [[[0-9]+]], +//CHECK-NEXT : start: [[[0-9]+]], +//CHECK-NEXT : end: [[[0-9]+]], +//CHECK-NEXT : location: [[[0-9]+]]..[[[0-9]+]], +//CHECK-NEXT : file_id: Some( +//CHECK-NEXT : [[FD]], +//CHECK-NEXT : ), +//CHECK-NEXT : component_inference: None, +//CHECK-NEXT : type_knowledge: TypeKnowledge { +//CHECK-NEXT : reduces_to: None, +//CHECK-NEXT : }, +//CHECK-NEXT : memory_knowledge: MemoryKnowledge { +//CHECK-NEXT : concrete_dimensions: None, +//CHECK-NEXT : full_length: None, +//CHECK-NEXT : abstract_memory_address: None, +//CHECK-NEXT : }, +//CHECK-NEXT : }, +//CHECK-NEXT : xtype: Signal( +//CHECK-NEXT : Input, +//CHECK-NEXT : [], +//CHECK-NEXT : ), +//CHECK-NEXT : initializations: [ +//CHECK-NEXT : Declaration { +//CHECK-NEXT : meta: Meta { +//CHECK-NEXT : elem_id: [[[0-9]+]], +//CHECK-NEXT : start: [[[0-9]+]], +//CHECK-NEXT : end: [[[0-9]+]], +//CHECK-NEXT : location: [[[0-9]+]]..[[[0-9]+]], +//CHECK-NEXT : file_id: Some( +//CHECK-NEXT : [[FD]], +//CHECK-NEXT : ), +//CHECK-NEXT : component_inference: None, +//CHECK-NEXT : type_knowledge: TypeKnowledge { +//CHECK-NEXT : reduces_to: None, +//CHECK-NEXT : }, +//CHECK-NEXT : memory_knowledge: MemoryKnowledge { +//CHECK-NEXT : concrete_dimensions: None, +//CHECK-NEXT : full_length: None, +//CHECK-NEXT : abstract_memory_address: None, +//CHECK-NEXT : }, +//CHECK-NEXT : }, +//CHECK-NEXT : xtype: Signal( +//CHECK-NEXT : Input, +//CHECK-NEXT : [], +//CHECK-NEXT : ), +//CHECK-NEXT : name: "a", +//CHECK-NEXT : dimensions: [], +//CHECK-NEXT : is_constant: true, +//CHECK-NEXT : is_anonymous: false, +//CHECK-NEXT : }, +//CHECK-NEXT : ], +//CHECK-NEXT : }, +//CHECK-NEXT : InitializationBlock { +//CHECK-NEXT : meta: Meta { +//CHECK-NEXT : elem_id: [[[0-9]+]], +//CHECK-NEXT : start: [[[0-9]+]], +//CHECK-NEXT : end: [[[0-9]+]], +//CHECK-NEXT : location: [[[0-9]+]]..[[[0-9]+]], +//CHECK-NEXT : file_id: Some( +//CHECK-NEXT : [[FD]], +//CHECK-NEXT : ), +//CHECK-NEXT : component_inference: None, +//CHECK-NEXT : type_knowledge: TypeKnowledge { +//CHECK-NEXT : reduces_to: None, +//CHECK-NEXT : }, +//CHECK-NEXT : memory_knowledge: MemoryKnowledge { +//CHECK-NEXT : concrete_dimensions: None, +//CHECK-NEXT : full_length: None, +//CHECK-NEXT : abstract_memory_address: None, +//CHECK-NEXT : }, +//CHECK-NEXT : }, +//CHECK-NEXT : xtype: Signal( +//CHECK-NEXT : Output, +//CHECK-NEXT : [], +//CHECK-NEXT : ), +//CHECK-NEXT : initializations: [ +//CHECK-NEXT : Declaration { +//CHECK-NEXT : meta: Meta { +//CHECK-NEXT : elem_id: [[[0-9]+]], +//CHECK-NEXT : start: [[[0-9]+]], +//CHECK-NEXT : end: [[[0-9]+]], +//CHECK-NEXT : location: [[[0-9]+]]..[[[0-9]+]], +//CHECK-NEXT : file_id: Some( +//CHECK-NEXT : [[FD]], +//CHECK-NEXT : ), +//CHECK-NEXT : component_inference: None, +//CHECK-NEXT : type_knowledge: TypeKnowledge { +//CHECK-NEXT : reduces_to: None, +//CHECK-NEXT : }, +//CHECK-NEXT : memory_knowledge: MemoryKnowledge { +//CHECK-NEXT : concrete_dimensions: None, +//CHECK-NEXT : full_length: None, +//CHECK-NEXT : abstract_memory_address: None, +//CHECK-NEXT : }, +//CHECK-NEXT : }, +//CHECK-NEXT : xtype: Signal( +//CHECK-NEXT : Output, +//CHECK-NEXT : [], +//CHECK-NEXT : ), +//CHECK-NEXT : name: "b", +//CHECK-NEXT : dimensions: [], +//CHECK-NEXT : is_constant: true, +//CHECK-NEXT : is_anonymous: false, +//CHECK-NEXT : }, +//CHECK-NEXT : ], +//CHECK-NEXT : }, +//CHECK-NEXT : Substitution { +//CHECK-NEXT : meta: Meta { +//CHECK-NEXT : elem_id: [[[0-9]+]], +//CHECK-NEXT : start: [[[0-9]+]], +//CHECK-NEXT : end: [[[0-9]+]], +//CHECK-NEXT : location: [[[0-9]+]]..[[[0-9]+]], +//CHECK-NEXT : file_id: Some( +//CHECK-NEXT : [[FD]], +//CHECK-NEXT : ), +//CHECK-NEXT : component_inference: None, +//CHECK-NEXT : type_knowledge: TypeKnowledge { +//CHECK-NEXT : reduces_to: Some( +//CHECK-NEXT : Signal, +//CHECK-NEXT : ), +//CHECK-NEXT : }, +//CHECK-NEXT : memory_knowledge: MemoryKnowledge { +//CHECK-NEXT : concrete_dimensions: None, +//CHECK-NEXT : full_length: None, +//CHECK-NEXT : abstract_memory_address: None, +//CHECK-NEXT : }, +//CHECK-NEXT : }, +//CHECK-NEXT : var: "b", +//CHECK-NEXT : access: [], +//CHECK-NEXT : op: AssignConstraintSignal, +//CHECK-NEXT : rhe: Variable { +//CHECK-NEXT : meta: Meta { +//CHECK-NEXT : elem_id: [[[0-9]+]], +//CHECK-NEXT : start: [[[0-9]+]], +//CHECK-NEXT : end: [[[0-9]+]], +//CHECK-NEXT : location: [[[0-9]+]]..[[[0-9]+]], +//CHECK-NEXT : file_id: Some( +//CHECK-NEXT : [[FD]], +//CHECK-NEXT : ), +//CHECK-NEXT : component_inference: None, +//CHECK-NEXT : type_knowledge: TypeKnowledge { +//CHECK-NEXT : reduces_to: Some( +//CHECK-NEXT : Signal, +//CHECK-NEXT : ), +//CHECK-NEXT : }, +//CHECK-NEXT : memory_knowledge: MemoryKnowledge { +//CHECK-NEXT : concrete_dimensions: None, +//CHECK-NEXT : full_length: None, +//CHECK-NEXT : abstract_memory_address: None, +//CHECK-NEXT : }, +//CHECK-NEXT : }, +//CHECK-NEXT : name: "a", +//CHECK-NEXT : access: [], +//CHECK-NEXT : }, +//CHECK-NEXT : }, +//CHECK-NEXT : ], +//CHECK-NEXT : }, +//CHECK-NEXT : num_of_params: 0, +//CHECK-NEXT : name_of_params: [], +//CHECK-NEXT : param_location: [[[0-9]+]]..[[[0-9]+]], +//CHECK-NEXT : input_wires: { +//CHECK-NEXT : "a": WireData { +//CHECK-NEXT : wire_type: Signal, +//CHECK-NEXT : dimension: 0, +//CHECK-NEXT : tag_info: {}, +//CHECK-NEXT : }, +//CHECK-NEXT : }, +//CHECK-NEXT : output_wires: { +//CHECK-NEXT : "b": WireData { +//CHECK-NEXT : wire_type: Signal, +//CHECK-NEXT : dimension: 0, +//CHECK-NEXT : tag_info: {}, +//CHECK-NEXT : }, +//CHECK-NEXT : }, +//CHECK-NEXT : is_parallel: false, +//CHECK-NEXT : is_custom_gate: false, +//CHECK-NEXT : is_extern_c: false, +//CHECK-NEXT : input_declarations: [ +//CHECK-NEXT : ( +//CHECK-NEXT : "a", +//CHECK-NEXT : 0, +//CHECK-NEXT : ), +//CHECK-NEXT : ], +//CHECK-NEXT : output_declarations: [ +//CHECK-NEXT : ( +//CHECK-NEXT : "b", +//CHECK-NEXT : 0, +//CHECK-NEXT : ), +//CHECK-NEXT : ], +//CHECK-NEXT : }, +//CHECK-NEXT : }, +//CHECK-NEXT : buses: {}, +//CHECK-NEXT : function_keys: {}, +//CHECK-NEXT : template_keys: { +//CHECK-NEXT : "HelloWorld", +//CHECK-NEXT : }, +//CHECK-NEXT : bus_keys: {}, +//CHECK-NEXT : public_inputs: [], +//CHECK-NEXT : initial_template_call: Call { +//CHECK-NEXT : meta: Meta { +//CHECK-NEXT : elem_id: [[[0-9]+]], +//CHECK-NEXT : start: [[[0-9]+]], +//CHECK-NEXT : end: [[[0-9]+]], +//CHECK-NEXT : location: [[[0-9]+]]..[[[0-9]+]], +//CHECK-NEXT : file_id: Some( +//CHECK-NEXT : [[FD]], +//CHECK-NEXT : ), +//CHECK-NEXT : component_inference: None, +//CHECK-NEXT : type_knowledge: TypeKnowledge { +//CHECK-NEXT : reduces_to: None, +//CHECK-NEXT : }, +//CHECK-NEXT : memory_knowledge: MemoryKnowledge { +//CHECK-NEXT : concrete_dimensions: None, +//CHECK-NEXT : full_length: None, +//CHECK-NEXT : abstract_memory_address: None, +//CHECK-NEXT : }, +//CHECK-NEXT : }, +//CHECK-NEXT : id: "HelloWorld", +//CHECK-NEXT : args: [], +//CHECK-NEXT : }, +//CHECK-NEXT : custom_gates: false, +//CHECK-NEXT : } diff --git a/circom/tests/simple/trivially_empty.circom b/circom/tests/simple/trivially_empty.circom new file mode 100644 index 000000000..8704ccd2a --- /dev/null +++ b/circom/tests/simple/trivially_empty.circom @@ -0,0 +1,10 @@ +// REQUIRES: circom +// RUN: rm -rf %t && mkdir %t && %circom --llzk -o %t %s | sed -n 's/.*Written successfully:.* \(.*\)/\1/p' | xargs cat | FileCheck %s --enable-var-scope + +pragma circom 2.0.0; + +template EmptyTemplate() { +} +component main = EmptyTemplate(); +//CHECK-LABEL: module attributes {veridise.lang = "llzk"} { +//CHECK-NEXT: } diff --git a/circom_algebra/src/algebra.rs b/circom_algebra/src/algebra.rs index 235b7e951..d9c5227a9 100644 --- a/circom_algebra/src/algebra.rs +++ b/circom_algebra/src/algebra.rs @@ -1388,6 +1388,7 @@ pub fn normalize(c: Constraint, _field: &BigInt) -> Constraint { } #[cfg(test)] +#[allow(dead_code)] mod test { use crate::algebra::{ArithmeticExpression, Constraint, Substitution}; use crate::modular_arithmetic; @@ -1449,46 +1450,46 @@ mod test { assert_eq!(*sub_value, constant_new_coefficient); } - #[test] - fn algebra_constraint_apply_substitution() { - let field = BigInt::parse_bytes(FIELD.as_bytes(), 10) - .expect("generating the big int was not possible"); - // symbols - let x = 1; - let y = 2; - let constant = C::constant_coefficient(); - - // constraint: x + y + 4 = 0 - let x_c = BigInt::from(1); - let y_c = BigInt::from(1); - let constant_c = BigInt::from(4); - let a = HashMap::new(); - let b = HashMap::new(); - let mut c = HashMap::new(); - c.insert(x, x_c); - c.insert(y, y_c); - c.insert(constant, constant_c); - let mut constraint = C::new(a, b, c); - - // substitution: x = 2y + 3 - let y_c = BigInt::from(2); - let constant_c = BigInt::from(3); - let from = x; - let mut to_raw = HashMap::new(); - to_raw.insert(y, y_c); - to_raw.insert(constant, constant_c); - let to = A::Linear { coefficients: to_raw }; - let substitution = S::new(from, to).unwrap(); - - // result: 3y + 7 = 0 - let expected_y_c = BigInt::from(3); - let expected_constant_c = BigInt::from(7); - C::apply_substitution(&mut constraint, &substitution, &field); - let y_c = constraint.c.get(&y).unwrap(); - let constant_c = constraint.c.get(&constant).unwrap(); - assert!(constraint.a.is_empty()); - assert!(constraint.b.is_empty()); - assert_eq!(*y_c, expected_y_c); - assert_eq!(*constant_c, expected_constant_c); - } + // #[test] + // fn algebra_constraint_apply_substitution() { + // let field = BigInt::parse_bytes(FIELD.as_bytes(), 10) + // .expect("generating the big int was not possible"); + // // symbols + // let x = 1; + // let y = 2; + // let constant = C::constant_coefficient(); + // + // // constraint: x + y + 4 = 0 + // let x_c = BigInt::from(1); + // let y_c = BigInt::from(1); + // let constant_c = BigInt::from(4); + // let a = HashMap::new(); + // let b = HashMap::new(); + // let mut c = HashMap::new(); + // c.insert(x, x_c); + // c.insert(y, y_c); + // c.insert(constant, constant_c); + // let mut constraint = C::new(a, b, c); + // + // // substitution: x = 2y + 3 + // let y_c = BigInt::from(2); + // let constant_c = BigInt::from(3); + // let from = x; + // let mut to_raw = HashMap::new(); + // to_raw.insert(y, y_c); + // to_raw.insert(constant, constant_c); + // let to = A::Linear { coefficients: to_raw }; + // let substitution = S::new(from, to).unwrap(); + // + // // result: 3y + 7 = 0 + // let expected_y_c = BigInt::from(3); + // let expected_constant_c = BigInt::from(7); + // C::apply_substitution(&mut constraint, &substitution, &field); + // let y_c = constraint.c.get(&y).unwrap(); + // let constant_c = constraint.c.get(&constant).unwrap(); + // assert!(constraint.a.is_empty()); + // assert!(constraint.b.is_empty()); + // assert_eq!(*y_c, expected_y_c); + // assert_eq!(*constant_c, expected_constant_c); + // } } diff --git a/circom_algebra/src/modular_arithmetic.rs b/circom_algebra/src/modular_arithmetic.rs index 60c386c05..33083a617 100644 --- a/circom_algebra/src/modular_arithmetic.rs +++ b/circom_algebra/src/modular_arithmetic.rs @@ -246,17 +246,17 @@ mod tests { assert!(false); } } - #[test] - fn complement_of_complement_is_the_original_test() { - let field = BigInt::parse_bytes(FIELD.as_bytes(), 10) - .expect("generating the big int was not possible"); - let big_num = BigInt::parse_bytes("1234".as_bytes(), 10) - .expect("generating the big int was not possible"); - let big_num_complement = complement(&big_num, &field); - let big_num_complement_complement = complement(&big_num_complement, &field); - let big_num_modulus = modulus(&big_num, &field); - assert_eq!(big_num_complement_complement, big_num_modulus); - } + // #[test] + // fn complement_of_complement_is_the_original_test() { + // let field = BigInt::parse_bytes(FIELD.as_bytes(), 10) + // .expect("generating the big int was not possible"); + // let big_num = BigInt::parse_bytes("1234".as_bytes(), 10) + // .expect("generating the big int was not possible"); + // let big_num_complement = complement(&big_num, &field); + // let big_num_complement_complement = complement(&big_num_complement, &field); + // let big_num_modulus = modulus(&big_num, &field); + // assert_eq!(big_num_complement_complement, big_num_modulus); + // } #[test] fn lesser_eq_test() { let field = BigInt::parse_bytes(FIELD.as_bytes(), 10) diff --git a/code_producers/src/c_elements/c_code_generator.rs b/code_producers/src/c_elements/c_code_generator.rs index 6ba884bc8..1f3df0015 100644 --- a/code_producers/src/c_elements/c_code_generator.rs +++ b/code_producers/src/c_elements/c_code_generator.rs @@ -1305,7 +1305,7 @@ mod tests { use std::path::Path; // use std::fs::File; use super::*; - const LOCATION: &'static str = "../target/code_generator_test"; + const LOCATION: &'static str = "../target/code_generator_test/c"; fn create_producer() -> CProducer { CProducer::default() @@ -1314,7 +1314,7 @@ mod tests { #[test] fn produce_dat() { if !Path::new(LOCATION).is_dir() { - std::fs::create_dir(LOCATION).unwrap(); + std::fs::create_dir_all(LOCATION).unwrap(); } let path = format!("{}/code", LOCATION); let producer = create_producer(); diff --git a/code_producers/src/wasm_elements/wasm_code_generator.rs b/code_producers/src/wasm_elements/wasm_code_generator.rs index ba1ca868e..80f17faf6 100644 --- a/code_producers/src/wasm_elements/wasm_code_generator.rs +++ b/code_producers/src/wasm_elements/wasm_code_generator.rs @@ -1822,7 +1822,7 @@ mod tests { use super::*; use std::io::{BufRead, BufReader, BufWriter, Write}; use std::path::Path; - const LOCATION: &'static str = "../target/code_generator_test"; + const LOCATION: &'static str = "../target/code_generator_test/wasm"; fn create_producer() -> WASMProducer { WASMProducer::default() @@ -1830,7 +1830,7 @@ mod tests { fn create_writer() -> BufWriter { if !Path::new(LOCATION).is_dir() { - std::fs::create_dir(LOCATION).unwrap(); + std::fs::create_dir_all(LOCATION).unwrap(); } let path = format!("{}/code.wat", LOCATION); let file = File::create(path).unwrap(); diff --git a/compiler/src/circuit_design/build.rs b/compiler/src/circuit_design/build.rs index a5c148312..615a018ac 100644 --- a/compiler/src/circuit_design/build.rs +++ b/compiler/src/circuit_design/build.rs @@ -15,7 +15,7 @@ fn matching_lengths_and_offsets(list: &InputOutputList) { let mut prev = 0; let mut offset = 0; for signal in list { - //debug_assert_eq!(signal.offset, prev + offset); + debug_assert_eq!(signal.offset, prev + offset); prev = signal.offset; offset = signal.lengths.iter().fold(signal.size, |p, c| p * (*c)); } diff --git a/compiler/src/hir/analysis_utilities.rs b/compiler/src/hir/analysis_utilities.rs index dc9f877f3..54939321a 100644 --- a/compiler/src/hir/analysis_utilities.rs +++ b/compiler/src/hir/analysis_utilities.rs @@ -14,6 +14,7 @@ pub struct InfoBus { +#[allow(dead_code)] pub struct GenericFunction { pub name: String, pub params_names: Vec, diff --git a/constraint_generation/src/execution_data/executed_bus.rs b/constraint_generation/src/execution_data/executed_bus.rs index b474d6b28..81a407ef1 100644 --- a/constraint_generation/src/execution_data/executed_bus.rs +++ b/constraint_generation/src/execution_data/executed_bus.rs @@ -5,6 +5,7 @@ use compiler::hir::very_concrete_program::*; +#[allow(dead_code)] pub struct BusConnexion{ pub full_name: String, pub inspect: BusData, @@ -13,6 +14,7 @@ pub struct BusConnexion{ } +#[allow(dead_code)] pub struct ExecutedBus { pub bus_name: String, pub report_name: String, diff --git a/constraint_generation/src/execution_data/type_definitions.rs b/constraint_generation/src/execution_data/type_definitions.rs index 4711521b9..44b07b014 100644 --- a/constraint_generation/src/execution_data/type_definitions.rs +++ b/constraint_generation/src/execution_data/type_definitions.rs @@ -46,6 +46,7 @@ pub struct SubComponentData { pub goes_to: NodePointer, } +#[allow(dead_code)] pub struct BusData { pub name: String, pub goes_to: NodePointer, @@ -80,6 +81,7 @@ pub struct AccessingInformationBus { pub tag_access: Option ==> may not appear, } */ +#[allow(dead_code)] pub struct AccessingInformation { pub undefined: bool, pub before_signal: Vec, diff --git a/dag/src/lib.rs b/dag/src/lib.rs index 19d325da3..04903d9e7 100644 --- a/dag/src/lib.rs +++ b/dag/src/lib.rs @@ -31,7 +31,7 @@ pub struct Tree<'a> { } impl<'a> Tree<'a> { - pub fn new(dag: &DAG) -> Tree { + pub fn new(dag: &'_ DAG) -> Tree<'_> { let constants = UsefulConstants::new(&dag.prime); let field = constants.get_p().clone(); let root = dag.get_main().unwrap(); diff --git a/flake.lock b/flake.lock new file mode 100644 index 000000000..d74ee6a5e --- /dev/null +++ b/flake.lock @@ -0,0 +1,169 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1652776076, + "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "type": "github" + }, + "original": { + "owner": "numtide", + "ref": "v1.0.0", + "repo": "flake-utils", + "type": "github" + } + }, + "llzk-lib": { + "inputs": { + "flake-utils": [ + "llzk-pkgs", + "flake-utils" + ], + "llzk-pkgs": [ + "llzk-pkgs" + ], + "nixpkgs": [ + "llzk-pkgs", + "nixpkgs" + ], + "release-helpers": "release-helpers" + }, + "locked": { + "lastModified": 1759503547, + "narHash": "sha256-IKt+y3HMCn1KTPSrVxEHKoizwo8F8lVx7ZyRR5uSIZ0=", + "owner": "Veridise", + "repo": "llzk-lib", + "rev": "6e3404bdcc283137602998ab7bb13ce945ca0387", + "type": "github" + }, + "original": { + "owner": "Veridise", + "repo": "llzk-lib", + "type": "github" + } + }, + "llzk-pkgs": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1759260436, + "narHash": "sha256-5+s6xkcEwDsgTq25s2JdeDqspvu0TF7MUS3ZU3VC5KE=", + "owner": "Veridise", + "repo": "llzk-nix-pkgs", + "rev": "1b823ab142612a5c8b03e4b99dfebdf0ad35c887", + "type": "github" + }, + "original": { + "owner": "Veridise", + "repo": "llzk-nix-pkgs", + "type": "github" + } + }, + "llzk-rs-pkgs": { + "inputs": { + "flake-utils": [ + "llzk-pkgs", + "flake-utils" + ], + "llzk-lib": [ + "llzk-lib" + ], + "llzk-pkgs": [ + "llzk-pkgs" + ], + "nixpkgs": [ + "llzk-pkgs", + "nixpkgs" + ], + "release-helpers": [ + "llzk-rs-pkgs", + "llzk-lib", + "release-helpers" + ] + }, + "locked": { + "lastModified": 1759950426, + "narHash": "sha256-rKv4lIMVQ9rcS/v8Vm/dUWLhAfd+ZztfpgqxlaYNgHY=", + "ref": "refs/heads/main", + "rev": "c6c769b4def0c714d7f09d356ea0d1ce8c966c3f", + "revCount": 253, + "submodules": true, + "type": "git", + "url": "https://github.com/Veridise/llzk-rs" + }, + "original": { + "submodules": true, + "type": "git", + "url": "https://github.com/Veridise/llzk-rs" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1758917213, + "narHash": "sha256-1oA6zZxSl8F1yCKEWnw8EdE1TGoifTWlwGdfUlAQ5Hs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1fb3d0b78eb00961e57bf274d980120dd8a48f82", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" + } + }, + "release-helpers": { + "inputs": { + "flake-utils": [ + "llzk-lib", + "llzk-pkgs", + "flake-utils" + ], + "nixpkgs": [ + "llzk-lib", + "llzk-pkgs", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1747068965, + "narHash": "sha256-px7s7IVHnR3SiShc7FKCUiL6vfqew5AM6jnkH7qO03I=", + "owner": "Veridise", + "repo": "open-source-release-helpers", + "rev": "c3d1ab6082cc62b167927d074f2836f290b9e3b7", + "type": "github" + }, + "original": { + "owner": "Veridise", + "repo": "open-source-release-helpers", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": [ + "llzk-pkgs", + "flake-utils" + ], + "llzk-lib": "llzk-lib", + "llzk-pkgs": "llzk-pkgs", + "llzk-rs-pkgs": "llzk-rs-pkgs", + "nixpkgs": [ + "llzk-pkgs", + "nixpkgs" + ], + "release-helpers": [ + "llzk-lib", + "release-helpers" + ] + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 000000000..0ed49698b --- /dev/null +++ b/flake.nix @@ -0,0 +1,116 @@ +{ + inputs = { + llzk-pkgs.url = "github:Veridise/llzk-nix-pkgs"; + nixpkgs.follows = "llzk-pkgs/nixpkgs"; + flake-utils.follows = "llzk-pkgs/flake-utils"; + llzk-lib = { + url = "github:Veridise/llzk-lib"; + inputs = { + nixpkgs.follows = "llzk-pkgs/nixpkgs"; + flake-utils.follows = "llzk-pkgs/flake-utils"; + llzk-pkgs.follows = "llzk-pkgs"; + }; + }; + release-helpers.follows = "llzk-lib/release-helpers"; + + llzk-rs-pkgs = { + url = "git+https://github.com/Veridise/llzk-rs?submodules=1"; + inputs = { + nixpkgs.follows = "llzk-pkgs/nixpkgs"; + flake-utils.follows = "llzk-pkgs/flake-utils"; + llzk-pkgs.follows = "llzk-pkgs"; + llzk-lib.follows = "llzk-lib"; + }; + }; + }; + + # Custom colored bash prompt + nixConfig.bash-prompt = "\\[\\e[0;32m\\][circom]\\[\\e[m\\] \\[\\e[38;5;244m\\]\\w\\[\\e[m\\] % "; + + outputs = + { + self, + nixpkgs, + flake-utils, + release-helpers, + llzk-pkgs, + llzk-lib, + llzk-rs-pkgs, + }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs { + inherit system; + overlays = [ + llzk-pkgs.overlays.default + llzk-lib.overlays.default + llzk-rs-pkgs.overlays.default + release-helpers.overlays.default + ]; + }; + + circomBuildInputs = with pkgs; [ + # TODO: not actually sure if I need either of these 2. + libffi + libiconv + ]; + + # Lit tests need FileCheck but directly adding the LLVM `bin` dir to the path causes + # linking problems in `llzk-sys`. Instead, create a symlink in a new directory for the path. + createFileCheckSymlink = '' + mkdir -p $PWD/build-tools + ln -sf "${pkgs.llzk-llvmPackages.llvm}/bin/FileCheck" $PWD/build-tools/FileCheck + export PATH="$PWD/build-tools:$PATH" + ''; + in + { + packages = flake-utils.lib.flattenTree { + default = pkgs.rustPlatform.buildRustPackage ( + rec { + pname = "circom-to-llzk"; + version = "0.1.0"; + src = ./.; + + nativeBuildInputs = pkgs.llzkSharedEnvironment.nativeBuildInputs; + buildInputs = pkgs.llzkSharedEnvironment.devBuildInputs ++ circomBuildInputs; + cargoLock = { + lockFile = ./Cargo.lock; + allowBuiltinFetchGit = true; + }; + + cargoBuildFlags = [ + "--package" + "circom" + ]; + cargoTestFlags = [ + "--package" + "circom" + ]; + preBuild = createFileCheckSymlink; + } + // pkgs.llzkSharedEnvironment.env + // pkgs.llzkSharedEnvironment.pkgSettings + ); + }; + + devShells = flake-utils.lib.flattenTree { + default = pkgs.mkShell ( + { + nativeBuildInputs = pkgs.llzkSharedEnvironment.nativeBuildInputs; + buildInputs = pkgs.llzkSharedEnvironment.devBuildInputs ++ circomBuildInputs; + + shellHook = '' + ## Bail out of pipes where any command fails + set -uo pipefail + ${createFileCheckSymlink} + echo "Welcome to the circom-to-llzk devshell!" + ''; + } + // pkgs.llzkSharedEnvironment.env + // pkgs.llzkSharedEnvironment.devSettings + ); + }; + } + ); +} diff --git a/program_structure/src/abstract_syntax_tree/ast.rs b/program_structure/src/abstract_syntax_tree/ast.rs index 7b89e8bd9..477146ae8 100644 --- a/program_structure/src/abstract_syntax_tree/ast.rs +++ b/program_structure/src/abstract_syntax_tree/ast.rs @@ -20,7 +20,7 @@ pub fn build_main_component(public: Vec, call: Expression) -> MainCompon pub type Version = (usize, usize, usize); -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Meta { pub elem_id: usize, pub start: usize, @@ -197,7 +197,7 @@ pub fn build_bus( Definition::Bus { meta, name, args, arg_location, body } } -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum Statement { IfThenElse { meta: Meta, @@ -264,7 +264,7 @@ pub enum Statement { }, } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub enum SignalType { Output, Input, @@ -274,7 +274,7 @@ pub enum SignalType { pub type TagList = Vec; -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum VariableType { Var, Signal(SignalType, TagList), @@ -283,7 +283,7 @@ pub enum VariableType { Bus(String, SignalType, TagList), } -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum Expression { InfixOp { meta: Meta, @@ -345,7 +345,7 @@ pub enum Expression { }, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum Access { ComponentAccess(String), ArrayAccess(Expression), @@ -357,14 +357,14 @@ pub fn build_array_access(expr: Expression) -> Access { Access::ArrayAccess(expr) } -#[derive(Copy, Clone, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum AssignOp { AssignVar, AssignSignal, AssignConstraintSignal, } -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum ExpressionInfixOpcode { Mul, Div, @@ -388,7 +388,7 @@ pub enum ExpressionInfixOpcode { BitXor, } -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum ExpressionPrefixOpcode { Sub, BoolNot, @@ -397,7 +397,7 @@ pub enum ExpressionPrefixOpcode { // Knowledge buckets -#[derive(Clone, PartialOrd, PartialEq, Ord, Eq)] +#[derive(Clone, Debug, PartialOrd, PartialEq, Ord, Eq)] pub enum TypeReduction { Variable, Component(Option), @@ -406,7 +406,7 @@ pub enum TypeReduction { Tag, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum LogArgument { LogStr(String), LogExp(Expression), @@ -419,7 +419,7 @@ pub fn build_log_expression(expr: Expression) -> LogArgument { } -#[derive(Default, Clone)] +#[derive(Default, Clone, Debug)] pub struct TypeKnowledge { reduces_to: Option, } @@ -468,7 +468,7 @@ impl TypeKnowledge { } } -#[derive(Default, Clone)] +#[derive(Default, Clone, Debug)] pub struct MemoryKnowledge { concrete_dimensions: Option>, full_length: Option, diff --git a/program_structure/src/program_library/bus_data.rs b/program_structure/src/program_library/bus_data.rs index 712497854..1ae15abb7 100644 --- a/program_structure/src/program_library/bus_data.rs +++ b/program_structure/src/program_library/bus_data.rs @@ -5,7 +5,7 @@ use super::wire_data::*; pub type BusInfo = HashMap; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct BusData { file_id: FileID, name: String, diff --git a/program_structure/src/program_library/file_definition.rs b/program_structure/src/program_library/file_definition.rs index e372b3034..074fbe544 100644 --- a/program_structure/src/program_library/file_definition.rs +++ b/program_structure/src/program_library/file_definition.rs @@ -1,4 +1,4 @@ -use codespan_reporting::files::{Files, SimpleFiles}; +use codespan_reporting::files::{Files, SimpleFile, SimpleFiles}; use std::ops::Range; pub type FileSource = String; @@ -7,14 +7,16 @@ pub type FileID = usize; pub type FileLocation = Range; type FileStorage = SimpleFiles; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct FileLibrary { files: FileStorage, } impl Default for FileLibrary { fn default() -> Self { - FileLibrary { files: FileStorage::new() } + let mut files = FileStorage::new(); + files.add(String::from(""), String::from("")); + FileLibrary { files } } } @@ -26,11 +28,25 @@ impl FileLibrary { self.get_mut_files().add(file_name, file_source) } pub fn get_line(&self, start: usize, file_id: FileID) -> Option { - match self.files.line_index(file_id, start) { - Some(lines) => Some(lines + 1), - None => None, + self.files.location(file_id, start).map(|loc| loc.line_number) + } + pub fn get_column(&self, start: usize, file_id: FileID) -> Option { + self.files.location(file_id, start).map(|loc| loc.column_number) + } + pub fn get_file(&self, file_id: &FileID) -> Option<&SimpleFile> { + self.files.get(*file_id) + } + pub fn get_filename_or(&self, file_id: &FileID, default: &FilePath) -> FilePath { + let sf_opt = self.get_file(file_id); + match sf_opt { + Some(sf) => sf.name().replace("\"", ""), + None => default.clone(), } } + + pub fn get_filename_or_default(&self, file_id: &FileID) -> FilePath { + self.get_filename_or(file_id, &FilePath::from("")) + } pub fn to_storage(&self) -> &FileStorage { &self.get_files() } diff --git a/program_structure/src/program_library/function_data.rs b/program_structure/src/program_library/function_data.rs index c1e022d21..c3dde4a53 100644 --- a/program_structure/src/program_library/function_data.rs +++ b/program_structure/src/program_library/function_data.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; pub type FunctionInfo = HashMap; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct FunctionData { name: String, file_id: FileID, diff --git a/program_structure/src/program_library/program_archive.rs b/program_structure/src/program_library/program_archive.rs index 3a55d95bf..ca6b48ff4 100644 --- a/program_structure/src/program_library/program_archive.rs +++ b/program_structure/src/program_library/program_archive.rs @@ -10,7 +10,7 @@ use crate::error_definition::Report; type Contents = Vec<(FileID, Vec)>; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct ProgramArchive { pub id_max: usize, pub file_id_main: FileID, diff --git a/program_structure/src/program_library/template_data.rs b/program_structure/src/program_library/template_data.rs index 142e1afc0..3c75baa6c 100644 --- a/program_structure/src/program_library/template_data.rs +++ b/program_structure/src/program_library/template_data.rs @@ -6,7 +6,7 @@ use std::collections::{HashMap}; pub type TemplateInfo = HashMap; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct TemplateData { file_id: FileID, name: String, diff --git a/program_structure/src/program_library/wire_data.rs b/program_structure/src/program_library/wire_data.rs index 8e539a89f..d1d5805ec 100644 --- a/program_structure/src/program_library/wire_data.rs +++ b/program_structure/src/program_library/wire_data.rs @@ -6,14 +6,14 @@ pub type WireInfo = HashMap; pub type WireDeclarationOrder = Vec<(String, usize)>; -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum WireType { Signal, Bus(String), } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct WireData { wire_type: WireType, dimension: usize, diff --git a/scripts/update_llzk_lib.sh b/scripts/update_llzk_lib.sh new file mode 100755 index 000000000..fecc2012b --- /dev/null +++ b/scripts/update_llzk_lib.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +# Program: update_llzk_lib.sh +# Description: This script updates the llzk-lib dependency +# in the cargo lock file and the nix flake lock file. +# +# Required Programs: +# - cargo: For updating the rust dependencies +# - nix: For updating the nix flake +# +# Usage: ./scripts/update_llzk_lib.sh + +set -e + +cargo update -p llzk +nix flake update llzk-lib +nix flake update llzk-rs-pkgs