Configuration system. Kill DFL_T (#127)

* Configuration system. Kill DFL_T

* add circ::cfg::CircCfg that holds cfg info
   * it's constructible from circ_opt::CircOpt
      * implements clap::Args, so you can set it from your compiler's
        CLI/envvars
      * defined in external crate to keep clap out of our main build
      * organized by circ module, but not feature gated
         *  no point: the build wouldn't meaningfully change
      * includes a way to set the default field
* added circ::cfg::set and circ::cfg::cfg
   * also circ::cfg::set_default and circ::cfg::set_cfg
   * access a sync::once_cell, static configuration
* killed DFL_T

* workflows
   * unit-tested component probably need to not read circ::cfg::cfg.
   * compilers need to call circ::cfg::set or circ::cfg::set_default.

* rm dead features
This commit is contained in:
Alex Ozdemir
2022-12-25 20:53:27 -08:00
committed by GitHub
parent 05b793d565
commit be8741c615
29 changed files with 2060 additions and 505 deletions

161
Cargo.lock generated
View File

@@ -48,15 +48,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
name = "approx"
version = "0.5.1"
@@ -257,6 +248,7 @@ dependencies = [
"bincode",
"bls12_381",
"circ_fields",
"circ_opt",
"curve25519-dalek",
"env_logger",
"ff",
@@ -275,6 +267,7 @@ dependencies = [
"logos",
"lp-solvers",
"merlin",
"once_cell",
"pairing",
"paste",
"pest",
@@ -290,7 +283,6 @@ dependencies = [
"serde_bytes",
"serde_json",
"spartan",
"structopt",
"thiserror",
"typed-arena",
"zokrates_parser",
@@ -313,18 +305,47 @@ dependencies = [
]
[[package]]
name = "clap"
version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
name = "circ_opt"
version = "0.1.0"
dependencies = [
"clap",
]
[[package]]
name = "clap"
version = "4.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2148adefda54e14492fb9bddcc600b4344c5d1a3123bd666dcb939c6f0e0e57e"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"clap_derive",
"clap_lex",
"once_cell",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
"termcolor",
]
[[package]]
name = "clap_derive"
version = "4.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2 1.0.49",
"quote 1.0.18",
"syn 1.0.95",
]
[[package]]
name = "clap_lex"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
[[package]]
@@ -491,7 +512,7 @@ version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
dependencies = [
"proc-macro2 1.0.39",
"proc-macro2 1.0.49",
"quote 1.0.18",
"syn 1.0.95",
"synstructure",
@@ -532,7 +553,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e715451ab983be06481e927a275ec12372103ad426c7cb82cebfe14698ed4cf4"
dependencies = [
"num-traits",
"proc-macro2 1.0.39",
"proc-macro2 1.0.49",
"quote 1.0.18",
"syn 1.0.95",
]
@@ -548,7 +569,7 @@ dependencies = [
"num-bigint",
"num-integer",
"num-traits",
"proc-macro2 1.0.39",
"proc-macro2 1.0.49",
"quote 1.0.18",
"syn 1.0.95",
]
@@ -700,12 +721,9 @@ dependencies = [
[[package]]
name = "heck"
version = "0.3.3"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "hermit-abi"
@@ -835,7 +853,7 @@ checksum = "56a7d287fd2ac3f75b11f19a1c8a874a7d55744bd91f7a1b3e7cf87d4343c36d"
dependencies = [
"beef",
"fnv",
"proc-macro2 1.0.39",
"proc-macro2 1.0.49",
"quote 1.0.18",
"regex-syntax",
"syn 1.0.95",
@@ -954,9 +972,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.11.0"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b10983b38c53aebdf33f542c6275b0f58a238129d00c4ae0e6fb59738d783ca"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
[[package]]
name = "opaque-debug"
@@ -964,6 +982,12 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]]
name = "os_str_bytes"
version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]]
name = "pairing"
version = "0.22.0"
@@ -1020,7 +1044,7 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
dependencies = [
"pest",
"pest_meta",
"proc-macro2 1.0.39",
"proc-macro2 1.0.49",
"quote 1.0.18",
"syn 1.0.95",
]
@@ -1059,7 +1083,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2 1.0.39",
"proc-macro2 1.0.49",
"quote 1.0.18",
"syn 1.0.95",
"version_check",
@@ -1071,7 +1095,7 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2 1.0.39",
"proc-macro2 1.0.49",
"quote 1.0.18",
"version_check",
]
@@ -1087,9 +1111,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.39"
version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
dependencies = [
"unicode-ident",
]
@@ -1111,7 +1135,7 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b22a693222d716a9587786f37ac3f6b4faedb5b80c23914e7303ff5a1d8016e9"
dependencies = [
"proc-macro2 1.0.39",
"proc-macro2 1.0.49",
"quote 1.0.18",
"syn 1.0.95",
]
@@ -1131,7 +1155,7 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
dependencies = [
"proc-macro2 1.0.39",
"proc-macro2 1.0.49",
]
[[package]]
@@ -1342,7 +1366,7 @@ version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
dependencies = [
"proc-macro2 1.0.39",
"proc-macro2 1.0.49",
"quote 1.0.18",
"syn 1.0.95",
]
@@ -1427,33 +1451,9 @@ dependencies = [
[[package]]
name = "strsim"
version = "0.8.0"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "structopt"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
dependencies = [
"clap",
"lazy_static",
"structopt-derive",
]
[[package]]
name = "structopt-derive"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2 1.0.39",
"quote 1.0.18",
"syn 1.0.95",
]
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "subtle"
@@ -1478,7 +1478,7 @@ version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942"
dependencies = [
"proc-macro2 1.0.39",
"proc-macro2 1.0.49",
"quote 1.0.18",
"unicode-ident",
]
@@ -1489,7 +1489,7 @@ version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
"proc-macro2 1.0.39",
"proc-macro2 1.0.49",
"quote 1.0.18",
"syn 1.0.95",
"unicode-xid 0.2.3",
@@ -1524,15 +1524,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "thiserror"
version = "1.0.31"
@@ -1548,7 +1539,7 @@ version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
dependencies = [
"proc-macro2 1.0.39",
"proc-macro2 1.0.49",
"quote 1.0.18",
"syn 1.0.95",
]
@@ -1577,18 +1568,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
[[package]]
name = "unicode-segmentation"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.1.0"
@@ -1607,12 +1586,6 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.4"
@@ -1698,7 +1671,7 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17"
dependencies = [
"proc-macro2 1.0.39",
"proc-macro2 1.0.49",
"quote 1.0.18",
"syn 1.0.95",
"synstructure",

View File

@@ -8,6 +8,7 @@ edition = "2018"
[dependencies]
circ_fields = { path = "circ_fields" }
circ_opt = { path = "circ_opt" }
#hashconsing = "1.3"
hashconsing = { git = "https://github.com/alex-ozdemir/hashconsing.git", branch = "phash"}
rug = { version = "1.11", features = ["serde"] }
@@ -46,21 +47,17 @@ merlin = { version = "3.0.0", optional = true }
curve25519-dalek = {version = "3.2.0", features = ["serde"], optional = true}
paste = "1.0"
im = "15"
once_cell = "1"
[dev-dependencies]
quickcheck = "1"
quickcheck_macros = "1"
env_logger = "0.8"
bls12_381 = "0.7"
structopt = "0.3"
approx = "0.5.0"
[features]
default = ["bls12381", "ff_dfl"]
bls12381 = []
bn254 = []
ristretto255 = []
ff_dfl = []
default = []
c = ["lang-c"]
lp = ["good_lp", "lp-solvers"]
r1cs = ["bellman", "spartan", "merlin", "curve25519-dalek"]

1
circ_opt/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
target

790
circ_opt/Cargo.lock generated Normal file
View File

@@ -0,0 +1,790 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bytes"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
[[package]]
name = "cc"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "circ_opt"
version = "0.1.0"
dependencies = [
"clap",
"heck",
"trycmd",
]
[[package]]
name = "clap"
version = "4.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "656ad1e55e23d287773f7d8192c300dc715c3eeded93b3da651d11c42cfd74d2"
dependencies = [
"bitflags",
"clap_derive",
"clap_lex",
"is-terminal",
"once_cell",
"strsim",
"termcolor",
]
[[package]]
name = "clap_derive"
version = "4.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "combine"
version = "4.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4"
dependencies = [
"bytes",
"memchr",
]
[[package]]
name = "concolor"
version = "0.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "318d6c16e73b3a900eb212ad6a82fc7d298c5ab8184c7a9998646455bc474a16"
dependencies = [
"bitflags",
"concolor-query",
"is-terminal",
]
[[package]]
name = "concolor-query"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82a90734b3d5dcf656e7624cca6bce9c3a90ee11f900e80141a7427ccfb3d317"
[[package]]
name = "content_inspector"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7bda66e858c683005a53a9a60c69a4aca7eeaa45d124526e389f7aec8e62f38"
dependencies = [
"memchr",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if",
]
[[package]]
name = "dunce"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c"
[[package]]
name = "either"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "escargot"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5584ba17d7ab26a8a7284f13e5bd196294dd2f2d79773cff29b9e9edef601a6"
dependencies = [
"log",
"once_cell",
"serde",
"serde_json",
]
[[package]]
name = "fastrand"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
dependencies = [
"instant",
]
[[package]]
name = "filetime"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"windows-sys",
]
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "heck"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "humantime-serde"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a3db5ea5923d99402c94e9feb261dc5ee9b4efa158b0315f788cf549cc200c"
dependencies = [
"humantime",
"serde",
]
[[package]]
name = "indexmap"
version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "io-lifetimes"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "is-terminal"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
dependencies = [
"hermit-abi",
"io-lifetimes",
"rustix",
"windows-sys",
]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "libc"
version = "0.2.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
[[package]]
name = "linux-raw-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
[[package]]
name = "normalize-line-endings"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
[[package]]
name = "num_cpus"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "once_cell"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
[[package]]
name = "os_pipe"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6a252f1f8c11e84b3ab59d7a488e48e4478a93937e027076638c49536204639"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "os_str_bytes"
version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"num_cpus",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
]
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "rustix"
version = "0.36.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "ryu"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "shlex"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
[[package]]
name = "similar"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf"
[[package]]
name = "snapbox"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efbd7b250c7243273b5aec4ca366fced84ad716d110bb7baae4814678952ebde"
dependencies = [
"concolor",
"content_inspector",
"dunce",
"filetime",
"libc",
"normalize-line-endings",
"os_pipe",
"similar",
"snapbox-macros",
"tempfile",
"wait-timeout",
"walkdir",
"windows-sys",
"yansi",
]
[[package]]
name = "snapbox-macros"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "485e65c1203eb37244465e857d15a26d3a85a5410648ccb53b18bd44cb3a7336"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tempfile"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
dependencies = [
"cfg-if",
"fastrand",
"libc",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]]
name = "toml_datetime"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "808b51e57d0ef8f71115d8f3a01e7d3750d01c79cac4b3eda910f4389fdf92fd"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1541ba70885967e662f69d31ab3aeca7b1aaecfcd58679590b893e9239c3646"
dependencies = [
"combine",
"indexmap",
"itertools",
"serde",
"toml_datetime",
]
[[package]]
name = "trycmd"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e381af441e13a3635303d26769620a9454aef05ec3303711efc3f1dd785a33af"
dependencies = [
"escargot",
"glob",
"humantime",
"humantime-serde",
"rayon",
"serde",
"shlex",
"snapbox",
"toml_edit",
]
[[package]]
name = "unicode-ident"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wait-timeout"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
dependencies = [
"libc",
]
[[package]]
name = "walkdir"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
dependencies = [
"same-file",
"winapi",
"winapi-util",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
[[package]]
name = "yansi"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"

13
circ_opt/Cargo.toml Normal file
View File

@@ -0,0 +1,13 @@
[package]
name = "circ_opt"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = { version = "4", features = ["derive", "env"] }
[dev-dependencies]
trycmd = { version = "0.14", features = ["examples"] }
heck = "0.4"

491
circ_opt/README.md Normal file
View File

@@ -0,0 +1,491 @@
Basic option system for CirC.
## Tests ([`trycmd`](https://docs.rs/trycmd/latest/trycmd/index.html))
These tests are based on the example binary in `examples/parser.rs`.
It contains a `clap::Parser` that simply includes `CircOpt`:
```rust
use clap::Parser;
use circ_opt::CircOpt;
#[derive(Parser, Debug)]
struct BinaryOpt {
#[command(flatten)]
pub circ: CircOpt,
}
fn main() {
let opt = BinaryOpt::parse();
println!("{:#?}", opt);
}
```
### Help Messages
```console
$ parser --help
? 0
Options that configure CirC
Usage: parser [OPTIONS]
Options:
--r1cs-verified <VERIFIED>
Use the verified field-blaster
[env: R1CS_VERIFIED=]
[default: false]
[possible values: true, false]
--r1cs-div-by-zero <DIV_BY_ZERO>
Which field division-by-zero semantics to encode in R1cs
[env: R1CS_DIV_BY_ZERO=]
[default: incomplete]
Possible values:
- incomplete: Division-by-zero renders the circuit incomplete
- zero: Division-by-zero gives zero
- non-det: Division-by-zero gives a per-division unspecified result
--r1cs-lc-elim-thresh <LC_ELIM_THRESH>
linear combination constraints up to this size will be eliminated
[env: R1CS_LC_ELIM_THRESH=]
[default: 50]
--field-builtin <BUILTIN>
Which field to use
[env: FIELD_BUILTIN=]
[default: bls12381]
Possible values:
- bls12381: BLS12-381 scalar field
- bn254: BN-254 scalar field
--field-custom-modulus <CUSTOM_MODULUS>
Which modulus to use (overrides [FieldOpt::builtin])
[env: FIELD_CUSTOM_MODULUS=]
[default: ]
--zsharp-isolate-asserts <ISOLATE_ASSERTS>
In Z#, "isolate" assertions. That is, assertions in if/then/else expressions only take effect if that branch is active.
See `--branch-isolation` in [ZoKrates](https://zokrates.github.io/language/control_flow.html).
[env: ZSHARP_ISOLATE_ASSERTS=]
[default: false]
[possible values: true, false]
--datalog-rec-limit <N>
How many recursions to allow
[env: DATALOG_REC_LIMIT=]
[default: 5]
--datalog-lint-prim-rec <LINT_PRIM_REC>
Lint recursions that are allegedly primitive recursive
[env: DATALOG_LINT_PRIM_REC=]
[default: false]
[possible values: true, false]
-h, --help
Print help information (use `-h` for a summary)
```
```console
$ parser -h
? 0
Options that configure CirC
Usage: parser [OPTIONS]
Options:
--r1cs-verified <VERIFIED>
Use the verified field-blaster [env: R1CS_VERIFIED=] [default: false] [possible values: true, false]
--r1cs-div-by-zero <DIV_BY_ZERO>
Which field division-by-zero semantics to encode in R1cs [env: R1CS_DIV_BY_ZERO=] [default: incomplete] [possible values: incomplete, zero, non-det]
--r1cs-lc-elim-thresh <LC_ELIM_THRESH>
linear combination constraints up to this size will be eliminated [env: R1CS_LC_ELIM_THRESH=] [default: 50]
--field-builtin <BUILTIN>
Which field to use [env: FIELD_BUILTIN=] [default: bls12381] [possible values: bls12381, bn254]
--field-custom-modulus <CUSTOM_MODULUS>
Which modulus to use (overrides [FieldOpt::builtin]) [env: FIELD_CUSTOM_MODULUS=] [default: ]
--zsharp-isolate-asserts <ISOLATE_ASSERTS>
In Z#, "isolate" assertions. That is, assertions in if/then/else expressions only take effect if that branch is active [env: ZSHARP_ISOLATE_ASSERTS=] [default: false] [possible values: true, false]
--datalog-rec-limit <N>
How many recursions to allow [env: DATALOG_REC_LIMIT=] [default: 5]
--datalog-lint-prim-rec <LINT_PRIM_REC>
Lint recursions that are allegedly primitive recursive [env: DATALOG_LINT_PRIM_REC=] [default: false] [possible values: true, false]
-h, --help
Print help information (use `--help` for more detail)
```
### Defaults
```console
$ parser
? 0
BinaryOpt {
circ: CircOpt {
r1cs: R1csOpt {
verified: false,
div_by_zero: Incomplete,
lc_elim_thresh: 50,
},
field: FieldOpt {
builtin: Bls12381,
custom_modulus: "",
},
zsharp: ZsharpOpt {
isolate_asserts: false,
},
datalog: DatalogOpt {
rec_limit: 5,
lint_prim_rec: false,
},
},
}
```
### R1CS Options
```console
$ parser --r1cs-verified true
? 0
BinaryOpt {
circ: CircOpt {
r1cs: R1csOpt {
verified: true,
div_by_zero: Incomplete,
lc_elim_thresh: 50,
},
field: FieldOpt {
builtin: Bls12381,
custom_modulus: "",
},
zsharp: ZsharpOpt {
isolate_asserts: false,
},
datalog: DatalogOpt {
rec_limit: 5,
lint_prim_rec: false,
},
},
}
```
```console
$ parser --r1cs-verified false
? 0
BinaryOpt {
circ: CircOpt {
r1cs: R1csOpt {
verified: false,
div_by_zero: Incomplete,
lc_elim_thresh: 50,
},
field: FieldOpt {
builtin: Bls12381,
custom_modulus: "",
},
zsharp: ZsharpOpt {
isolate_asserts: false,
},
datalog: DatalogOpt {
rec_limit: 5,
lint_prim_rec: false,
},
},
}
```
```console
$ parser --r1cs-div-by-zero non-det
? 0
BinaryOpt {
circ: CircOpt {
r1cs: R1csOpt {
verified: false,
div_by_zero: NonDet,
lc_elim_thresh: 50,
},
field: FieldOpt {
builtin: Bls12381,
custom_modulus: "",
},
zsharp: ZsharpOpt {
isolate_asserts: false,
},
datalog: DatalogOpt {
rec_limit: 5,
lint_prim_rec: false,
},
},
}
```
```console
$ parser --r1cs-div-by-zero incomplete
? 0
BinaryOpt {
circ: CircOpt {
r1cs: R1csOpt {
verified: false,
div_by_zero: Incomplete,
lc_elim_thresh: 50,
},
field: FieldOpt {
builtin: Bls12381,
custom_modulus: "",
},
zsharp: ZsharpOpt {
isolate_asserts: false,
},
datalog: DatalogOpt {
rec_limit: 5,
lint_prim_rec: false,
},
},
}
```
```console
$ parser --r1cs-div-by-zero zero
? 0
BinaryOpt {
circ: CircOpt {
r1cs: R1csOpt {
verified: false,
div_by_zero: Zero,
lc_elim_thresh: 50,
},
field: FieldOpt {
builtin: Bls12381,
custom_modulus: "",
},
zsharp: ZsharpOpt {
isolate_asserts: false,
},
datalog: DatalogOpt {
rec_limit: 5,
lint_prim_rec: false,
},
},
}
```
```console
$ R1CS_DIV_BY_ZERO=non-det parser --r1cs-lc-elim-thresh 11
? 0
BinaryOpt {
circ: CircOpt {
r1cs: R1csOpt {
verified: false,
div_by_zero: NonDet,
lc_elim_thresh: 11,
},
field: FieldOpt {
builtin: Bls12381,
custom_modulus: "",
},
zsharp: ZsharpOpt {
isolate_asserts: false,
},
datalog: DatalogOpt {
rec_limit: 5,
lint_prim_rec: false,
},
},
}
```
```console
$ R1CS_VERIFIED=true R1CS_LC_ELIM_THRESH=10 parser
? 0
BinaryOpt {
circ: CircOpt {
r1cs: R1csOpt {
verified: true,
div_by_zero: Incomplete,
lc_elim_thresh: 10,
},
field: FieldOpt {
builtin: Bls12381,
custom_modulus: "",
},
zsharp: ZsharpOpt {
isolate_asserts: false,
},
datalog: DatalogOpt {
rec_limit: 5,
lint_prim_rec: false,
},
},
}
```
### Field Options
```console
$ FIELD_CUSTOM_MODULUS=7 parser --field-builtin bn254
? 0
BinaryOpt {
circ: CircOpt {
r1cs: R1csOpt {
verified: false,
div_by_zero: Incomplete,
lc_elim_thresh: 50,
},
field: FieldOpt {
builtin: Bn254,
custom_modulus: "7",
},
zsharp: ZsharpOpt {
isolate_asserts: false,
},
datalog: DatalogOpt {
rec_limit: 5,
lint_prim_rec: false,
},
},
}
```
```console
$ FIELD_BUILTIN=bn254 parser --field-custom-modulus 7
? 0
BinaryOpt {
circ: CircOpt {
r1cs: R1csOpt {
verified: false,
div_by_zero: Incomplete,
lc_elim_thresh: 50,
},
field: FieldOpt {
builtin: Bn254,
custom_modulus: "7",
},
zsharp: ZsharpOpt {
isolate_asserts: false,
},
datalog: DatalogOpt {
rec_limit: 5,
lint_prim_rec: false,
},
},
}
```
### Z# Options
```console
$ ZSHARP_ISOLATE_ASSERTS=true parser
? 0
BinaryOpt {
circ: CircOpt {
r1cs: R1csOpt {
verified: false,
div_by_zero: Incomplete,
lc_elim_thresh: 50,
},
field: FieldOpt {
builtin: Bls12381,
custom_modulus: "",
},
zsharp: ZsharpOpt {
isolate_asserts: true,
},
datalog: DatalogOpt {
rec_limit: 5,
lint_prim_rec: false,
},
},
}
```
```console
$ parser --zsharp-isolate-asserts true
? 0
BinaryOpt {
circ: CircOpt {
r1cs: R1csOpt {
verified: false,
div_by_zero: Incomplete,
lc_elim_thresh: 50,
},
field: FieldOpt {
builtin: Bls12381,
custom_modulus: "",
},
zsharp: ZsharpOpt {
isolate_asserts: true,
},
datalog: DatalogOpt {
rec_limit: 5,
lint_prim_rec: false,
},
},
}
```
### Datalog Options
```console
$ DATALOG_LINT_PRIM_REC=true parser --datalog-rec-limit 10
? 0
BinaryOpt {
circ: CircOpt {
r1cs: R1csOpt {
verified: false,
div_by_zero: Incomplete,
lc_elim_thresh: 50,
},
field: FieldOpt {
builtin: Bls12381,
custom_modulus: "",
},
zsharp: ZsharpOpt {
isolate_asserts: false,
},
datalog: DatalogOpt {
rec_limit: 10,
lint_prim_rec: true,
},
},
}
```
```console
$ DATALOG_REC_LIMIT=15 parser --datalog-lint-prim-rec true
? 0
BinaryOpt {
circ: CircOpt {
r1cs: R1csOpt {
verified: false,
div_by_zero: Incomplete,
lc_elim_thresh: 50,
},
field: FieldOpt {
builtin: Bls12381,
custom_modulus: "",
},
zsharp: ZsharpOpt {
isolate_asserts: false,
},
datalog: DatalogOpt {
rec_limit: 15,
lint_prim_rec: true,
},
},
}
```

View File

@@ -0,0 +1,13 @@
use circ_opt::CircOpt;
use clap::Parser;
#[derive(Parser, Debug)]
struct BinaryOpt {
#[command(flatten)]
pub circ: CircOpt,
}
fn main() {
let opt = BinaryOpt::parse();
println!("{:#?}", opt);
}

244
circ_opt/src/lib.rs Normal file
View File

@@ -0,0 +1,244 @@
//! Options for CirC.
//!
//! ## Contents
//!
//! * A type for circ options [CircOpt] containing fields for module options:
//! * `r1cs`: [R1csOpt]
//! * `datalog`: [DatalogOpt]
//! * `zsharp`: [ZsharpOpt]
//! * `field`: [FieldOpt]
//! * all options types implement:
//! * std's [Default]
//! * clap's [Args]; all options are settable by
//! * environmental variable (SHOUTY_SNEK_CASE), e.g., `"R1CS_LC_ELIM_THRESH"`
//! * long option (kebab-case), e.g., `"--r1cs-lc-elim-thresh"`
//! * these a guaranteed to agree (and we test this)
//!
//! ## Constructing custom options in a compiler
//!
//! We recommend that compilers construct custom options using [`clap`][clap].
//! Simply use our (rexported) version of clap in your compiler ([crate::clap])
//! and include [CircOpt] in your [clap::Parser].
//!
//! ```rust
//! use circ_opt::{CircOpt, clap::Parser};
//!
//! #[derive(Parser, Debug)]
//! struct BinaryOpt {
//! #[command(flatten)]
//! pub circ: CircOpt,
//! }
//!
//! fn main() {
//! let opt = BinaryOpt::parse();
//! }
//! ```
//!
//! [clap]: https://crates.io/crates/clap
use clap::{ArgAction, Args, ValueEnum};
use std::default::Default;
/// Re-export our version of clap.
pub use clap;
#[derive(Args, Debug, Clone, Default, PartialEq, Eq)]
/// Options that configure CirC
pub struct CircOpt {
/// Options for the R1cs backend
#[command(flatten)]
pub r1cs: R1csOpt,
/// Options for the prime field used
#[command(flatten)]
pub field: FieldOpt,
/// Options for the Z# frontend
#[command(flatten)]
pub zsharp: ZsharpOpt,
/// Options for the datalog frontend
#[command(flatten)]
pub datalog: DatalogOpt,
}
/// Options for the R1cs backend
#[derive(Args, Debug, Clone, PartialEq, Eq)]
pub struct R1csOpt {
/// Use the verified field-blaster
#[arg(long = "r1cs-verified", env = "R1CS_VERIFIED", action = ArgAction::Set, default_value = "false")]
pub verified: bool,
/// Which field division-by-zero semantics to encode in R1cs
#[arg(
long = "r1cs-div-by-zero",
env = "R1CS_DIV_BY_ZERO",
value_enum,
default_value = "incomplete"
)]
pub div_by_zero: FieldDivByZero,
#[arg(
long = "r1cs-lc-elim-thresh",
env = "R1CS_LC_ELIM_THRESH",
default_value = "50"
)]
/// linear combination constraints up to this size will be eliminated
pub lc_elim_thresh: usize,
}
impl Default for R1csOpt {
fn default() -> Self {
Self {
verified: false,
div_by_zero: FieldDivByZero::Incomplete,
lc_elim_thresh: 50,
}
}
}
#[derive(ValueEnum, Debug, PartialEq, Eq, Clone, Copy)]
/// Which field division-by-zero semantics to encode in R1cs
pub enum FieldDivByZero {
/// Division-by-zero renders the circuit incomplete
Incomplete,
/// Division-by-zero gives zero
Zero,
/// Division-by-zero gives a per-division unspecified result
NonDet,
}
impl Default for FieldDivByZero {
fn default() -> Self {
FieldDivByZero::Incomplete
}
}
/// Options for the prime field used
#[derive(Args, Debug, Default, Clone, PartialEq, Eq)]
pub struct FieldOpt {
/// Which field to use
#[arg(
long = "field-builtin",
env = "FIELD_BUILTIN",
value_enum,
default_value = "bls12381"
)]
pub builtin: BuiltinField,
/// Which modulus to use (overrides [FieldOpt::builtin])
#[arg(
long = "field-custom-modulus",
env = "FIELD_CUSTOM_MODULUS",
default_value = ""
)]
pub custom_modulus: String,
}
#[derive(ValueEnum, Debug, PartialEq, Eq, Clone, Copy)]
/// Which field to use
pub enum BuiltinField {
/// BLS12-381 scalar field
Bls12381,
/// BN-254 scalar field
Bn254,
}
impl Default for BuiltinField {
fn default() -> Self {
BuiltinField::Bls12381
}
}
/// Options for the datalog frontend
#[derive(Args, Debug, Default, Clone, PartialEq, Eq)]
pub struct ZsharpOpt {
/// In Z#, "isolate" assertions. That is, assertions in if/then/else expressions only take
/// effect if that branch is active.
///
/// See `--branch-isolation` in
/// [ZoKrates](https://zokrates.github.io/language/control_flow.html).
#[arg(long = "zsharp-isolate-asserts", env = "ZSHARP_ISOLATE_ASSERTS", action = ArgAction::Set, default_value = "false")]
pub isolate_asserts: bool,
}
/// Options for the datalog frontend
#[derive(Args, Debug, Clone, PartialEq, Eq)]
pub struct DatalogOpt {
/// How many recursions to allow
#[arg(
long = "datalog-rec-limit",
env = "DATALOG_REC_LIMIT",
name = "N",
default_value = "5"
)]
pub rec_limit: usize,
/// Lint recursions that are allegedly primitive recursive
#[arg(long = "datalog-lint-prim-rec", env = "DATALOG_LINT_PRIM_REC", action = ArgAction::Set, default_value = "false")]
pub lint_prim_rec: bool,
}
impl Default for DatalogOpt {
fn default() -> Self {
Self {
rec_limit: 5,
lint_prim_rec: false,
}
}
}
#[cfg(test)]
mod test {
use super::*;
use clap::{CommandFactory, Parser};
use heck::{ToKebabCase, ToShoutySnekCase};
#[derive(Parser, Debug)]
struct BinaryOpt {
#[command(flatten)]
pub circ: CircOpt,
}
#[test]
fn std_and_clap_defaults_agree() {
let std_default: CircOpt = Default::default();
let clap_default: CircOpt = BinaryOpt::parse_from::<_, &str>(std::iter::empty()).circ;
assert_eq!(std_default, clap_default);
}
#[test]
fn long_and_env_names_agree() {
for arg in BinaryOpt::command().get_arguments() {
if let Some(long_name) = arg.get_long() {
if let Some(env_name) = arg.get_env() {
let env_name = env_name.to_str().unwrap();
assert_eq!(
env_name,
long_name.TO_SHOUTY_SNEK_CASE(),
"The long name\n '{}'\ndoes not match the envvar name\n '{}'\n",
long_name,
env_name,
);
assert_eq!(
env_name,
env_name.TO_SHOUTY_SNEK_CASE(),
"The envvar name '{}' is not in SHOUTY_SNEK_CASE",
env_name,
);
assert_eq!(
long_name,
long_name.to_kebab_case(),
"The long name '{}' is not in kebab-case",
long_name,
);
} else {
panic!("Long option '{}' has no envvar", long_name);
}
} else if let Some(env_name) = arg.get_env() {
let env_name = env_name.to_str().unwrap();
panic!("Envar option '{}' has no long_name", env_name);
}
}
}
}

6
circ_opt/tests/trycmd.rs Normal file
View File

@@ -0,0 +1,6 @@
#[test]
fn trycmd() {
trycmd::TestCases::new()
.register_bins(trycmd::cargo::compile_examples([]).unwrap())
.case("README.md");
}

189
driver.py
View File

@@ -7,6 +7,16 @@ import sys
from util import *
def log_run_check(cmd):
s = (
" ".join(f"'{tok}'" if " " in tok else tok for tok in cmd)
if type(cmd) == list
else cmd
)
print(f"Running: {s}")
return subprocess.run(cmd, check=True)
def install(features):
"""
Used for installing third party libraries
@@ -16,7 +26,7 @@ def install(features):
features : set of str
set of features required
"""
def verify_path_empty(path) -> bool:
return not os.path.isdir(path) or (os.path.isdir(path) and not os.listdir(path))
@@ -24,7 +34,8 @@ def install(features):
if f == "aby":
if verify_path_empty(ABY_SOURCE):
subprocess.run(
["git", "clone", "https://github.com/edwjchen/ABY.git", ABY_SOURCE])
["git", "clone", "https://github.com/edwjchen/ABY.git", ABY_SOURCE]
)
subprocess.run(["./scripts/build_aby.zsh"])
# install python requirements
@@ -45,8 +56,9 @@ def check(features):
cargo_features = filter_cargo_features(features)
if cargo_features:
cmd = cmd + ["--features"] + cargo_features
if "ristretto255" in features: cmd = cmd + ["--no-default-features"]
subprocess.run(cmd, check=True)
if "ristretto255" in features:
cmd = cmd + ["--no-default-features"]
log_run_check(cmd)
def build(features):
@@ -65,7 +77,7 @@ def build(features):
cmd = ["cargo", "build"]
if mode:
cmd += ["--"+mode]
cmd += ["--" + mode]
else:
# default to release mode
cmd += ["--release"]
@@ -74,18 +86,17 @@ def build(features):
cargo_features = filter_cargo_features(features)
if cargo_features:
cmd = cmd + ["--features"] + cargo_features
if "ristretto255" in features: cmd = cmd + ["--no-default-features"]
if "ristretto255" in features:
cmd = cmd + ["--no-default-features"]
print(cmd)
subprocess.run(cmd, check=True)
log_run_check(cmd)
if "aby" in features:
if "c" in features:
subprocess.run(["./scripts/build_mpc_c_test.zsh"], check=True)
log_run_check(["./scripts/build_mpc_c_test.zsh"])
if "smt" in features and "zok" in features:
subprocess.run(
["./scripts/build_mpc_zokrates_test.zsh"], check=True)
subprocess.run(["./scripts/build_aby.zsh"], check=True)
log_run_check(["./scripts/build_mpc_zokrates_test.zsh"])
log_run_check(["./scripts/build_aby.zsh"])
def test(features, extra_args):
@@ -113,34 +124,33 @@ def test(features, extra_args):
test_cmd += ["--no-default-features"]
test_cmd_release += ["--no-default-features"]
if len(extra_args) > 0:
test_cmd += ["--"] + extra_args
test_cmd_release += ["--"] + extra_args
test_cmd += extra_args
test_cmd_release += extra_args
subprocess.run(test_cmd, check=True)
log_run_check(test_cmd)
if load_mode() == "release":
subprocess.run(test_cmd_release, check=True)
log_run_check(test_cmd_release)
if "r1cs" in features and "smt" in features:
subprocess.run(["./scripts/test_datalog.zsh"], check=True)
log_run_check(["./scripts/test_datalog.zsh"])
if "zok" in features and "smt" in features:
if "aby" in features:
subprocess.run(
["python3", "./scripts/aby_tests/zokrates_test_aby.py"], check=True)
log_run_check(["python3", "./scripts/aby_tests/zokrates_test_aby.py"])
if "lp" in features:
subprocess.run(["./scripts/test_zok_to_ilp.zsh"], check=True)
log_run_check(["./scripts/test_zok_to_ilp.zsh"])
if "r1cs" in features:
if "ristretto255" in features: # spartan field
subprocess.run(["./scripts/spartan_zok_test.zsh"], check=True)
else: # bellman field
subprocess.run(["./scripts/zokrates_test.zsh"], check=True)
if "ristretto255" in features: # spartan field
log_run_check(["./scripts/spartan_zok_test.zsh"])
else: # bellman field
log_run_check(["./scripts/zokrates_test.zsh"])
if "lp" in features and "r1cs" in features:
subprocess.run(["./scripts/test_zok_to_ilp_pf.zsh"], check=True)
log_run_check(["./scripts/test_zok_to_ilp_pf.zsh"])
if "c" in features:
if "aby" in features:
subprocess.run(
["python3", "./scripts/aby_tests/c_test_aby.py"], check=True)
log_run_check(["python3", "./scripts/aby_tests/c_test_aby.py"])
def benchmark(features):
mode = load_mode()
@@ -150,7 +160,7 @@ def benchmark(features):
cmd = ["cargo", "build"]
if mode:
cmd += ["--"+mode]
cmd += ["--" + mode]
else:
# default to release mode
cmd += ["--release"]
@@ -159,13 +169,14 @@ def benchmark(features):
cargo_features = filter_cargo_features(features)
if cargo_features:
cmd = cmd + ["--features"] + cargo_features
if "ristretto255" in features: cmd = cmd + ["--no-default-features"]
subprocess.run(cmd, check=True)
if "ristretto255" in features:
cmd = cmd + ["--no-default-features"]
log_run_check(cmd)
def format():
print("formatting!")
subprocess.run(["cargo", "fmt", "--all"], check=True)
log_run_check(["cargo", "fmt", "--all"])
def lint():
@@ -183,8 +194,9 @@ def lint():
cargo_features = filter_cargo_features(features)
if cargo_features:
cmd = cmd + ["--features"] + cargo_features
if "ristretto255" in features: cmd = cmd + ["--no-default-features"]
subprocess.run(cmd, check=True)
if "ristretto255" in features:
cmd = cmd + ["--no-default-features"]
log_run_check(cmd)
def flamegraph(features, extra):
@@ -192,26 +204,29 @@ def flamegraph(features, extra):
cargo_features = filter_cargo_features(features)
if cargo_features:
cmd = cmd + ["--features"] + cargo_features
if "ristretto255" in features: cmd = cmd + ["--no-default-features"]
if "ristretto255" in features:
cmd = cmd + ["--no-default-features"]
cmd += extra
print("running:", " ".join(cmd))
subprocess.run(cmd, check=True)
log_run_check(cmd)
def clean(features):
print("cleaning!")
if "aby" in features:
subprocess.run(["./scripts/clean_aby.zsh"])
subprocess.run(["rm", "-rf", "scripts/aby_tests/__pycache__"])
subprocess.run(["rm", "-rf", "P", "V", "pi",
"perf.data perf.data.old flamegraph.svg"])
log_run_check(["./scripts/clean_aby.zsh"])
log_run_check(["rm", "-rf", "scripts/aby_tests/__pycache__"])
log_run_check(
["rm", "-rf", "P", "V", "pi", "perf.data perf.data.old flamegraph.svg"]
)
log_run_check(["cargo", "clean"])
def set_mode(mode):
def verify_mode(mode):
if mode not in ("debug", "release"):
raise RuntimeError(
f"Unknown mode: {mode}, --mode <debug, release>")
raise RuntimeError(f"Unknown mode: {mode}, --mode <debug, release>")
verify_mode(mode)
save_mode(mode)
@@ -233,6 +248,7 @@ def set_features(features):
if f in valid_features | {"ristretto255"}:
return True
return False
features = set(sorted([f for f in features if verify_feature(f)]))
save_features(features)
print("Feature set:", sorted(list(features)))
@@ -246,48 +262,83 @@ def format_sub_process_cmd(r: subprocess.CalledProcessError) -> str:
if __name__ == "__main__":
try:
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--install", action="store_true",
help="install all dependencies from the feature set")
parser.add_argument(
"-c", "--check", action="store_true", help="run `cargo check`")
parser.add_argument("-b", "--build", action="store_true",
help="run `cargo build` and build all dependencies from the feature set")
parser.add_argument("-t", "--test", action="store_true",
help="build and test all dependencies from the feature set")
"-i",
"--install",
action="store_true",
help="install all dependencies from the feature set",
)
parser.add_argument(
"-f", "--format", action="store_true", help="run `cargo fmt --all`")
"-c", "--check", action="store_true", help="run `cargo check`"
)
parser.add_argument(
"-l", "--lint", action="store_true", help="run `cargo clippy`")
parser.add_argument("--flamegraph", action="store_true",
help="run `cargo flamegraph`")
parser.add_argument("-C", "--clean", action="store_true",
help="remove all generated files")
parser.add_argument("-m", "--mode", type=str,
help="set `debug` or `release` mode")
parser.add_argument("-A", "--all_features",
action="store_true", help="set all features on")
parser.add_argument("-L", "--list_features",
action="store_true", help="print active features")
parser.add_argument("-F", "--features", nargs="+",
help="set features on <aby, c, lp, r1cs, smt, zok>, reset features with -F none")
"-b",
"--build",
action="store_true",
help="run `cargo build` and build all dependencies from the feature set",
)
parser.add_argument(
"--benchmark", action="store_true", help="build benchmarks")
parser.add_argument("extra", metavar="PASS_THROUGH_ARGS", nargs=argparse.REMAINDER,
help="Extra arguments for --flamegraph. Prefix with --")
"-t",
"--test",
action="store_true",
help="build and test all dependencies from the feature set",
)
parser.add_argument(
"-f", "--format", action="store_true", help="run `cargo fmt --all`"
)
parser.add_argument(
"-l", "--lint", action="store_true", help="run `cargo clippy`"
)
parser.add_argument(
"--flamegraph", action="store_true", help="run `cargo flamegraph`"
)
parser.add_argument(
"-C", "--clean", action="store_true", help="remove all generated files"
)
parser.add_argument(
"-m", "--mode", type=str, help="set `debug` or `release` mode"
)
parser.add_argument(
"-A", "--all_features", action="store_true", help="set all features on"
)
parser.add_argument(
"-L", "--list_features", action="store_true", help="print active features"
)
parser.add_argument(
"-F",
"--features",
nargs="+",
help="set features on <aby, c, lp, r1cs, smt, zok>, reset features with -F none",
)
parser.add_argument("--benchmark", action="store_true", help="build benchmarks")
parser.add_argument(
"extra",
metavar="PASS_THROUGH_ARGS",
nargs=argparse.REMAINDER,
help="Extra arguments for --flamegraph. Prefix with --",
)
args = parser.parse_args()
def verify_single_action(args: argparse.Namespace):
actions = [k for k, v in vars(args).items() if (
type(v) is bool or k in ["features", "mode"]) and bool(v)]
actions = [
k
for k, v in vars(args).items()
if (type(v) is bool or k in ["features", "mode"]) and bool(v)
]
if len(actions) != 1:
parser.error(
"parser error: only one action can be specified. got: " + " ".join(actions))
"parser error: only one action can be specified. got: "
+ " ".join(actions)
)
verify_single_action(args)
def verify_extra_implies_flamegraph_or_test(args: argparse.Namespace):
if (not args.flamegraph and not args.test) and len(args.extra) > 0:
parser.error(
"parser error: no --flamegraph or --test action, and extra arguments")
"parser error: no --flamegraph or --test action, and extra arguments"
)
verify_extra_implies_flamegraph_or_test(args)
features = load_features()

View File

@@ -9,6 +9,11 @@ use bellman::groth16::{
#[cfg(feature = "r1cs")]
use bellman::Circuit;
use bls12_381::{Bls12, Scalar};
use circ::cfg::{
cfg,
clap::{self, Args, Parser, Subcommand, ValueEnum},
CircOpt,
};
#[cfg(feature = "c")]
use circ::front::c::{self, C};
use circ::front::datalog::{self, Datalog};
@@ -35,7 +40,6 @@ use circ::target::r1cs::spartan::write_data;
use circ::target::r1cs::trans::to_r1cs;
#[cfg(feature = "smt")]
use circ::target::smt::find_model;
use circ::util::field::DFL_T;
use circ_fields::FieldT;
use fxhash::FxHashMap as HashMap;
#[cfg(feature = "lp")]
@@ -44,87 +48,69 @@ use std::fs::File;
use std::io::Read;
use std::io::Write;
use std::path::{Path, PathBuf};
use structopt::clap::arg_enum;
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
#[structopt(name = "circ", about = "CirC: the circuit compiler")]
#[derive(Debug, Parser)]
#[command(name = "circ", about = "CirC: the circuit compiler")]
struct Options {
/// Input file
#[structopt(parse(from_os_str), name = "PATH")]
#[arg(name = "PATH")]
path: PathBuf,
#[structopt(flatten)]
#[command(flatten)]
frontend: FrontendOptions,
#[command(flatten)]
circ: CircOpt,
/// Number of parties for an MPC.
#[structopt(long, default_value = "2", name = "PARTIES")]
#[arg(long, default_value = "2", name = "PARTIES")]
parties: u8,
#[structopt(subcommand)]
backend: Backend,
}
#[derive(Debug, StructOpt)]
#[derive(Debug, Args)]
struct FrontendOptions {
/// Input language
#[structopt(long, default_value = "auto", name = "LANG")]
#[arg(long, default_value = "auto", name = "LANG")]
language: Language,
/// Value threshold
#[structopt(long)]
#[arg(long)]
value_threshold: Option<u64>,
/// How many recursions to allow (datalog)
#[structopt(short, long, name = "N", default_value = "5")]
rec_limit: usize,
/// Lint recursions that are allegedly primitive recursive (datalog)
#[structopt(long)]
lint_prim_rec: bool,
#[cfg(feature = "zok")]
/// In Z#, "isolate" assertions. That is, assertions in if/then/else expressions only take
/// effect if that branch is active.
///
/// See `--branch-isolation` in
/// [ZoKrates](https://zokrates.github.io/language/control_flow.html).
#[structopt(long)]
z_isolate_asserts: bool,
}
#[derive(Debug, StructOpt)]
#[derive(Debug, Subcommand)]
enum Backend {
#[allow(dead_code)]
R1cs {
#[structopt(long, default_value = "P", parse(from_os_str))]
#[arg(long, default_value = "P")]
prover_key: PathBuf,
#[structopt(long, default_value = "V", parse(from_os_str))]
#[arg(long, default_value = "V")]
verifier_key: PathBuf,
#[structopt(long, default_value = "50")]
#[arg(long, default_value = "50")]
/// linear combination constraints up to this size will be eliminated
lc_elimination_thresh: usize,
#[structopt(long, default_value = "count")]
#[arg(long, default_value = "count")]
action: ProofAction,
},
Smt {},
Ilp {},
Mpc {
#[structopt(long, default_value = "hycc", name = "cost_model")]
#[arg(long, default_value = "hycc", name = "cost_model")]
cost_model: String,
#[structopt(long, default_value = "lp", name = "selection_scheme")]
#[arg(long, default_value = "lp", name = "selection_scheme")]
selection_scheme: String,
},
}
arg_enum! {
#[derive(PartialEq, Eq, Debug)]
enum Language {
Zsharp,
Datalog,
C,
Auto,
}
#[derive(PartialEq, Eq, Debug, Clone, ValueEnum)]
enum Language {
Zsharp,
Datalog,
C,
Auto,
}
#[derive(PartialEq, Eq, Debug)]
@@ -140,13 +126,11 @@ pub enum CostModelType {
Hycc,
}
arg_enum! {
#[derive(PartialEq, Eq, Debug)]
enum ProofAction {
Count,
Setup,
SpartanSetup,
}
#[derive(PartialEq, Eq, Debug, Clone, ValueEnum)]
enum ProofAction {
Count,
Setup,
SpartanSetup,
}
fn determine_language(l: &Language, input_path: &Path) -> DeterminedLanguage {
@@ -175,7 +159,8 @@ fn main() {
.format_level(false)
.format_timestamp(None)
.init();
let options = Options::from_args();
let options = Options::parse();
circ::cfg::set(&options.circ);
let path_buf = options.path.clone();
println!("{:?}", options);
let mode = match options.backend {
@@ -194,7 +179,6 @@ fn main() {
let inputs = zsharp::Inputs {
file: options.path,
mode,
isolate_asserts: options.frontend.z_isolate_asserts,
};
ZSharpFE::gen(inputs)
}
@@ -203,11 +187,7 @@ fn main() {
panic!("Missing feature: smt,zok");
}
DeterminedLanguage::Datalog => {
let inputs = datalog::Inputs {
file: options.path,
rec_limit: options.frontend.rec_limit,
lint_prim_rec: options.frontend.lint_prim_rec,
};
let inputs = datalog::Inputs { file: options.path };
Datalog::gen(inputs)
}
#[cfg(feature = "c")]
@@ -285,15 +265,13 @@ fn main() {
action,
prover_key,
verifier_key,
lc_elimination_thresh,
..
} => {
println!("Converting to r1cs");
let (r1cs, mut prover_data, verifier_data) =
to_r1cs(cs.get("main").clone(), FieldT::from(DFL_T.modulus()));
let (r1cs, mut prover_data, verifier_data) = to_r1cs(cs.get("main").clone(), cfg());
println!("Pre-opt R1cs size: {}", r1cs.constraints().len());
let r1cs = reduce_linearities(r1cs, Some(lc_elimination_thresh));
let r1cs = reduce_linearities(r1cs, cfg());
println!("Final R1cs size: {}", r1cs.constraints().len());
// save the optimized r1cs: the prover needs it to synthesize.
@@ -363,7 +341,7 @@ fn main() {
}
#[cfg(feature = "smt")]
Backend::Smt { .. } => {
if options.frontend.lint_prim_rec {
if options.circ.datalog.lint_prim_rec {
let main_comp = cs.get("main").clone();
assert_eq!(main_comp.outputs.len(), 1);
match find_model(&main_comp.outputs[0]) {

View File

@@ -1,16 +1,16 @@
use circ::cfg::clap::{self, Parser};
use circ::ir::term::*;
use circ::target::aby::assignment::ilp;
use circ::term;
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
#[structopt(
#[derive(Debug, Parser)]
#[command(
name = "opa_bench",
about = "Optimal Protocol Assignment via ILP benchmarker"
)]
struct Options {
/// Number of parties for an MPC. If missing, generates a proof circuit.
#[structopt(name = "MULTS")]
#[arg(name = "MULTS")]
n_mults: u32,
}
@@ -19,7 +19,7 @@ fn main() {
.format_level(false)
.format_timestamp(None)
.init();
let options = Options::from_args();
let options = Options::parse();
let v = leaf_term(Op::Var("a".to_owned(), Sort::BitVector(32)));
let mut t = v.clone();
for _i in 0..options.n_mults {

View File

@@ -1,39 +1,36 @@
use bls12_381::Bls12;
use circ::cfg::clap::{self, Parser, ValueEnum};
use circ::ir::term::text::parse_value_map;
use circ::target::r1cs::bellman;
use circ::target::r1cs::spartan;
use std::path::PathBuf;
use structopt::clap::arg_enum;
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
#[structopt(name = "circ", about = "CirC: the circuit compiler")]
#[derive(Debug, Parser)]
#[command(name = "zk", about = "The CirC ZKP runner")]
struct Options {
#[structopt(long, default_value = "P", parse(from_os_str))]
#[arg(long, default_value = "P")]
prover_key: PathBuf,
#[structopt(long, default_value = "V", parse(from_os_str))]
#[arg(long, default_value = "V")]
verifier_key: PathBuf,
#[structopt(long, default_value = "pi", parse(from_os_str))]
#[arg(long, default_value = "pi")]
proof: PathBuf,
#[structopt(long, default_value = "in", parse(from_os_str))]
#[arg(long, default_value = "in")]
inputs: PathBuf,
#[structopt(long, default_value = "pin", parse(from_os_str))]
#[arg(long, default_value = "pin")]
pin: PathBuf,
#[structopt(long, default_value = "vin", parse(from_os_str))]
#[arg(long, default_value = "vin")]
vin: PathBuf,
#[structopt(long)]
#[arg(long)]
action: ProofAction,
}
arg_enum! {
#[derive(PartialEq, Debug)]
/// `Prove`/`Verify` execute proving/verifying in bellman separately
/// `Spartan` executes both proving/verifying in spartan
enum ProofAction {
Prove,
Verify,
Spartan,
}
#[derive(PartialEq, Debug, Clone, ValueEnum)]
/// `Prove`/`Verify` execute proving/verifying in bellman separately
/// `Spartan` executes both proving/verifying in spartan
enum ProofAction {
Prove,
Verify,
Spartan,
}
fn main() {
@@ -41,7 +38,7 @@ fn main() {
.format_level(false)
.format_timestamp(None)
.init();
let opts = Options::from_args();
let opts = Options::parse();
match opts.action {
ProofAction::Prove => {
let input_map = parse_value_map(&std::fs::read(opts.inputs).unwrap());

View File

@@ -10,74 +10,71 @@ use bls12_381::{Bls12, Scalar};
use circ::front::zsharp::{self, ZSharpFE};
use circ::front::{FrontEnd, Mode};
use circ::ir::opt::{opt, Opt};
use circ_fields::FieldT;
/*
use circ::target::r1cs::bellman::parse_instance;
*/
use circ::target::r1cs::opt::reduce_linearities;
use circ::target::r1cs::trans::to_r1cs;
use circ::util::field::DFL_T;
/*
use std::fs::File;
use std::io::Read;
use std::io::Write;
*/
use circ::cfg::{
cfg,
clap::{self, Parser, ValueEnum},
CircOpt,
};
use std::path::PathBuf;
use structopt::clap::arg_enum;
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
#[structopt(name = "zxc", about = "CirC: the circuit compiler")]
#[derive(Debug, Parser)]
#[command(name = "zxc", about = "CirC: the circuit compiler")]
struct Options {
/// Input file
#[structopt(parse(from_os_str), name = "PATH")]
#[arg(name = "PATH")]
path: PathBuf,
/*
#[structopt(long, default_value = "P", parse(from_os_str))]
#[arg(long, default_value = "P", parse(from_os_str))]
prover_key: PathBuf,
#[structopt(long, default_value = "V", parse(from_os_str))]
#[arg(long, default_value = "V", parse(from_os_str))]
verifier_key: PathBuf,
#[structopt(long, default_value = "pi", parse(from_os_str))]
#[arg(long, default_value = "pi", parse(from_os_str))]
proof: PathBuf,
#[structopt(long, default_value = "x", parse(from_os_str))]
#[arg(long, default_value = "x", parse(from_os_str))]
instance: PathBuf,
*/
#[structopt(short = "L")]
#[arg(short = 'L')]
/// skip linearity reduction entirely
skip_linred: bool,
#[structopt(long, default_value = "50")]
/// linear combination constraints up to this size will be eliminated (if the pass is enabled)
lc_elimination_thresh: usize,
#[command(flatten)]
/// CirC options
circ: CircOpt,
#[structopt(long, default_value = "count")]
#[arg(long, default_value = "count")]
action: ProofAction,
#[structopt(short = "q")]
#[arg(short = 'q')]
/// quiet mode: don't print R1CS at the end
quiet: bool,
}
arg_enum! {
#[derive(PartialEq, Debug)]
enum ProofAction {
Count,
Prove,
Setup,
Verify,
}
#[derive(PartialEq, Eq, Debug, Clone, ValueEnum)]
enum ProofAction {
Count,
Setup,
Prove,
Verify,
}
arg_enum! {
#[derive(PartialEq, Debug)]
enum ProofOption {
Count,
Prove,
}
#[derive(PartialEq, Debug, Clone, ValueEnum)]
enum ProofOption {
Count,
Prove,
}
fn main() {
@@ -85,14 +82,14 @@ fn main() {
.format_level(false)
.format_timestamp(None)
.init();
let options = Options::from_args();
let options = Options::parse();
circ::cfg::set(&options.circ);
println!("{:?}", options);
let cs = {
let inputs = zsharp::Inputs {
file: options.path,
mode: Mode::Proof,
isolate_asserts: false,
};
ZSharpFE::gen(inputs)
};
@@ -132,7 +129,7 @@ fn main() {
*/
println!("Converting to r1cs");
let (r1cs, _, _) = to_r1cs(cs.get("main").clone(), FieldT::from(DFL_T.modulus()));
let (r1cs, _, _) = to_r1cs(cs.get("main").clone(), cfg());
let r1cs = if options.skip_linred {
println!("Skipping linearity reduction, as requested.");
r1cs
@@ -141,7 +138,7 @@ fn main() {
"R1cs size before linearity reduction: {}",
r1cs.constraints().len()
);
reduce_linearities(r1cs, Some(options.lc_elimination_thresh))
reduce_linearities(r1cs, cfg())
};
println!("Final R1cs size: {}", r1cs.constraints().len());
match action {

View File

@@ -1,23 +1,22 @@
use circ::front::zsharp::{Inputs, ZSharpFE};
use circ::cfg::{
clap::{self, Parser},
CircOpt,
};
use circ::front::Mode;
use std::path::PathBuf;
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
#[structopt(name = "circ", about = "CirC: the circuit compiler")]
#[derive(Debug, Parser)]
#[command(name = "zxi", about = "The Z# interpreter")]
struct Options {
/// Input file
#[structopt(parse(from_os_str))]
#[arg()]
zsharp_path: PathBuf,
/// Number of parties for an MPC. If missing, generates a proof circuit.
#[structopt(short, long, name = "PARTIES")]
parties: Option<u8>,
/// Whether to maximize the output
#[structopt(short, long)]
maximize: bool,
#[command(flatten)]
/// CirC options
circ: CircOpt,
}
fn main() {
@@ -25,20 +24,11 @@ fn main() {
.format_level(false)
.format_timestamp(None)
.init();
let options = Options::from_args();
//println!("{:?}", options);
let mode = if options.maximize {
Mode::Opt
} else {
match options.parties {
Some(p) => Mode::Mpc(p),
None => Mode::Proof,
}
};
let options = Options::parse();
circ::cfg::set(&options.circ);
let inputs = Inputs {
file: options.zsharp_path,
mode,
isolate_asserts: false,
mode: Mode::Proof,
};
let cs = ZSharpFE::interpret(inputs);
cs.pretty(&mut std::io::stdout().lock())

View File

@@ -11,18 +11,18 @@ $BIN --language datalog ./examples/datalog/inv.pl r1cs --action count || true
$BIN --language datalog ./examples/datalog/call.pl r1cs --action count || true
$BIN --language datalog ./examples/datalog/arr.pl r1cs --action count || true
# Small R1cs b/c too little recursion.
size=$(($BIN --language datalog ./examples/datalog/dumb_hash.pl -r 4 r1cs --action count || true) | egrep "Final R1cs size:" | egrep -o "\\b[0-9]+")
size=$(($BIN --language datalog ./examples/datalog/dumb_hash.pl --datalog-rec-limit 4 r1cs --action count || true) | egrep "Final R1cs size:" | egrep -o "\\b[0-9]+")
[ "$size" -lt 10 ]
# Big R1cs b/c enough recursion
size=$(($BIN --language datalog ./examples/datalog/dumb_hash.pl -r 5 r1cs --action count || true) | egrep "Final R1cs size:" | egrep -o "\\b[0-9]+")
size=$(($BIN --language datalog ./examples/datalog/dumb_hash.pl --datalog-rec-limit 5 r1cs --action count || true) | egrep "Final R1cs size:" | egrep -o "\\b[0-9]+")
[ "$size" -gt 250 ]
size=$(($BIN --language datalog ./examples/datalog/dumb_hash.pl -r 10 r1cs --action count || true) | egrep "Final R1cs size:" | egrep -o "\\b[0-9]+")
size=$(($BIN --language datalog ./examples/datalog/dumb_hash.pl --datalog-rec-limit 10 r1cs --action count || true) | egrep "Final R1cs size:" | egrep -o "\\b[0-9]+")
[ "$size" -gt 250 ]
size=$(($BIN --language datalog ./examples/datalog/dec.pl -r 2 r1cs --action count || true) | egrep "Final R1cs size:" | egrep -o "\\b[0-9]+")
size=$(($BIN --language datalog ./examples/datalog/dec.pl --datalog-rec-limit 2 r1cs --action count || true) | egrep "Final R1cs size:" | egrep -o "\\b[0-9]+")
[ "$size" -gt 250 ]
# Test prim-rec test
$BIN --language datalog ./examples/datalog/dec.pl --lint-prim-rec smt
$BIN --language datalog ./examples/datalog/dec.pl --datalog-lint-prim-rec true smt
($BIN --language datalog ./examples/datalog/not_dec.pl --lint-prim-rec smt || true) | egrep 'Not prim'
($BIN --language datalog ./examples/datalog/not_dec.pl --datalog-lint-prim-rec true smt || true) | egrep 'Not prim'

View File

@@ -45,7 +45,7 @@ function pf_test {
# Test prove workflow with --z-isolate-asserts, given an example name
function pf_test_isolate {
ex_name=$1
$BIN --z-isolate-asserts examples/ZoKrates/pf/$ex_name.zok r1cs --action setup
$BIN --zsharp-isolate-asserts true examples/ZoKrates/pf/$ex_name.zok r1cs --action setup
$ZK_BIN --inputs examples/ZoKrates/pf/$ex_name.zok.pin --action prove
$ZK_BIN --inputs examples/ZoKrates/pf/$ex_name.zok.vin --action verify
rm -rf P V pi

109
src/cfg.rs Normal file
View File

@@ -0,0 +1,109 @@
//! CirC Configuration
//!
//! This module contains two components:
//! * A type [CircCfg] for configuration information.
//! * Static configuration storage
//! * set with [set] and [set_cfg]
//! * read with [cfg]
//! * it can only be set once per process
//! * if you want to unit-test your component, we recommend that it **should not** use [cfg].
use circ_fields::FieldT;
use once_cell::sync::OnceCell;
use rug::Integer;
use std::convert::From;
use std::default::Default;
/// Re-export our clap version
pub use circ_opt::clap;
/// Re-export our clap [clap::Args]
pub use circ_opt::CircOpt;
/// A Circ configuration. Contructible [From::from] [CircOpt].
#[derive(Clone, Debug)]
pub struct CircCfg {
opt: CircOpt,
field: FieldT,
}
/// Set the CirC configuration from a [CircOpt].
///
/// If you want to build the CirC configuration [CircCfg] object yourself,
/// you can set it with [set_cfg].
///
/// [CircOpt] implements [clap::Args], so it can be build from your command line or envvars. See
/// its documentation.
pub fn set(o: &CircOpt) {
set_cfg(From::from(o.clone()))
}
/// Set the CirC configuration to its defaults.
/// See [set] to customize
pub fn set_default() {
set_cfg(Default::default())
}
/// Set the CirC configuration from a [CircCfg].
///
/// We recommends using [set], which takes a [CircOpt] instead.
pub fn set_cfg(c: CircCfg) {
CFG.set(c).unwrap_or_else(|c| {
panic!(
"Tried to set the CirC configuration, but it had already been set.\nNew cfg:\n{:#?}",
c
)
})
}
/// Get the configuration
pub fn cfg() -> &'static CircCfg {
CFG.get().expect("A component tried to read the CirC configuration, but it was not yet set. Did the top-level application call `circ::cfg::set`?")
}
static CFG: OnceCell<CircCfg> = OnceCell::new();
impl From<CircOpt> for CircCfg {
fn from(opt: CircOpt) -> Self {
let field = if !opt.field.custom_modulus.is_empty() {
let error =
|r: &str| panic!("The field modulus '{}' is {}", &opt.field.custom_modulus, r);
let i = Integer::from_str_radix(&opt.field.custom_modulus, 10)
.unwrap_or_else(|_| error("not an integer"));
if i.is_probably_prime(30) == rug::integer::IsPrime::No {
error("not a prime");
}
FieldT::from(i)
} else {
match opt.field.builtin {
circ_opt::BuiltinField::Bls12381 => FieldT::FBls12381,
circ_opt::BuiltinField::Bn254 => FieldT::FBn254,
}
};
Self { opt, field }
}
}
impl Default for CircCfg {
fn default() -> Self {
Self::from(CircOpt::default())
}
}
/// Used to expose all fields of [CircOpt].
impl std::ops::Deref for CircCfg {
type Target = CircOpt;
fn deref(&self) -> &Self::Target {
&self.opt
}
}
/// Additional functionality
impl CircCfg {
/// The default field
pub fn field(&self) -> &FieldT {
&self.field
}
}

View File

@@ -9,6 +9,7 @@ use fxhash::FxHashMap;
use log::debug;
use rug::Integer;
use crate::cfg::cfg;
use crate::circify::{Circify, Loc, Val};
use crate::front::{PROVER_VIS, PUBLIC_VIS};
use crate::ir::opt::cfold::fold;
@@ -29,10 +30,6 @@ use parser::ast;
pub struct Inputs {
/// The file to look for `main` in.
pub file: PathBuf,
/// How many recursions to tolerate
pub rec_limit: usize,
/// Should we lint primitive recursions?
pub lint_prim_rec: bool,
}
struct Gen<'ast> {
@@ -381,7 +378,7 @@ pub struct Datalog;
impl FrontEnd for Datalog {
type Inputs = Inputs;
fn gen(i: Inputs) -> Computations {
let mut f = File::open(&i.file).unwrap();
let mut f = File::open(i.file).unwrap();
let mut buffer = String::new();
f.read_to_string(&mut buffer).unwrap();
let ast = parser::parse(&buffer);
@@ -392,9 +389,9 @@ impl FrontEnd for Datalog {
panic!("parse error!")
}
};
let mut g = Gen::new(i.rec_limit);
let mut g = Gen::new(cfg().datalog.rec_limit);
g.register_rules(&ast);
let r = if i.lint_prim_rec {
let r = if cfg().datalog.lint_prim_rec {
g.lint_rules()
} else {
g.entry_rule("main")

View File

@@ -7,9 +7,9 @@ use rug::Integer;
use super::error::ErrorKind;
use super::ty::Ty;
use crate::cfg::cfg;
use crate::circify::{CirCtx, Embeddable, Typed};
use crate::ir::term::*;
use crate::util::field::DFL_T;
/// A term
#[derive(Debug, Clone)]
@@ -63,7 +63,7 @@ pub fn pf_ir_lit<I>(i: I) -> Term
where
Integer: From<I>,
{
leaf_term(Op::Const(Value::Field(DFL_T.new_v(i))))
leaf_term(Op::Const(Value::Field(cfg().field().new_v(i))))
}
/// Initialize a boolean literal
@@ -81,10 +81,12 @@ impl Ty {
match self {
Self::Bool => Sort::Bool,
Self::Uint(w) => Sort::BitVector(*w as usize),
Self::Field => Sort::Field(DFL_T.clone()),
Self::Array(n, b) => {
Sort::Array(Box::new(Sort::Field(DFL_T.clone())), Box::new(b.sort()), *n)
}
Self::Field => Sort::Field(cfg().field().clone()),
Self::Array(n, b) => Sort::Array(
Box::new(Sort::Field(cfg().field().clone())),
Box::new(b.sort()),
*n,
),
}
}
fn default_ir_term(&self) -> Term {
@@ -316,7 +318,7 @@ pub fn or(s: &T, t: &T) -> Result<T> {
pub fn uint_to_field(s: &T) -> Result<T> {
match &s.ty {
Ty::Uint(_) => Ok(T::new(
term![Op::UbvToPf(DFL_T.clone()); s.ir.clone()],
term![Op::UbvToPf(cfg().field().clone()); s.ir.clone()],
Ty::Field,
)),
_ => Err(ErrorKind::InvalidUnOp("to_field".into(), s.clone())),
@@ -393,7 +395,3 @@ impl Datalog {
Self
}
}
// fn idx_name(struct_name: &str, idx: usize) -> String {
// format!("{}.{}", struct_name, idx)
// }

View File

@@ -5,11 +5,11 @@ mod term;
pub mod zvisit;
use super::{FrontEnd, Mode};
use crate::cfg::cfg;
use crate::circify::{CircError, Circify, Loc, Val};
use crate::front::{PROVER_VIS, PUBLIC_VIS};
use crate::ir::proof::ConstraintMetadata;
use crate::ir::term::*;
use crate::util::field::DFL_T;
use log::{debug, warn};
use rug::Integer;
@@ -32,10 +32,6 @@ pub struct Inputs {
pub file: PathBuf,
/// The mode to generate for (MPC or proof). Effects visibility.
pub mode: Mode,
/// Whether to isolate assertions.
///
/// That is, whether assertions in in-active if/then/else branches are disabled.
pub isolate_asserts: bool,
}
/// The Z# front-end. Implements [FrontEnd].
@@ -46,11 +42,11 @@ impl FrontEnd for ZSharpFE {
fn gen(i: Inputs) -> Computations {
debug!(
"Starting Z# front-end, field: {}",
Sort::Field(DFL_T.clone())
Sort::Field(cfg().field().clone())
);
let loader = parser::ZLoad::new();
let asts = loader.load(&i.file);
let mut g = ZGen::new(asts, i.mode, loader.stdlib(), i.isolate_asserts);
let mut g = ZGen::new(asts, i.mode, loader.stdlib(), cfg().zsharp.isolate_asserts);
g.visit_files();
g.file_stack_push(i.file);
g.generics_stack_push(HashMap::new());
@@ -72,7 +68,7 @@ impl ZSharpFE {
pub fn interpret(i: Inputs) -> T {
let loader = parser::ZLoad::new();
let asts = loader.load(&i.file);
let mut g = ZGen::new(asts, i.mode, loader.stdlib(), i.isolate_asserts);
let mut g = ZGen::new(asts, i.mode, loader.stdlib(), cfg().zsharp.isolate_asserts);
g.visit_files();
g.file_stack_push(i.file);
g.generics_stack_push(HashMap::new());
@@ -330,7 +326,7 @@ impl<'ast> ZGen<'ast> {
generics.len()
))
} else {
Ok(uint_lit(DFL_T.modulus().significant_bits(), 32))
Ok(uint_lit(cfg().field().modulus().significant_bits(), 32))
}
}
_ => Err(format!("Unknown or unimplemented builtin '{}'", f_name)),

View File

@@ -4,11 +4,11 @@ use std::fmt::{self, Display, Formatter};
use rug::Integer;
use crate::cfg::cfg;
use crate::circify::{CirCtx, Embeddable, Typed};
use crate::front::field_list::FieldList;
use crate::ir::opt::cfold::fold as constant_fold;
use crate::ir::term::*;
use crate::util::field::DFL_T;
#[derive(Clone, PartialEq, Eq)]
pub enum Ty {
@@ -57,10 +57,12 @@ impl Ty {
match self {
Self::Bool => Sort::Bool,
Self::Uint(w) => Sort::BitVector(*w),
Self::Field => Sort::Field(DFL_T.clone()),
Self::Array(n, b) => {
Sort::Array(Box::new(Sort::Field(DFL_T.clone())), Box::new(b.sort()), *n)
}
Self::Field => Sort::Field(cfg().field().clone()),
Self::Array(n, b) => Sort::Array(
Box::new(Sort::Field(cfg().field().clone())),
Box::new(b.sort()),
*n,
),
Self::Struct(_name, fs) => {
Sort::Tuple(fs.fields().map(|(_f_name, f_ty)| f_ty.sort()).collect())
}
@@ -360,10 +362,10 @@ pub fn div(a: T, b: T) -> Result<T, String> {
}
fn rem_field(a: Term, b: Term) -> Term {
let len = DFL_T.modulus().significant_bits() as usize;
let len = cfg().field().modulus().significant_bits() as usize;
let a_bv = term![Op::PfToBv(len); a];
let b_bv = term![Op::PfToBv(len); b];
term![Op::UbvToPf(DFL_T.clone()); term![Op::BvBinOp(BvBinOp::Urem); a_bv, b_bv]]
term![Op::UbvToPf(cfg().field().clone()); term![Op::BvBinOp(BvBinOp::Urem); a_bv, b_bv]]
}
fn rem_uint(a: Term, b: Term) -> Term {
@@ -441,7 +443,7 @@ fn ult_uint(a: Term, b: Term) -> Term {
// XXX(constr_opt) see TODO file - only need to expand to MIN of two bit-lengths if done right
// XXX(constr_opt) do this using subtraction instead?
fn field_comp(a: Term, b: Term, op: BvBinPred) -> Term {
let len = DFL_T.modulus().significant_bits() as usize;
let len = cfg().field().modulus().significant_bits() as usize;
let a_bv = term![Op::PfToBv(len); a];
let b_bv = term![Op::PfToBv(len); b];
term![Op::BvBinPred(op); a_bv, b_bv]
@@ -634,7 +636,7 @@ fn pf_val<I>(i: I) -> Value
where
Integer: From<I>,
{
Value::Field(DFL_T.new_v(i))
Value::Field(cfg().field().new_v(i))
}
pub fn field_lit<I>(i: I) -> T
@@ -711,7 +713,7 @@ pub fn array_select(array: T, idx: T) -> Result<T, String> {
match array.ty {
Ty::Array(_, elem_ty) if matches!(idx.ty, Ty::Uint(_) | Ty::Field) => {
let iterm = if matches!(idx.ty, Ty::Uint(_)) {
term![Op::UbvToPf(DFL_T.clone()); idx.term]
term![Op::UbvToPf(cfg().field().clone()); idx.term]
} else {
idx.term
};
@@ -725,7 +727,7 @@ pub fn array_store(array: T, idx: T, val: T) -> Result<T, String> {
if matches!(&array.ty, Ty::Array(_, _)) && matches!(&idx.ty, Ty::Uint(_) | Ty::Field) {
// XXX(q) typecheck here?
let iterm = if matches!(idx.ty, Ty::Uint(_)) {
term![Op::UbvToPf(DFL_T.clone()); idx.term]
term![Op::UbvToPf(cfg().field().clone()); idx.term]
} else {
idx.term
};
@@ -756,7 +758,7 @@ fn ir_array<I: IntoIterator<Item = Term>>(sort: Sort, elems: I) -> Term {
.collect::<Vec<(Term, Term)>>();
let len = values.len() + to_insert.len();
let arr = leaf_term(Op::Const(Value::Array(Array::new(
Sort::Field(DFL_T.clone()),
Sort::Field(cfg().field().clone()),
Box::new(sort.default_value()),
values.into_iter().collect::<BTreeMap<_, _>>(),
len,
@@ -786,7 +788,10 @@ pub fn array<I: IntoIterator<Item = T>>(elems: I) -> Result<T, String> {
pub fn uint_to_field(u: T) -> Result<T, String> {
match &u.ty {
Ty::Uint(_) => Ok(T::new(Ty::Field, term![Op::UbvToPf(DFL_T.clone()); u.term])),
Ty::Uint(_) => Ok(T::new(
Ty::Field,
term![Op::UbvToPf(cfg().field().clone()); u.term],
)),
u => Err(format!("Cannot do uint-to-field on {}", u)),
}
}
@@ -925,7 +930,7 @@ impl Embeddable for ZSharp {
Ty::Field,
ctx.cs.borrow_mut().new_var(
&name,
Sort::Field(DFL_T.clone()),
Sort::Field(cfg().field().clone()),
visibility,
precompute.map(|p| p.term),
),

View File

@@ -316,8 +316,6 @@ impl rand::distributions::Distribution<Term> for FixedSizeDist {
pub mod test {
use super::*;
use crate::util::field::DFL_T;
use fxhash::FxHashMap as HashMap;
use quickcheck::{Arbitrary, Gen};
use rand::distributions::Distribution;
@@ -337,7 +335,7 @@ pub mod test {
let mut rng = rand::rngs::StdRng::seed_from_u64(u64::arbitrary(g));
let d = FixedSizeDist {
bv_width: Some(8),
pf_t: Some(DFL_T.clone()),
pf_t: Some(FieldT::FBls12381),
tuples: true,
size: g.size(),
sort: Sort::Bool,

View File

@@ -7,6 +7,7 @@
#[macro_use]
pub mod ir;
pub mod cfg;
pub mod circify;
pub mod front;
pub mod target;

View File

@@ -2,7 +2,6 @@
use circ_fields::{FieldT, FieldV};
use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet};
use lazy_static::lazy_static;
use log::debug;
use paste::paste;
use rug::Integer;
@@ -20,37 +19,6 @@ pub mod opt;
pub mod spartan;
pub mod trans;
/// Guarantees for the IR->R1cs transform
///
/// Relevant to division by zero (in the field).
pub enum Relaxation {
/// May introduce incompleteness
Incomplete,
/// May introduce non-determinism
NonDet,
/// Deterministic
Det,
}
lazy_static! {
static ref RELAXATION: Relaxation = {
match std::env::var("CIRC_RELAXATION")
.map(|s| s.to_lowercase())
.as_ref()
.map(|s| s.as_str())
{
Ok("incomplete") => Relaxation::Incomplete,
Ok("nondet") => Relaxation::NonDet,
Ok("det") => Relaxation::Det,
Ok(s) => panic!(
"Invalid CIRC_RELAXATION {}. Should be: incomplete, nondet or det",
s
),
Err(_) => Relaxation::Incomplete,
}
};
}
#[derive(Debug, Clone, Serialize, Deserialize)]
/// A Rank 1 Constraint System.
pub struct R1cs<S: Hash + Eq> {

View File

@@ -1,5 +1,6 @@
//! Optimizations over R1CS
use super::*;
use crate::cfg::CircCfg;
use crate::util::once::OnceQueue;
use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet};
use log::debug;
@@ -183,11 +184,8 @@ fn constantly_true((a, b, c): &(Lc, Lc, Lc)) -> bool {
///
/// * `lc_size_thresh`: the maximum size LC (number of non-constant monomials) that will be used
/// for propagation. `None` means no size limit.
pub fn reduce_linearities<S: Eq + Hash + Clone + Display>(
r1cs: R1cs<S>,
lc_size_thresh: Option<usize>,
) -> R1cs<S> {
LinReducer::new(r1cs, lc_size_thresh.unwrap_or(usize::MAX)).run()
pub fn reduce_linearities<S: Eq + Hash + Clone + Display>(r1cs: R1cs<S>, cfg: &CircCfg) -> R1cs<S> {
LinReducer::new(r1cs, cfg.r1cs.lc_elim_thresh).run()
}
#[cfg(test)]
@@ -256,7 +254,7 @@ mod test {
#[quickcheck]
fn random(SatR1cs(r1cs, values): SatR1cs) {
let r1cs2 = reduce_linearities(r1cs, None);
let r1cs2 = reduce_linearities(r1cs, &CircCfg::default());
r1cs2.check_all(&values);
}
}

View File

@@ -3,6 +3,7 @@
//! [Ben Braun's
//! thesis](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.683.6940&rep=rep1&type=pdf)
//! is a good intro to how this process works.
use crate::cfg::CircCfg;
use crate::ir::term::extras::Letified;
use crate::ir::term::precomp::PreComp;
use crate::ir::term::*;
@@ -10,6 +11,7 @@ use crate::target::bitsize;
use crate::target::r1cs::*;
use circ_fields::FieldT;
use circ_opt::FieldDivByZero;
use fxhash::FxHashSet;
use log::debug;
use rug::ops::Pow;
@@ -35,7 +37,7 @@ enum EmbeddedTerm {
Tuple(Vec<EmbeddedTerm>),
}
struct ToR1cs {
struct ToR1cs<'cfg> {
r1cs: R1cs<String>,
cache: TermMap<EmbeddedTerm>,
wit_ext: PreComp,
@@ -43,11 +45,13 @@ struct ToR1cs {
next_idx: usize,
zero: TermLc,
one: TermLc,
cfg: &'cfg CircCfg,
field: FieldT,
}
impl ToR1cs {
fn new(field: FieldT, public_inputs: FxHashSet<String>) -> Self {
impl<'cfg> ToR1cs<'cfg> {
fn new(cfg: &'cfg CircCfg, public_inputs: FxHashSet<String>) -> Self {
let field = cfg.field().clone();
debug!("Starting R1CS back-end, field: {}", field);
let r1cs = R1cs::new(field.clone());
let zero = TermLc(pf_lit(field.new_v(0u8)), r1cs.zero());
@@ -61,6 +65,7 @@ impl ToR1cs {
zero,
one,
field,
cfg,
}
}
@@ -870,8 +875,8 @@ impl ToR1cs {
}
Op::UbvToPf(_) => self.get_bv_uint(&c.cs[0]),
Op::PfUnOp(PfUnOp::Neg) => -self.get_pf(&c.cs[0]).clone(),
Op::PfUnOp(PfUnOp::Recip) => match *super::RELAXATION {
Relaxation::Incomplete => {
Op::PfUnOp(PfUnOp::Recip) => match self.cfg.r1cs.div_by_zero {
FieldDivByZero::Incomplete => {
// ix = 1
let x = self.get_pf(&c.cs[0]).clone();
let inv_x = self.fresh_var("recip", term![PF_RECIP; x.0.clone()], false);
@@ -879,7 +884,7 @@ impl ToR1cs {
.constraint(x.1, inv_x.1.clone(), self.r1cs.zero() + 1);
inv_x
}
Relaxation::NonDet => {
FieldDivByZero::NonDet => {
// ixx = x
let x = self.get_pf(&c.cs[0]).clone();
let x2 = self.mul(x.clone(), x.clone());
@@ -887,7 +892,7 @@ impl ToR1cs {
self.r1cs.constraint(x2.1, inv_x.1.clone(), x.1);
inv_x
}
Relaxation::Det => {
FieldDivByZero::Zero => {
// ix = 1 - z
// zx = 0
// zi = 0
@@ -933,7 +938,7 @@ impl ToR1cs {
/// ## Returns
///
/// * The R1CS instance
pub fn to_r1cs(mut cs: Computation, modulus: FieldT) -> (R1cs<String>, ProverData, VerifierData) {
pub fn to_r1cs(mut cs: Computation, cfg: &CircCfg) -> (R1cs<String>, ProverData, VerifierData) {
let assertions = cs.outputs.clone();
let metadata = cs.metadata.clone();
let public_inputs = metadata
@@ -941,7 +946,7 @@ pub fn to_r1cs(mut cs: Computation, modulus: FieldT) -> (R1cs<String>, ProverDat
.map(ToOwned::to_owned)
.collect();
debug!("public inputs: {:?}", public_inputs);
let mut converter = ToR1cs::new(modulus, public_inputs);
let mut converter = ToR1cs::new(cfg, public_inputs);
debug!(
"Term count: {}",
assertions
@@ -969,20 +974,28 @@ pub fn to_r1cs(mut cs: Computation, modulus: FieldT) -> (R1cs<String>, ProverDat
#[cfg(test)]
pub mod test {
use super::*;
use crate::util::field::DFL_T;
use crate::ir::proof::Constraints;
use crate::ir::term::dist::test::*;
use crate::ir::term::dist::*;
use crate::target::r1cs::opt::reduce_linearities;
use circ_fields::FieldT;
use fxhash::FxHashMap;
use quickcheck::{Arbitrary, Gen};
use quickcheck_macros::quickcheck;
use rand::distributions::Distribution;
use rand::SeedableRng;
fn to_r1cs_dflt(cs: Computation) -> (R1cs<String>, ProverData, VerifierData) {
to_r1cs(cs, &CircCfg::default())
}
fn to_r1cs_mod17(cs: Computation) -> (R1cs<String>, ProverData, VerifierData) {
let mut opt = crate::cfg::CircOpt::default();
opt.field.custom_modulus = "17".into();
to_r1cs(cs, &CircCfg::from(opt))
}
fn init() {
let _ = env_logger::builder().is_test(true).try_init();
}
@@ -1006,7 +1019,7 @@ pub mod test {
leaf_term(Op::Var("b".to_owned(), Sort::Bool)),
],
);
let (r1cs, pd, _) = to_r1cs(cs, FieldT::from(Integer::from(17)));
let (r1cs, pd, _) = to_r1cs_mod17(cs);
let precomp = pd.precompute;
let extended_values = precomp.eval(&values);
r1cs.check_all(&extended_values);
@@ -1050,7 +1063,7 @@ pub mod test {
term![Op::Not; t]
};
let cs = Computation::from_constraint_system_parts(vec![t], Vec::new());
let (r1cs, pd, _) = to_r1cs(cs, DFL_T.clone());
let (r1cs, pd, _) = to_r1cs_dflt(cs);
let precomp = pd.precompute;
let extended_values = precomp.eval(&values);
r1cs.check_all(&extended_values);
@@ -1063,7 +1076,8 @@ pub mod test {
let mut cs = Computation::from_constraint_system_parts(vec![t], Vec::new());
crate::ir::opt::scalarize_vars::scalarize_inputs(&mut cs);
crate::ir::opt::tuple::eliminate_tuples(&mut cs);
let (r1cs, pd, _) = to_r1cs(cs, DFL_T.clone());
let cfg = CircCfg::default();
let (r1cs, pd, _) = to_r1cs(cs, &cfg);
let precomp = pd.precompute;
let extended_values = precomp.eval(&values);
r1cs.check_all(&extended_values);
@@ -1074,11 +1088,12 @@ pub mod test {
let v = eval(&t, &values);
let t = term![Op::Eq; t, leaf_term(Op::Const(v))];
let cs = Computation::from_constraint_system_parts(vec![t], Vec::new());
let (r1cs, pd, _) = to_r1cs(cs, DFL_T.clone());
let cfg = CircCfg::default();
let (r1cs, pd, _) = to_r1cs(cs, &cfg);
let precomp = pd.precompute;
let extended_values = precomp.eval(&values);
r1cs.check_all(&extended_values);
let r1cs2 = reduce_linearities(r1cs, None);
let r1cs2 = reduce_linearities(r1cs, &cfg);
r1cs2.check_all(&extended_values);
}
@@ -1089,11 +1104,12 @@ pub mod test {
let mut cs = Computation::from_constraint_system_parts(vec![t], Vec::new());
crate::ir::opt::scalarize_vars::scalarize_inputs(&mut cs);
crate::ir::opt::tuple::eliminate_tuples(&mut cs);
let (r1cs, pd, _) = to_r1cs(cs, DFL_T.clone());
let cfg = CircCfg::default();
let (r1cs, pd, _) = to_r1cs(cs, &cfg);
let precomp = pd.precompute;
let extended_values = precomp.eval(&values);
r1cs.check_all(&extended_values);
let r1cs2 = reduce_linearities(r1cs, None);
let r1cs2 = reduce_linearities(r1cs, &cfg);
r1cs2.check_all(&extended_values);
}
@@ -1111,7 +1127,7 @@ pub mod test {
term![Op::BvUnOp(BvUnOp::Neg); leaf_term(Op::Var("b".to_owned(), Sort::BitVector(8)))]]]],
vec![leaf_term(Op::Var("b".to_owned(), Sort::BitVector(8)))],
);
let (r1cs, pd, _) = to_r1cs(cs, DFL_T.clone());
let (r1cs, pd, _) = to_r1cs_dflt(cs);
let precomp = pd.precompute;
let extended_values = precomp.eval(&values);
r1cs.check_all(&extended_values);
@@ -1127,11 +1143,12 @@ pub mod test {
let v = eval(&t, &values);
let t = term![Op::Eq; t, leaf_term(Op::Const(v))];
let cs = Computation::from_constraint_system_parts(vec![t], vec![]);
let (r1cs, pd, _) = to_r1cs(cs, DFL_T.clone());
let cfg = CircCfg::default();
let (r1cs, pd, _) = to_r1cs(cs, &cfg);
let precomp = pd.precompute;
let extended_values = precomp.eval(&values);
r1cs.check_all(&extended_values);
let r1cs2 = reduce_linearities(r1cs, None);
let r1cs2 = reduce_linearities(r1cs, &cfg);
r1cs2.check_all(&extended_values);
}
@@ -1143,14 +1160,14 @@ pub mod test {
))))
}
fn pf(i: isize) -> Term {
leaf_term(Op::Const(Value::Field(DFL_T.new_v(i))))
fn pf_dflt(i: isize) -> Term {
leaf_term(Op::Const(Value::Field(CircCfg::default().field().new_v(i))))
}
fn const_test(term: Term) {
let mut cs = Computation::new();
cs.assert(term);
let (r1cs, pd, _) = to_r1cs(cs, DFL_T.clone());
let (r1cs, pd, _) = to_r1cs_dflt(cs);
let precomp = pd.precompute;
let extended_values = precomp.eval(&Default::default());
r1cs.check_all(&extended_values);
@@ -1240,17 +1257,17 @@ pub mod test {
fn pf2bv() {
const_test(term![
Op::Eq;
term![Op::PfToBv(4); pf(8)],
term![Op::PfToBv(4); pf_dflt(8)],
bv(0b1000, 4)
]);
const_test(term![
Op::Eq;
term![Op::PfToBv(4); pf(15)],
term![Op::PfToBv(4); pf_dflt(15)],
bv(0b1111, 4)
]);
const_test(term![
Op::Eq;
term![Op::PfToBv(8); pf(15)],
term![Op::PfToBv(8); pf_dflt(15)],
bv(0b1111, 8)
]);
}
@@ -1274,7 +1291,7 @@ pub mod test {
],
);
crate::ir::opt::tuple::eliminate_tuples(&mut cs);
let (r1cs, pd, _) = to_r1cs(cs, FieldT::from(Integer::from(17)));
let (r1cs, pd, _) = to_r1cs_mod17(cs);
let precomp = pd.precompute;
let extended_values = precomp.eval(&values);
r1cs.check_all(&extended_values);

View File

@@ -1,72 +0,0 @@
//! Field type defaults
//
// NOTE: when we eventually break CirC into separate crates,
// each crate may want its own field type default
#[cfg(all(not(feature = "ff_dfl"), not(feature = "ristretto255")))]
use circ_fields::moduli::*;
use circ_fields::FieldT;
#[cfg(not(feature = "ff_dfl"))]
use lazy_static::lazy_static;
#[cfg(feature = "ristretto255")]
use rug::Integer;
#[cfg(all(
feature = "bls12381",
not(feature = "bn254"),
not(feature = "ristretto255"),
feature = "ff_dfl"
))]
/// Default field
pub const DFL_T: FieldT = FieldT::FBls12381;
#[cfg(all(
feature = "bls12381",
not(feature = "bn254"),
not(feature = "ristretto255"),
not(feature = "ff_dfl")
))]
lazy_static! {
/// Default field
pub static ref DFL_T: FieldT = FieldT::IntField(F_BLS12381_FMOD_ARC.clone());
}
#[cfg(all(
not(feature = "bls12381"),
feature = "bn254",
not(feature = "ristretto255"),
feature = "ff_dfl"
))]
/// Default field
pub const DFL_T: FieldT = FieldT::FBn254;
#[cfg(all(
not(feature = "bls12381"),
feature = "bn254",
not(feature = "ristretto255"),
not(feature = "ff_dfl")
))]
lazy_static! {
/// Default field
pub static ref DFL_T: FieldT = FieldT::IntField(F_BN254_FMOD_ARC.clone());
}
#[cfg(all(
not(feature = "bls12381"),
not(feature = "bn254"),
feature = "ristretto255"
))]
lazy_static! {
/// Spartan modulus
pub static ref RISTRETTO255_MOD: Integer = Integer::from_str_radix(
"7237005577332262213973186563042994240857116359379907606001950938285454250989",
10
).unwrap();
}
#[cfg(all(
not(feature = "bls12381"),
not(feature = "bn254"),
feature = "ristretto255"
))]
lazy_static! {
/// Default field
pub static ref DFL_T: FieldT = FieldT::from(RISTRETTO255_MOD.clone());
}

View File

@@ -1,6 +1,5 @@
//! Various data structures, etc.
pub mod field;
pub mod hc;
pub mod once;