Explorar el Código

made directory names singular

lunar-mining hace 4 años
padre
commit
e83853718f

+ 10 - 0
example/config/cashierd.toml

@@ -0,0 +1,10 @@
+accept_url = "127.0.0.1:7777"
+rpc_url = "http://127.0.0.1:8000"
+client_database_path = "cashier_client_database.db"
+btc_endpoint = "tcp://electrum.blockstream.info:50001"
+gateway_url = "127.0.0.1:3333"
+log_path = "/tmp/cashierd.log"
+cashierdb_path = "~/.config/darkfi/cashier.db"
+client_walletdb_path = "~/.config/darkfi/cashier_client_walletdb.db"
+password = "TEST_PASSWORD"
+client_password = "TEST_PASSWORD"

+ 8 - 0
example/config/darkfid.toml

@@ -0,0 +1,8 @@
+connect_url = "127.0.0.1:3333"
+subscriber_url = "127.0.0.1:4444"
+cashier_url = "127.0.0.1:7777"
+rpc_url = "127.0.0.1:8000"
+database_path = "~/.config/darkfi/database_client.db"
+walletdb_path = "~/.config/darkfi/walletdb.db"
+log_path = "/tmp/darkfid_service_daemon.log"
+password = "TEST_PASSWORD"

+ 2 - 0
example/config/drk.toml

@@ -0,0 +1,2 @@
+rpc_url = "http://127.0.0.1:8000"
+log_path = "/tmp/drk_cli.log"

+ 4 - 0
example/config/gatewayd.toml

@@ -0,0 +1,4 @@
+connect_url = "127.0.0.1:3333"
+publisher_url = "127.0.0.1:4444"
+database_path = "gatewayd.db"
+log_path = "/tmp/gatewayd.log"

+ 791 - 0
example/halo2/Cargo.lock

@@ -0,0 +1,791 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "aes"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561"
+dependencies = [
+ "aes-soft",
+ "aesni",
+ "cipher",
+]
+
+[[package]]
+name = "aes-soft"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072"
+dependencies = [
+ "cipher",
+ "opaque-debug",
+]
+
+[[package]]
+name = "aesni"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce"
+dependencies = [
+ "cipher",
+ "opaque-debug",
+]
+
+[[package]]
+name = "arrayref"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
+
+[[package]]
+name = "arrayvec"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
+
+[[package]]
+name = "arrayvec"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd"
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+
+[[package]]
+name = "bigint"
+version = "4.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0e8c8a600052b52482eff2cf4d810e462fdff1f656ac1ecb6232132a1ed7def"
+dependencies = [
+ "byteorder",
+ "crunchy",
+]
+
+[[package]]
+name = "bitvec"
+version = "0.22.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527"
+dependencies = [
+ "funty",
+ "radium",
+ "tap",
+ "wyz",
+]
+
+[[package]]
+name = "blake2b_simd"
+version = "0.5.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587"
+dependencies = [
+ "arrayref",
+ "arrayvec 0.5.2",
+ "constant_time_eq",
+]
+
+[[package]]
+name = "block-modes"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0"
+dependencies = [
+ "block-padding",
+ "cipher",
+]
+
+[[package]]
+name = "block-padding"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
+
+[[package]]
+name = "bls12_381"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54757888b09a69be70b5ec303e382a74227392086ba808cb01eeca29233a2397"
+dependencies = [
+ "ff",
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "cipher"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "constant_time_eq"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+ "lazy_static",
+ "memoffset",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
+dependencies = [
+ "cfg-if",
+ "lazy_static",
+]
+
+[[package]]
+name = "crunchy"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
+
+[[package]]
+name = "crypto_api"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f855e87e75a4799e18b8529178adcde6fd4f97c1449ff4821e747ff728bb102"
+
+[[package]]
+name = "crypto_api_chachapoly"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d930b6a026ce9d358a17f9c9046c55d90b14bb847f36b6ebb6b19365d4feffb8"
+dependencies = [
+ "crypto_api",
+]
+
+[[package]]
+name = "digest"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "either"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+
+[[package]]
+name = "ff"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f"
+dependencies = [
+ "bitvec",
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "fpe"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a25080721bbcd2cd4d765b7d607ea350425fa087ce53cd3e31afcacdab850352"
+dependencies = [
+ "aes",
+ "block-modes",
+ "num-bigint",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "funty"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e"
+
+[[package]]
+name = "generic-array"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "group"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912"
+dependencies = [
+ "byteorder",
+ "ff",
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "halo2"
+version = "0.0.1"
+source = "git+https://github.com/zcash/halo2.git?rev=27c4187673a9c6ade13fbdbd4f20955530c22d7f#27c4187673a9c6ade13fbdbd4f20955530c22d7f"
+dependencies = [
+ "blake2b_simd",
+ "ff",
+ "group",
+ "pasta_curves",
+ "rand",
+ "rayon",
+]
+
+[[package]]
+name = "halo2_ecc"
+version = "0.0.0"
+source = "git+https://github.com/parazyd/orchard.git?rev=f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9#f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
+dependencies = [
+ "arrayvec 0.7.1",
+ "bigint",
+ "ff",
+ "group",
+ "halo2",
+ "halo2_utilities",
+ "lazy_static",
+ "pasta_curves",
+ "rand",
+]
+
+[[package]]
+name = "halo2_examples"
+version = "0.1.0"
+dependencies = [
+ "arrayvec 0.7.1",
+ "bigint",
+ "bitvec",
+ "ff",
+ "group",
+ "halo2",
+ "halo2_ecc",
+ "halo2_poseidon",
+ "halo2_utilities",
+ "lazy_static",
+ "orchard",
+ "pasta_curves",
+ "rand",
+ "sinsemilla",
+ "subtle",
+]
+
+[[package]]
+name = "halo2_poseidon"
+version = "0.0.0"
+source = "git+https://github.com/parazyd/orchard.git?rev=f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9#f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
+dependencies = [
+ "bitvec",
+ "ff",
+ "halo2",
+ "halo2_utilities",
+ "pasta_curves",
+]
+
+[[package]]
+name = "halo2_utilities"
+version = "0.0.0"
+source = "git+https://github.com/parazyd/orchard.git?rev=f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9#f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
+dependencies = [
+ "bigint",
+ "ff",
+ "halo2",
+ "pasta_curves",
+ "rand",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "incrementalmerkletree"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16d75fb342984cc8cea665a9ef5607b4956569839ca098172082fa1b19bdaf02"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "jubjub"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "593fc4726ca80edb47ee18ab4d826719e25c2096991a79308b44fb915c6014ef"
+dependencies = [
+ "bitvec",
+ "bls12_381",
+ "ff",
+ "group",
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5"
+
+[[package]]
+name = "memoffset"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "nonempty"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7"
+
+[[package]]
+name = "num-bigint"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d0a3d5e207573f948a9e5376662aa743a2ea13f7c50a554d7af443a73fbfeba"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "opaque-debug"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+
+[[package]]
+name = "orchard"
+version = "0.0.0"
+source = "git+https://github.com/parazyd/orchard.git?rev=f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9#f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
+dependencies = [
+ "aes",
+ "arrayvec 0.7.1",
+ "bigint",
+ "bitvec",
+ "blake2b_simd",
+ "ff",
+ "fpe",
+ "group",
+ "halo2",
+ "halo2_ecc",
+ "halo2_poseidon",
+ "halo2_utilities",
+ "incrementalmerkletree",
+ "lazy_static",
+ "nonempty",
+ "pasta_curves",
+ "rand",
+ "reddsa",
+ "serde",
+ "sinsemilla",
+ "subtle",
+ "zcash_note_encryption",
+]
+
+[[package]]
+name = "pasta_curves"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a21914ddc589b74e7638091c8e91a4e8b083ee5e1d0066d64407131b7570799"
+dependencies = [
+ "blake2b_simd",
+ "ff",
+ "group",
+ "lazy_static",
+ "rand",
+ "static_assertions",
+ "subtle",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "radium"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb"
+
+[[package]]
+name = "rand"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rayon"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
+dependencies = [
+ "autocfg",
+ "crossbeam-deque",
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "lazy_static",
+ "num_cpus",
+]
+
+[[package]]
+name = "reddsa"
+version = "0.0.0"
+source = "git+https://github.com/str4d/redjubjub.git?rev=d5d8c5f3bb704bad8ae88fe4a29ae1f744774cb2#d5d8c5f3bb704bad8ae88fe4a29ae1f744774cb2"
+dependencies = [
+ "blake2b_simd",
+ "byteorder",
+ "digest",
+ "group",
+ "jubjub",
+ "pasta_curves",
+ "rand_core",
+ "serde",
+ "thiserror",
+ "zeroize",
+]
+
+[[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.128"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1056a0db1978e9dbf0f6e4fca677f6f9143dc1c19de346f22cac23e422196834"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.128"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13af2fbb8b60a8950d6c72a56d2095c28870367cc8e10c55e9745bac4995a2c4"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "sinsemilla"
+version = "0.0.0"
+source = "git+https://github.com/parazyd/orchard.git?rev=f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9#f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
+dependencies = [
+ "ff",
+ "group",
+ "halo2",
+ "halo2_ecc",
+ "halo2_utilities",
+ "pasta_curves",
+ "rand",
+ "subtle",
+]
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "subtle"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+
+[[package]]
+name = "syn"
+version = "1.0.75"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "synstructure"
+version = "0.12.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unicode-xid",
+]
+
+[[package]]
+name = "tap"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+
+[[package]]
+name = "thiserror"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "typenum"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
+
+[[package]]
+name = "version_check"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
+
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+
+[[package]]
+name = "wyz"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188"
+dependencies = [
+ "tap",
+]
+
+[[package]]
+name = "zcash_note_encryption"
+version = "0.0.0"
+source = "git+https://github.com/zcash/librustzcash.git?rev=13b023387bafdc7b5712c933dc0e16ee94b96a6a#13b023387bafdc7b5712c933dc0e16ee94b96a6a"
+dependencies = [
+ "blake2b_simd",
+ "byteorder",
+ "crypto_api_chachapoly",
+ "ff",
+ "group",
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "zeroize"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "377db0846015f7ae377174787dd452e1c5f5a9050bc6f954911d01f116daa0cd"
+dependencies = [
+ "zeroize_derive",
+]
+
+[[package]]
+name = "zeroize_derive"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2c1e130bebaeab2f23886bf9acbaca14b092408c452543c857f66399cd6dab1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]

+ 47 - 0
example/halo2/Cargo.toml

@@ -0,0 +1,47 @@
+[package]
+name = "halo2_examples"
+version = "0.1.0"
+authors = ["narodnik <x@x.org>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+ff = "0.10"
+group = "0.10"
+pasta_curves = "0.1.2"
+bitvec = "0.22"
+rand = "0.8.4"
+arrayvec = "0.7.0"
+lazy_static = "1"
+bigint = "4"
+subtle = "2.3"
+halo2 = "0.0"
+
+[patch.crates-io]
+halo2 = { git = "https://github.com/zcash/halo2.git", rev = "27c4187673a9c6ade13fbdbd4f20955530c22d7f" }
+
+[dependencies.halo2_poseidon]
+git = "https://github.com/parazyd/orchard.git"
+#rev = "0d14f2390734e4710fc24a976f037dae3a6e7ac8"
+rev = "f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
+features = ["halo2"]
+
+[dependencies.halo2_utilities]
+git = "https://github.com/parazyd/orchard.git"
+#rev = "0d14f2390734e4710fc24a976f037dae3a6e7ac8"
+rev = "f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
+
+[dependencies.halo2_ecc]
+git = "https://github.com/parazyd/orchard.git"
+#rev = "0d14f2390734e4710fc24a976f037dae3a6e7ac8"
+rev = "f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
+
+[dependencies.sinsemilla]
+git = "https://github.com/parazyd/orchard.git"
+#rev = "0d14f2390734e4710fc24a976f037dae3a6e7ac8"
+rev = "f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
+
+ [dependencies.orchard]
+git = "https://github.com/parazyd/orchard.git"
+rev = "f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"

+ 6 - 0
example/halo2/README.md

@@ -0,0 +1,6 @@
+Always use the --release flag otherwise it's too slow:
+
+```
+cargo run --release --bin simple3
+```
+

+ 73 - 0
example/halo2/src/bin/burn.rs

@@ -0,0 +1,73 @@
+use std::iter;
+
+use group::{ff::PrimeFieldBits, Curve};
+use halo2::{
+    arithmetic::{CurveAffine, Field, FieldExt},
+    pasta::{Fp, Fq},
+};
+use halo2_ecc::gadget::FixedPoints;
+use halo2_poseidon::primitive::{ConstantLength, Hash, P128Pow5T3 as OrchardNullifier};
+use orchard::constants::{fixed_bases::OrchardFixedBases, sinsemilla::MERKLE_CRH_PERSONALIZATION};
+use rand::rngs::OsRng;
+use sinsemilla::primitive::{CommitDomain, HashDomain};
+
+use halo2_examples::pedersen_commitment;
+
+fn main() {
+    let secret_key = Fq::random(&mut OsRng);
+    let serial = Fp::random(&mut OsRng);
+
+    // Sinsemilla hash
+    let domain = HashDomain::new(MERKLE_CRH_PERSONALIZATION);
+    let nullifier = domain
+        .hash(
+            iter::empty()
+                .chain(secret_key.to_le_bits().iter().by_val())
+                .chain(serial.to_le_bits().iter().by_val()),
+        )
+        .unwrap();
+
+    let public_key = OrchardFixedBases::SpendAuthG.generator() * secret_key;
+    let coords = public_key.to_affine().coordinates().unwrap();
+
+    let value = 110;
+    let asset = 1;
+
+    let value_blind = Fq::random(&mut OsRng);
+    let asset_blind = Fq::random(&mut OsRng);
+
+    let coin_blind = Fp::random(&mut OsRng);
+
+    // FIXME:
+    let messages = [
+        [*coords.x(), *coords.y()],
+        [Fp::from(value), Fp::from(asset)],
+        [serial, coin_blind],
+    ];
+    let mut coin = Fp::zero();
+    for msg in messages.iter() {
+        coin += Hash::init(OrchardNullifier, ConstantLength::<2>).hash(*msg);
+    }
+
+    // TODO: Merkle
+
+    let value_commit = pedersen_commitment(value, value_blind);
+    let asset_commit = pedersen_commitment(asset, asset_blind);
+    let value_coords = value_commit.to_affine().coordinates().unwrap();
+    let asset_coords = value_commit.to_affine().coordinates().unwrap();
+
+    let sig_secret = Fq::random(&mut OsRng);
+    let sig_pubkey = OrchardFixedBases::SpendAuthG.generator() * sig_secret;
+    let sig_pk_coords = sig_pubkey.to_affine().coordinates().unwrap();
+
+    let mut public_inputs = vec![
+        nullifier,
+        *value_coords.x(),
+        *value_coords.y(),
+        *asset_coords.x(),
+        *asset_coords.y(),
+        // merkle_root,
+        *sig_pk_coords.x(),
+        *sig_pk_coords.y(),
+    ];
+}

+ 439 - 0
example/halo2/src/bin/mint.rs

@@ -0,0 +1,439 @@
+use std::{convert::TryInto, time::Instant};
+
+use group::{ff::Field, Curve, Group};
+use halo2::{
+    arithmetic::CurveAffine,
+    circuit::{floor_planner, Layouter},
+    dev::MockProver,
+    pasta::{vesta, Ep, Fp, Fq},
+    plonk,
+    plonk::{Circuit, ConstraintSystem, Error},
+    poly::commitment,
+    transcript::{Blake2bRead, Blake2bWrite},
+};
+use halo2_ecc::{chip::EccChip, gadget::FixedPoint};
+use halo2_poseidon::{
+    gadget::{Hash as PoseidonHash, Word},
+    pow5t3::{Pow5T3Chip as PoseidonChip, StateWord},
+    primitive::{ConstantLength, Hash, P128Pow5T3 as OrchardNullifier},
+};
+use halo2_utilities::{
+    lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
+};
+use orchard::constants::fixed_bases::OrchardFixedBases;
+use rand::rngs::OsRng;
+
+use halo2_examples::{circuit::Config, pedersen_commitment};
+
+const K: u32 = 9;
+
+#[derive(Default, Debug)]
+struct MintCircuit {
+    pub_x: Option<Fp>,       // x coordinate for pubkey
+    pub_y: Option<Fp>,       // y coordinate for pubkey
+    value: Option<Fp>,       // The value of this coin
+    asset: Option<Fp>,       // The asset ID
+    serial: Option<Fp>,      // Unique serial number corresponding to this coin
+    coin_blind: Option<Fp>,  // Random blinding factor for coin
+    value_blind: Option<Fq>, // Random blinding factor for value commitment
+    asset_blind: Option<Fq>, // Random blinding factor for the asset ID
+}
+
+impl UtilitiesInstructions<Fp> for MintCircuit {
+    type Var = CellValue<Fp>;
+}
+
+impl Circuit<Fp> for MintCircuit {
+    type Config = Config;
+    type FloorPlanner = floor_planner::V1;
+    //type FloorPlanner = SimpleFloorPlanner;
+
+    fn without_witnesses(&self) -> Self {
+        Self::default()
+    }
+
+    fn configure(meta: &mut ConstraintSystem<Fp>) -> Self::Config {
+        let advices = [
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+        ];
+
+        let q_add = meta.selector();
+
+        let table_idx = meta.lookup_table_column();
+
+        // let lookup = (
+        // table_idx,
+        // meta.lookup_table_column(),
+        // meta.lookup_table_column(),
+        // );
+
+        let primary = meta.instance_column();
+
+        meta.enable_equality(primary.into());
+
+        for advice in advices.iter() {
+            meta.enable_equality((*advice).into());
+        }
+
+        let lagrange_coeffs = [
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+        ];
+
+        let rc_a = lagrange_coeffs[2..5].try_into().unwrap();
+        let rc_b = lagrange_coeffs[5..8].try_into().unwrap();
+
+        meta.enable_constant(lagrange_coeffs[0]);
+
+        let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx);
+
+        let ecc_config = EccChip::<OrchardFixedBases>::configure(
+            meta,
+            advices,
+            lagrange_coeffs,
+            range_check.clone(),
+        );
+
+        let poseidon_config = PoseidonChip::configure(
+            meta,
+            OrchardNullifier,
+            advices[6..9].try_into().unwrap(),
+            advices[5],
+            rc_a,
+            rc_b,
+        );
+
+        Config {
+            primary,
+            q_add,
+            advices,
+            ecc_config,
+            poseidon_config,
+        }
+    }
+
+    fn synthesize(
+        &self,
+        config: Self::Config,
+        mut layouter: impl Layouter<Fp>,
+    ) -> Result<(), Error> {
+        // Construct the ECC chip.
+        let ecc_chip = EccChip::construct(config.ecc_config.clone());
+
+        let pub_x = self.load_private(
+            layouter.namespace(|| "load pubkey x"),
+            config.advices[0],
+            self.pub_x,
+        )?;
+        let pub_y = self.load_private(
+            layouter.namespace(|| "load pubkey y"),
+            config.advices[0],
+            self.pub_y,
+        )?;
+        let value = self.load_private(
+            layouter.namespace(|| "load value"),
+            config.advices[0],
+            self.value,
+        )?;
+        let asset = self.load_private(
+            layouter.namespace(|| "load asset"),
+            config.advices[0],
+            self.asset,
+        )?;
+        let serial = self.load_private(
+            layouter.namespace(|| "load serial"),
+            config.advices[0],
+            self.serial,
+        )?;
+        let coin_blind = self.load_private(
+            layouter.namespace(|| "load coin_blind"),
+            config.advices[0],
+            self.coin_blind,
+        )?;
+
+        // =============
+        // = Coin hash =
+        // =============
+
+        // TODO: This is a hack until issue is resolved in poseidon gadget
+        let mut coin = Fp::zero();
+        let messages = [[pub_x, pub_y], [value, asset], [serial, coin_blind]];
+        //let messages = [[pub_x, pub_y], [value, asset]];
+        //let messages = [[pub_x, pub_y]];
+        for msg in messages.iter() {
+            let poseidon_message = layouter.assign_region(
+                || "load message",
+                |mut region| {
+                    let mut message_word = |i: usize| {
+                        let val = msg[i].value();
+                        let var = region.assign_advice(
+                            || format!("load message_{}", i),
+                            config.poseidon_config.state()[i],
+                            0,
+                            || val.ok_or(Error::SynthesisError),
+                        )?;
+                        region.constrain_equal(var, msg[i].cell())?;
+                        Ok(Word::<_, _, OrchardNullifier, 3, 2>::from_inner(
+                            StateWord::new(var, val),
+                        ))
+                    };
+                    Ok([message_word(0)?, message_word(1)?])
+                },
+            )?;
+
+            let poseidon_hasher = PoseidonHash::init(
+                PoseidonChip::construct(config.poseidon_config.clone()),
+                layouter.namespace(|| "Poseidon init"),
+                ConstantLength::<2>,
+            )?;
+
+            let poseidon_output =
+                poseidon_hasher.hash(layouter.namespace(|| "Poseidon hash"), poseidon_message)?;
+
+            let poseidon_output: CellValue<Fp> = poseidon_output.inner().into();
+
+            if !poseidon_output.value().is_none() {
+                coin += poseidon_output.value().unwrap();
+            }
+        }
+
+        // if coin != Fp::zero() {
+        // println!("circuit hash: {:?}", coin);
+        // }
+
+        let hash = self.load_private(
+            layouter.namespace(|| "load hash"),
+            config.advices[0],
+            Some(coin),
+        )?;
+
+        // Constrain the coin C; index in public values is 0
+        layouter.constrain_instance(hash.cell(), config.primary, 0)?;
+
+        // ====================
+        // = Value commitment =
+        // ====================
+
+        // This constant one is used for multiplication
+        let one = self.load_constant(
+            layouter.namespace(|| "constant one"),
+            config.advices[0],
+            Fp::one(),
+        )?;
+
+        // v*G_1
+        let (commitment, _) = {
+            let value_commit_v = OrchardFixedBases::ValueCommitV;
+            let value_commit_v = FixedPoint::from_inner(ecc_chip.clone(), value_commit_v);
+            value_commit_v.mul_short(layouter.namespace(|| "[value] ValueCommitV"), (value, one))?
+        };
+
+        // r_V*G_2
+        let (blind, _rcv) = {
+            let rcv = self.value_blind;
+            let value_commit_r = OrchardFixedBases::ValueCommitR;
+            let value_commit_r = FixedPoint::from_inner(ecc_chip.clone(), value_commit_r);
+            value_commit_r.mul(layouter.namespace(|| "[value_blind] ValueCommitR"), rcv)?
+        };
+
+        // Constrain the x and y; indexes in public values are 1 and 2
+        let value_commit = commitment.add(layouter.namespace(|| "valuecommit"), &blind)?;
+        layouter.constrain_instance(value_commit.inner().x().cell(), config.primary, 1)?;
+        layouter.constrain_instance(value_commit.inner().y().cell(), config.primary, 2)?;
+
+        // ====================
+        // = Asset commitment =
+        // ====================
+
+        // a*G_1
+        let (commitment, _) = {
+            let asset_commit_v = OrchardFixedBases::ValueCommitV;
+            let asset_commit_v = FixedPoint::from_inner(ecc_chip.clone(), asset_commit_v);
+            asset_commit_v.mul_short(layouter.namespace(|| "[asset] ValueCommitV"), (asset, one))?
+        };
+
+        // r_A*G_2
+        let (blind, _rca) = {
+            let rca = self.asset_blind;
+            let asset_commit_r = OrchardFixedBases::ValueCommitR;
+            let asset_commit_r = FixedPoint::from_inner(ecc_chip.clone(), asset_commit_r);
+            asset_commit_r.mul(layouter.namespace(|| "[asset_blind] ValueCommitR"), rca)?
+        };
+
+        // Constrain the x and y; indexes in public values are 3 and 4
+        let asset_commit = commitment.add(layouter.namespace(|| "assetcommit"), &blind)?;
+        layouter.constrain_instance(asset_commit.inner().x().cell(), config.primary, 3)?;
+        layouter.constrain_instance(asset_commit.inner().y().cell(), config.primary, 4)?;
+
+        Ok(())
+    }
+}
+
+#[derive(Debug)]
+struct VerifyingKey {
+    params: commitment::Params<vesta::Affine>,
+    vk: plonk::VerifyingKey<vesta::Affine>,
+}
+
+impl VerifyingKey {
+    fn build() -> Self {
+        let params = commitment::Params::new(K);
+        let circuit: MintCircuit = Default::default();
+
+        let vk = plonk::keygen_vk(&params, &circuit).unwrap();
+
+        VerifyingKey { params, vk }
+    }
+}
+
+#[derive(Debug)]
+struct ProvingKey {
+    params: commitment::Params<vesta::Affine>,
+    pk: plonk::ProvingKey<vesta::Affine>,
+}
+
+impl ProvingKey {
+    fn build() -> Self {
+        let params = commitment::Params::new(K);
+        let circuit: MintCircuit = Default::default();
+
+        let vk = plonk::keygen_vk(&params, &circuit).unwrap();
+        let pk = plonk::keygen_pk(&params, vk, &circuit).unwrap();
+
+        ProvingKey { params, pk }
+    }
+}
+
+#[derive(Clone, Debug)]
+struct Proof(Vec<u8>);
+
+impl AsRef<[u8]> for Proof {
+    fn as_ref(&self) -> &[u8] {
+        &self.0
+    }
+}
+
+impl Proof {
+    fn create(pk: &ProvingKey, circuits: &[MintCircuit], pubinputs: &[Fp]) -> Result<Self, Error> {
+        let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]);
+        plonk::create_proof(
+            &pk.params,
+            &pk.pk,
+            circuits,
+            &[&[pubinputs]],
+            &mut transcript,
+        )?;
+        Ok(Proof(transcript.finalize()))
+    }
+
+    fn verify(&self, vk: &VerifyingKey, pubinputs: &[Fp]) -> Result<(), plonk::Error> {
+        let msm = vk.params.empty_msm();
+        let mut transcript = Blake2bRead::init(&self.0[..]);
+        let guard = plonk::verify_proof(&vk.params, &vk.vk, msm, &[&[pubinputs]], &mut transcript)?;
+        let msm = guard.clone().use_challenges();
+        if msm.eval() {
+            Ok(())
+        } else {
+            Err(Error::ConstraintSystemFailure)
+        }
+    }
+
+    // fn new(bytes: Vec<u8>) -> Self {
+    // Proof(bytes)
+    // }
+}
+
+fn main() {
+    let pubkey = Ep::random(&mut OsRng);
+    let coords = pubkey.to_affine().coordinates().unwrap();
+
+    let value = 110;
+    let asset = 1;
+
+    let value_blind = Fq::random(&mut OsRng);
+    let asset_blind = Fq::random(&mut OsRng);
+
+    let serial = Fp::random(&mut OsRng);
+    let coin_blind = Fp::random(&mut OsRng);
+
+    let mut coin = Fp::zero();
+
+    let messages = [
+        [*coords.x(), *coords.y()],
+        [Fp::from(value), Fp::from(asset)],
+        [serial, coin_blind],
+    ];
+
+    // TODO: This is a hack until issue is fixed in poseidon gadget
+    for msg in messages.iter() {
+        coin += Hash::init(OrchardNullifier, ConstantLength::<2>).hash(*msg);
+    }
+
+    let value_commit = pedersen_commitment(value, value_blind);
+    let value_coords = value_commit.to_affine().coordinates().unwrap();
+
+    let asset_commit = pedersen_commitment(asset, asset_blind);
+    let asset_coords = asset_commit.to_affine().coordinates().unwrap();
+
+    let mut public_inputs = vec![
+        coin,
+        *value_coords.x(),
+        *value_coords.y(),
+        *asset_coords.x(),
+        *asset_coords.y(),
+    ];
+
+    let circuit = MintCircuit {
+        pub_x: Some(*coords.x()),
+        pub_y: Some(*coords.y()),
+        value: Some(vesta::Scalar::from(value)),
+        asset: Some(vesta::Scalar::from(asset)),
+        serial: Some(serial),
+        coin_blind: Some(coin_blind),
+        value_blind: Some(value_blind),
+        asset_blind: Some(asset_blind),
+    };
+
+    // Valid MockProver
+    let prover = MockProver::run(K, &circuit, vec![public_inputs.clone()]).unwrap();
+    assert_eq!(prover.verify(), Ok(()));
+
+    // Add 1 to break the public inputs
+    public_inputs[0] += Fp::from(0xdeadbeef);
+
+    // Invalid MockProver
+    let prover = MockProver::run(K, &circuit, vec![public_inputs.clone()]).unwrap();
+    assert!(prover.verify().is_err());
+
+    // Remove 1 to make the public inputs valid again
+    public_inputs[0] -= Fp::from(0xdeadbeef);
+
+    // Actual ZK proof
+    let start = Instant::now();
+    let vk = VerifyingKey::build();
+    let pk = ProvingKey::build();
+    println!("\nSetup: [{:?}]", start.elapsed());
+
+    let start = Instant::now();
+    let proof = Proof::create(&pk, &[circuit], &public_inputs).unwrap();
+    println!("Prove: [{:?}]", start.elapsed());
+
+    let start = Instant::now();
+    assert!(proof.verify(&vk, &public_inputs).is_ok());
+    println!("Verify: [{:?}]", start.elapsed());
+}

+ 298 - 0
example/halo2/src/bin/poseidon.rs

@@ -0,0 +1,298 @@
+use std::convert::TryInto;
+use std::time::Instant;
+
+use halo2::{
+    circuit::{floor_planner, Layouter},
+    pasta::{vesta, Fp},
+    plonk,
+    plonk::{
+        Advice, Circuit, Column, ConstraintSystem, Error, Instance as InstanceColumn, Selector,
+    },
+    poly::{commitment, Rotation},
+    transcript::{Blake2bRead, Blake2bWrite},
+};
+
+use halo2_poseidon::{
+    gadget::{Hash as PoseidonHash, Word},
+    pow5t3::{Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig, StateWord},
+    primitive::{ConstantLength, Hash, P128Pow5T3 as OrchardNullifier},
+};
+use halo2_utilities::{copy, CellValue, UtilitiesInstructions, Var};
+
+const K: u32 = 6;
+
+#[derive(Clone, Debug)]
+struct Config {
+    primary: Column<InstanceColumn>,
+    q_add: Selector,
+    advices: [Column<Advice>; 10],
+    poseidon_config: PoseidonConfig<Fp>,
+}
+
+#[derive(Default, Debug)]
+struct HashCircuit {
+    a: Option<Fp>, // First input for hash
+    b: Option<Fp>, // Second input for hash
+    c: Option<Fp>, // c is summed with hash
+}
+
+impl UtilitiesInstructions<Fp> for HashCircuit {
+    type Var = CellValue<Fp>;
+}
+
+impl Circuit<Fp> for HashCircuit {
+    type Config = Config;
+    type FloorPlanner = floor_planner::V1;
+
+    fn without_witnesses(&self) -> Self {
+        Self::default()
+    }
+
+    fn configure(meta: &mut ConstraintSystem<Fp>) -> Self::Config {
+        // 10 advice columns
+        let advices = [
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+            meta.advice_column(),
+        ];
+
+        // Addition of two field elements: poseidon_hash(a, b) + c
+        let q_add = meta.selector();
+
+        meta.create_gate("poseidon_hash(a, b) + c", |meta| {
+            let q_add = meta.query_selector(q_add);
+            let sum = meta.query_advice(advices[6], Rotation::cur());
+            let hash = meta.query_advice(advices[7], Rotation::cur());
+            let c = meta.query_advice(advices[8], Rotation::cur());
+
+            vec![q_add * (hash + c - sum)]
+        });
+
+        let primary = meta.instance_column();
+        meta.enable_equality(primary.into());
+
+        for advice in advices.iter() {
+            meta.enable_equality((*advice).into());
+        }
+
+        let lagrange_coeffs = [
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+        ];
+
+        let rc_a = lagrange_coeffs[2..5].try_into().unwrap();
+        let rc_b = lagrange_coeffs[5..8].try_into().unwrap();
+
+        meta.enable_constant(lagrange_coeffs[0]);
+
+        let poseidon_config = PoseidonChip::configure(
+            meta,
+            OrchardNullifier,
+            advices[6..9].try_into().unwrap(),
+            advices[5],
+            rc_a,
+            rc_b,
+        );
+
+        Config {
+            primary,
+            q_add,
+            advices,
+            poseidon_config,
+        }
+    }
+
+    fn synthesize(
+        &self,
+        config: Self::Config,
+        mut layouter: impl Layouter<Fp>,
+    ) -> Result<(), Error> {
+        let a = self.load_private(layouter.namespace(|| "load a"), config.advices[0], self.a)?;
+        let b = self.load_private(layouter.namespace(|| "load b"), config.advices[0], self.b)?;
+        let c = self.load_private(layouter.namespace(|| "load c"), config.advices[0], self.c)?;
+
+        let hash = {
+            let message = [a, b];
+
+            let poseidon_message = layouter.assign_region(
+                || "load message",
+                |mut region| {
+                    let mut message_word = |i: usize| {
+                        let value = message[i].value();
+                        let var = region.assign_advice(
+                            || format!("load message_{}", i),
+                            config.poseidon_config.state()[i],
+                            0,
+                            || value.ok_or(Error::SynthesisError),
+                        )?;
+                        region.constrain_equal(var, message[i].cell())?;
+                        Ok(Word::<_, _, OrchardNullifier, 3, 2>::from_inner(
+                            StateWord::new(var, value),
+                        ))
+                    };
+                    Ok([message_word(0)?, message_word(1)?])
+                },
+            )?;
+
+            let poseidon_hasher = PoseidonHash::init(
+                //config.poseidon_chip(),
+                PoseidonChip::construct(config.poseidon_config.clone()),
+                layouter.namespace(|| "Poseidon init"),
+                ConstantLength::<2>,
+            )?;
+
+            let poseidon_output = poseidon_hasher.hash(
+                layouter.namespace(|| "Poseidon hash (a, b)"),
+                poseidon_message,
+            )?;
+
+            let poseidon_output: CellValue<Fp> = poseidon_output.inner().into();
+            poseidon_output
+        };
+
+        // Add hash output to c
+        let scalar = layouter.assign_region(
+            || " `scalar` = poseidon_hash(a, b) + c",
+            |mut region| {
+                config.q_add.enable(&mut region, 0)?;
+
+                copy(&mut region, || "copy hash", config.advices[7], 0, &hash)?;
+                copy(&mut region, || "copy c", config.advices[8], 0, &c)?;
+
+                let scalar_val = hash.value().zip(c.value()).map(|(hash, c)| hash + c);
+
+                let cell = region.assign_advice(
+                    || "poseidon_hash(a, b) + c",
+                    config.advices[6],
+                    0,
+                    || scalar_val.ok_or(Error::SynthesisError),
+                )?;
+                Ok(CellValue::new(cell, scalar_val))
+            },
+        )?;
+
+        layouter.constrain_instance(scalar.cell(), config.primary, 0)
+    }
+}
+
+#[derive(Debug)]
+struct VerifyingKey {
+    params: commitment::Params<vesta::Affine>,
+    vk: plonk::VerifyingKey<vesta::Affine>,
+}
+
+impl VerifyingKey {
+    fn build() -> Self {
+        let params = commitment::Params::new(K);
+        let circuit: HashCircuit = Default::default();
+
+        let vk = plonk::keygen_vk(&params, &circuit).unwrap();
+
+        VerifyingKey { params, vk }
+    }
+}
+
+#[derive(Debug)]
+struct ProvingKey {
+    params: commitment::Params<vesta::Affine>,
+    pk: plonk::ProvingKey<vesta::Affine>,
+}
+
+impl ProvingKey {
+    fn build() -> Self {
+        let params = commitment::Params::new(K);
+        let circuit: HashCircuit = Default::default();
+
+        let vk = plonk::keygen_vk(&params, &circuit).unwrap();
+        let pk = plonk::keygen_pk(&params, vk, &circuit).unwrap();
+
+        ProvingKey { params, pk }
+    }
+}
+
+#[derive(Clone, Debug)]
+struct Proof(Vec<u8>);
+
+impl AsRef<[u8]> for Proof {
+    fn as_ref(&self) -> &[u8] {
+        &self.0
+    }
+}
+
+impl Proof {
+    fn create(pk: &ProvingKey, circuits: &[HashCircuit], pubinputs: &[Fp]) -> Result<Self, Error> {
+        let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]);
+        plonk::create_proof(
+            &pk.params,
+            &pk.pk,
+            circuits,
+            &[&[pubinputs]],
+            &mut transcript,
+        )?;
+        Ok(Proof(transcript.finalize()))
+    }
+
+    fn verify(&self, vk: &VerifyingKey, pubinputs: &[Fp]) -> Result<(), plonk::Error> {
+        let msm = vk.params.empty_msm();
+        let mut transcript = Blake2bRead::init(&self.0[..]);
+        let guard = plonk::verify_proof(&vk.params, &vk.vk, msm, &[&[pubinputs]], &mut transcript)?;
+        let msm = guard.clone().use_challenges();
+        if msm.eval() {
+            Ok(())
+        } else {
+            Err(Error::ConstraintSystemFailure)
+        }
+    }
+
+    // fn new(bytes: Vec<u8>) -> Self {
+    // Proof(bytes)
+    // }
+}
+
+fn main() {
+    let a = Fp::from(13);
+    let b = Fp::from(69);
+    let c = Fp::from(42);
+
+    let message = [a, b];
+    let output = Hash::init(OrchardNullifier, ConstantLength::<2>).hash(message);
+
+    let circuit = HashCircuit {
+        a: Some(a),
+        b: Some(b),
+        c: Some(c),
+    };
+
+    let sum = output + c;
+
+    // Correct:
+    let public_inputs = vec![sum];
+    // Incorrect:
+    // let public_inputs = vec![sum + Fp::one()];
+
+    let start = Instant::now();
+    let vk = VerifyingKey::build();
+    let pk = ProvingKey::build();
+    println!("Setup: [{:?}]", start.elapsed());
+
+    let start = Instant::now();
+    let proof = Proof::create(&pk, &[circuit], &public_inputs).unwrap();
+    println!("Prove: [{:?}]", start.elapsed());
+
+    let start = Instant::now();
+    assert!(proof.verify(&vk, &public_inputs).is_ok());
+    println!("Verify: [{:?}]", start.elapsed());
+}

+ 130 - 0
example/halo2/src/bin/simple3.rs

@@ -0,0 +1,130 @@
+use halo2::{
+    circuit::{SimpleFloorPlanner, Chip, Layouter},
+    pasta::{EqAffine, Fp},
+    plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Expression, Selector, create_proof, verify_proof, keygen_vk, keygen_pk},
+    poly::{commitment::Params, Rotation},
+    transcript::{Blake2bRead, Blake2bWrite, Challenge255},
+};
+use std::time::Instant;
+
+#[derive(Clone, Debug)]
+struct CoolConfig {
+    a_col: Column<Advice>,
+    s_range: Selector,
+}
+
+struct CoolChip {
+    config: CoolConfig
+}
+
+impl Chip<Fp> for CoolChip {
+    type Config = CoolConfig;
+    type Loaded = ();
+
+    fn config(&self) -> &Self::Config {
+        &self.config
+    }
+
+    fn loaded(&self) -> &Self::Loaded {
+        &()
+    }
+}
+
+impl CoolChip {
+    fn construct(config: CoolConfig) -> Self {
+        Self { config }
+    }
+
+    fn configure(cs: &mut ConstraintSystem<Fp>) -> CoolConfig {
+        let a_col = cs.advice_column();
+        let s_range = cs.selector();
+
+        cs.create_gate("check", |cs| {
+            let a = cs.query_advice(a_col, Rotation::cur());
+            let s_range = cs.query_selector(s_range);
+            vec![s_range * (a - Expression::Constant(Fp::from(2)))]
+        });
+
+        CoolConfig { a_col, s_range }
+    }
+
+    fn alloc_and_check(
+        &self,
+        layouter: &mut impl Layouter<Fp>,
+        a: Option<Fp>,
+    ) -> Result<(), Error> {
+        layouter.assign_region(
+            || "load private inputs",
+            |mut region| {
+                let row_offset = 0;
+                self.config.s_range.enable(&mut region, row_offset)?;
+                region.assign_advice(
+                    || "private input 'a'",
+                    self.config.a_col,
+                    row_offset,
+                    || a.ok_or(Error::SynthesisError),
+                )?;
+                Ok(())
+            },
+        )
+    }
+}
+
+#[derive(Clone)]
+struct CoolCircuit {
+    // Private input.
+    a: Option<Fp>,
+}
+
+impl Circuit<Fp> for CoolCircuit {
+    type Config = CoolConfig;
+    type FloorPlanner = SimpleFloorPlanner;
+
+    fn without_witnesses(&self) -> Self {
+        Self { a: None }
+    }
+
+    fn configure(cs: &mut ConstraintSystem<Fp>) -> Self::Config {
+        CoolChip::configure(cs)
+    }
+
+    fn synthesize(&self, config: Self::Config, mut layouter: impl Layouter<Fp>) -> Result<(), Error> {
+        let chip = CoolChip::construct(config);
+        chip.alloc_and_check(&mut layouter, self.a)
+    }
+}
+
+fn main() {
+    let start = Instant::now();
+    let params: Params<EqAffine> = Params::new(4);
+
+    let empty_circuit = CoolCircuit { a: None };
+    let vk = keygen_vk(&params, &empty_circuit).expect("keygen_vk should not fail");
+    let pk = keygen_pk(&params, vk, &empty_circuit).expect("keygen_pk should not fail");
+    println!("Setup: [{:?}]", start.elapsed());
+
+    let start = Instant::now();
+    let circuit = CoolCircuit {
+        a: Some(Fp::from(2)),
+    };
+
+    // Create a proof
+    let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]);
+    create_proof(&params, &pk, &[circuit], &[&[]], &mut transcript)
+        .expect("proof generation should not fail");
+    let proof = transcript.finalize();
+    println!("Prove: [{:?}]", start.elapsed());
+
+    let start = Instant::now();
+    let msm = params.empty_msm();
+    let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof[..]);
+    let verification = verify_proof(&params, pk.get_vk(), msm, &[&[]], &mut transcript);
+    if let Err(err) = verification {
+        panic!("error {:?}", err);
+    }
+    let guard = verification.unwrap();
+    let msm = guard.clone().use_challenges();
+    assert!(msm.eval());
+    println!("Verify: [{:?}]", start.elapsed());
+}
+

+ 267 - 0
example/halo2/src/bin/simple4.rs

@@ -0,0 +1,267 @@
+use halo2::{
+    circuit::{SimpleFloorPlanner, Cell, Chip, Layouter},
+    pasta::{EqAffine, Fp},
+    plonk::{Advice, Any, Circuit, Column, ConstraintSystem, Error, Expression, Selector, create_proof, verify_proof, keygen_vk, keygen_pk, Permutation},
+    poly::{commitment::{Blind, Params}, Rotation},
+    transcript::{Blake2bRead, Blake2bWrite, Challenge255},
+};
+use group::Curve;
+use std::time::Instant;
+
+#[derive(Clone, Debug)]
+struct CoolConfig {
+    a_col: Column<Advice>,
+    b_col: Column<Advice>,
+    permute: Permutation,
+    s_range: Selector,
+    s_mul: Selector,
+    s_pub: Selector,
+}
+
+struct CoolChip {
+    config: CoolConfig
+}
+
+impl Chip<Fp> for CoolChip {
+    type Config = CoolConfig;
+    type Loaded = ();
+
+    fn config(&self) -> &Self::Config {
+        &self.config
+    }
+
+    fn loaded(&self) -> &Self::Loaded {
+        &()
+    }
+}
+
+#[derive(Clone, Debug)]
+struct Number {
+    cell: Cell,
+    value: Option<Fp>,
+}
+
+impl CoolChip {
+    fn construct(config: CoolConfig) -> Self {
+        Self { config }
+    }
+
+    fn configure(cs: &mut ConstraintSystem<Fp>) -> CoolConfig {
+        let a_col = cs.advice_column();
+        let b_col = cs.advice_column();
+
+        let instance = cs.instance_column();
+
+        let permute = {
+            // Convert advice columns into an "any" columns.
+            let cols: [Column<Any>; 2] = [a_col.into(), b_col.into()];
+            Permutation::new(cs, &cols)
+        };
+
+        let s_range = cs.selector();
+        let s_mul = cs.selector();
+        let s_pub = cs.selector();
+
+        cs.create_gate("check", |cs| {
+            let a = cs.query_advice(a_col, Rotation::cur());
+            let s_range = cs.query_selector(s_range);
+            vec![s_range * (a - Expression::Constant(Fp::from(2)))]
+        });
+
+        cs.create_gate("mul", |cs| {
+            let lhs = cs.query_advice(a_col, Rotation::cur());
+            let rhs = cs.query_advice(b_col, Rotation::cur());
+            let out = cs.query_advice(a_col, Rotation::next());
+            let s_mul = cs.query_selector(s_mul);
+
+            vec![s_mul * (lhs * rhs + out * -Fp::one())]
+        });
+
+        cs.create_gate("public input", |cs| {
+            let a = cs.query_advice(b_col, Rotation::cur());
+            let p = cs.query_instance(instance, Rotation::cur());
+            let s = cs.query_selector(s_pub);
+
+            vec![s * (p + a * -Fp::one())]
+        });
+
+        CoolConfig { a_col, b_col, permute, s_range, s_mul, s_pub }
+    }
+
+    fn alloc_left(
+        &self,
+        layouter: &mut impl Layouter<Fp>,
+        value: Option<Fp>
+    ) -> Result<Number, Error> {
+        layouter.assign_region(
+            || "load left private input",
+            |mut region| {
+                let cell = region.assign_advice(
+                    || "private input 'a'",
+                    self.config.a_col,
+                    0,
+                    || value.ok_or(Error::SynthesisError),
+                )?;
+                Ok(Number { cell, value })
+            }
+        )
+    }
+
+    fn check(
+        &self,
+        layouter: &mut impl Layouter<Fp>,
+        number: Number
+    ) -> Result<(), Error> {
+        layouter.assign_region(
+            || "load private inputs",
+            |mut region| {
+                self.config.s_range.enable(&mut region, 0)?;
+
+                let a = region.assign_advice(
+                    || "lhs",
+                    self.config.a_col,
+                    0,
+                    || number.value.ok_or(Error::SynthesisError),
+                )?;
+                region.constrain_equal(&self.config.permute, number.cell, a)?;
+
+                Ok(())
+            },
+        )
+    }
+
+    fn mul(
+        &self,
+        layouter: &mut impl Layouter<Fp>,
+        a: Number,
+        b: Number
+    ) -> Result<Number, Error> {
+        let mut out = None;
+        layouter.assign_region(
+            || "mul",
+            |mut region| {
+                self.config.s_mul.enable(&mut region, 0)?;
+
+                let lhs = region.assign_advice(
+                    || "lhs",
+                    self.config.a_col,
+                    0,
+                    || a.value.ok_or(Error::SynthesisError),
+                )?;
+                let rhs = region.assign_advice(
+                    || "rhs",
+                    self.config.b_col,
+                    0,
+                    || b.value.ok_or(Error::SynthesisError),
+                )?;
+                region.constrain_equal(&self.config.permute, a.cell, lhs)?;
+                region.constrain_equal(&self.config.permute, b.cell, rhs)?;
+
+                let value = a.value.and_then(|a| b.value.map(|b| a * b));
+                let cell = region.assign_advice(
+                    || "lhs * rhs",
+                    self.config.a_col,
+                    1,
+                    || value.ok_or(Error::SynthesisError),
+                )?;
+
+                out = Some(Number { cell, value });
+                Ok(())
+            },
+        )?;
+
+        Ok(out.unwrap())
+    }
+
+    fn expose_public(&self, layouter: &mut impl Layouter<Fp>, num: Number) -> Result<(), Error> {
+        layouter.assign_region(
+            || "expose public",
+            |mut region| {
+                self.config.s_pub.enable(&mut region, 0)?;
+
+                let out = region.assign_advice(
+                    || "public advice",
+                    self.config.b_col,
+                    0,
+                    || num.value.ok_or(Error::SynthesisError),
+                )?;
+                region.constrain_equal(&self.config.permute, num.cell, out)?;
+
+                Ok(())
+            },
+        )
+    }
+}
+
+#[derive(Clone)]
+struct CoolCircuit {
+    // Private input.
+    a: Option<Fp>,
+}
+
+impl Circuit<Fp> for CoolCircuit {
+    type Config = CoolConfig;
+    type FloorPlanner = SimpleFloorPlanner;
+
+    fn without_witnesses(&self) -> Self {
+        Self { a: None }
+    }
+
+    fn configure(cs: &mut ConstraintSystem<Fp>) -> Self::Config {
+        CoolChip::configure(cs)
+    }
+
+    fn synthesize(&self, config: Self::Config, mut layouter: impl Layouter<Fp>) -> Result<(), Error> {
+        let chip = CoolChip::construct(config);
+        let a = chip.alloc_left(&mut layouter, self.a)?;
+        chip.check(&mut layouter, a.clone())?;
+        let a2 = chip.mul(&mut layouter, a.clone(), a)?;
+        chip.expose_public(&mut layouter, a2)?;
+        Ok(())
+    }
+}
+
+fn main() {
+    let k = 6;
+
+    let start = Instant::now();
+    let params: Params<EqAffine> = Params::new(k);
+
+    let empty_circuit = CoolCircuit { a: None };
+    let vk = keygen_vk(&params, &empty_circuit).expect("keygen_vk should not fail");
+    let pk = keygen_pk(&params, vk, &empty_circuit).expect("keygen_pk should not fail");
+    println!("Setup: [{:?}]", start.elapsed());
+
+    let start = Instant::now();
+    let circuit = CoolCircuit {
+        a: Some(Fp::from(2)),
+    };
+
+    let mut public_inputs = pk.get_vk().get_domain().empty_lagrange();
+    public_inputs[4] = Fp::from(4);
+
+    // Create a proof
+    let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]);
+    create_proof(&params, &pk, &[circuit], &[&[public_inputs.clone()]], &mut transcript)
+        .expect("proof generation should not fail");
+    let proof = transcript.finalize();
+    println!("Prove: [{:?}]", start.elapsed());
+
+    let pubinput = params
+        .commit_lagrange(&public_inputs, Blind::default())
+        .to_affine();
+    let pubinput_slice = &[pubinput];
+
+    let start = Instant::now();
+    let msm = params.empty_msm();
+    let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof[..]);
+    let verification = verify_proof(&params, pk.get_vk(), msm, &[pubinput_slice], &mut transcript);
+    if let Err(err) = verification {
+        panic!("error {:?}", err);
+    }
+    let guard = verification.unwrap();
+    let msm = guard.clone().use_challenges();
+    assert!(msm.eval());
+    println!("Verify: [{:?}]", start.elapsed());
+}
+

+ 16 - 0
example/halo2/src/circuit.rs

@@ -0,0 +1,16 @@
+use halo2::{
+    pasta::pallas,
+    plonk::{Advice, Column, Instance as InstanceColumn, Selector},
+};
+
+use halo2_ecc::chip::EccConfig;
+use halo2_poseidon::pow5t3::Pow5T3Config as PoseidonConfig;
+
+#[derive(Clone, Debug)]
+pub struct Config {
+    pub primary: Column<InstanceColumn>,
+    pub q_add: Selector,
+    pub advices: [Column<Advice>; 10],
+    pub ecc_config: EccConfig,
+    pub poseidon_config: PoseidonConfig<pallas::Base>,
+}

+ 19 - 0
example/halo2/src/lib.rs

@@ -0,0 +1,19 @@
+pub mod circuit;
+
+use halo2::{
+    arithmetic::{CurveExt, FieldExt},
+    pasta::{Ep, Fq},
+};
+use orchard::constants::fixed_bases::{
+    VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_R_BYTES, VALUE_COMMITMENT_V_BYTES,
+};
+
+#[allow(non_snake_case)]
+pub fn pedersen_commitment(value: u64, blind: Fq) -> Ep {
+    let hasher = Ep::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION);
+    let V = hasher(&VALUE_COMMITMENT_V_BYTES);
+    let R = hasher(&VALUE_COMMITMENT_R_BYTES);
+    let value = Fq::from_u64(value);
+
+    V * value + R * blind
+}

+ 460 - 0
old/compile.py

@@ -0,0 +1,460 @@
+import argparse
+import sys
+from enum import Enum
+
+alloc_commands = {
+    "param": 1,
+    "private": 1,
+    "public": 1,
+}
+
+op_commands = {
+    "set": 2,
+    "mul": 2,
+    "add": 2, 
+    "sub": 2,
+    "divide": 2,
+    "double": 1,
+    "square": 1,
+    "invert": 1,
+    "unpack_bits": 3,
+    "load": 2,
+    "local": 1,
+    "debug": 1,
+    "dump_alloc": 0,
+    "dump_local": 0,
+}
+
+constraint_commands = {
+    "lc0_add": 1,
+    "lc1_add": 1,
+    "lc2_add": 1,
+    "lc0_sub": 1,
+    "lc1_sub": 1,
+    "lc2_sub": 1,
+    "lc0_add_one": 0,
+    "lc1_add_one": 0,
+    "lc2_add_one": 0,
+    "lc0_sub_one": 0,
+    "lc1_sub_one": 0,
+    "lc2_sub_one": 0,
+    "lc0_add_coeff": 2,
+    "lc1_add_coeff": 2,
+    "lc2_add_coeff": 2,
+    "lc0_add_constant": 1,
+    "lc1_add_constant": 1,
+    "lc2_add_constant": 1,
+    "enforce": 0,
+    "lc_coeff_reset": 0,
+    "lc_coeff_double": 0,
+}
+
+def eprint(*args):
+    print(*args, file=sys.stderr)
+
+class Line:
+
+    def __init__(self, text, line_number):
+        self.text = text
+        self.orig = text
+        self.lineno = line_number
+
+        self.clean()
+
+    def clean(self):
+        # Remove the comments
+        self.text = self.text.split("#", 1)[0]
+        # Remove whitespace
+        self.text = self.text.strip()
+
+    def is_empty(self):
+        return bool(self.text)
+
+    def __repr__(self):
+        return "Line %s: %s" % (self.lineno, self.orig.lstrip())
+
+    def command(self):
+        if not self.is_empty():
+            return None
+        return self.text.split(" ")[0]
+
+    def args(self):
+        if not self.is_empty():
+            return None
+        return self.text.split()[1:]
+
+def clean(contents):
+    # Split input into lines
+    contents = contents.split("\n")
+    contents = [Line(line, i + 1) for i, line in enumerate(contents)]
+    # Remove empty blank lines
+    contents = [line for line in contents if line.is_empty()]
+    return contents
+
+def divide_sections(contents):
+    state = "NOSCOPE"
+    segments = {}
+    current_segment = []
+    contract_name = None
+
+    for line in contents:
+        if line.command() == "contract":
+            if len(line.args()) != 1:
+                eprint("error: missing contract name")
+                eprint(line)
+                return None
+            contract_name = line.args()[0]
+
+            if state == "NOSCOPE":
+                assert not current_segment
+                state = "INSCOPE"
+                continue
+            else:
+                assert state == "INSCOPE"
+                eprint("error: double contract entry violation")
+                eprint(line)
+                return None
+        elif line.command() == "end":
+            if len(line.args()) != 0:
+                eprint("error: end takes no args")
+                eprint(line)
+                return None
+
+            if state == "NOSCOPE":
+                eprint("error: missing contract start for end")
+                eprint(line)
+                return None
+            else:
+                assert state == "INSCOPE"
+                state = "NOSCOPE"
+                segments[contract_name] = current_segment
+                current_segment = []
+                continue
+        elif state == "NOSCOPE":
+            # Ignore lines outside any contract
+            continue
+
+        current_segment.append(line)
+
+    if state != "NOSCOPE":
+        eprint("error: reached end of file with unclosed scope")
+        return None
+
+    return segments
+
+def extract_relevant_lines(contract, commands_table):
+    relevant_lines = []
+
+    for line in contract:
+        command = line.command()
+
+        if command not in commands_table.keys():
+            continue
+
+        define = commands_table[command]
+
+        if len(line.args()) != define:
+            eprint("error: wrong number of args")
+            return None
+
+        relevant_lines.append(line)
+
+    return relevant_lines
+
+class VariableType(Enum):
+    PUBLIC = 1
+    PRIVATE = 2
+
+class Variable:
+
+    def __init__(self, symbol, index, type, is_param):
+        self.symbol = symbol
+        self.index = index
+        self.type = type
+        self.is_param = is_param
+
+    def __repr__(self):
+        return "<Variable %s:%s>" % (self.symbol, self.index)
+
+def generate_alloc_table(contract):
+    relevant_lines = extract_relevant_lines(contract, alloc_commands)
+    alloc_table = {}
+    for i, line in enumerate(relevant_lines):
+        assert len(line.args()) == 1
+        symbol = line.args()[0]
+
+        command = line.command()
+
+        if command == "param":
+            type = VariableType.PRIVATE
+            is_param = True
+        elif command == "private":
+            type = VariableType.PRIVATE
+            is_param = False
+        elif command == "public":
+            type = VariableType.PUBLIC
+            is_param = False
+        else:
+            assert False
+
+        if symbol in alloc_table:
+            eprint("error: duplicate symbol '%s'" % symbol)
+            eprint(line)
+            return None
+
+        alloc_table[symbol] = Variable(symbol, i, type, is_param)
+
+    return alloc_table
+
+class Operation:
+
+    def __init__(self, line, indexes):
+        self.command = line.command()
+        self.args = indexes
+        self.line = line
+
+class VariableRefType(Enum):
+    AUX = 1
+    LOCAL = 2
+    CONST = 3
+
+class VariableRef:
+
+    def __init__(self, type, index):
+        self.type = type
+        self.index = index
+
+    def __repr__(self):
+        return "%s(%s)" % (self.type.name, self.index)
+
+def symbols_list_to_refs(line, alloc, local_vars, constants):
+    indexes = []
+    for symbol in line.args():
+        if symbol in alloc:
+            # Lookup variable index
+            index = alloc[symbol].index
+            index = VariableRef(VariableRefType.AUX, index)
+        elif symbol in local_vars:
+            index = local_vars[symbol]
+            index = VariableRef(VariableRefType.LOCAL, index)
+        elif symbol in constants:
+            index = constants[symbol][0]
+            index = VariableRef(VariableRefType.CONST, index)
+        else:
+            eprint("error: missing unallocated symbol '%s'" % symbol)
+            eprint(line)
+            return None
+        indexes.append(index)
+    return indexes
+
+def generate_ops_table(contract, alloc, constants):
+    relevant_lines = extract_relevant_lines(contract, op_commands)
+    ops = []
+    local_vars = {}
+    for line in relevant_lines:
+        # This is a special case which creates a new local stack value
+        if line.command() == "local":
+            assert len(line.args()) == 1
+            symbol = line.args()[0]
+            local_vars[symbol] = len(local_vars)
+            indexes = []
+        else:
+            if (indexes := symbols_list_to_refs(line, alloc, 
+                                                local_vars, constants)) is None:
+                return None
+
+            # Handle this here directly since only the
+            # load command deals with constants
+            if line.command() == "load":
+                assert len(indexes) == 2
+                # This is the only command which uses consts
+                if indexes[1].type != VariableRefType.CONST:
+                    eprint("error: load command takes a const argument")
+                    eprint(line)
+                    return None
+            elif any(index.type == VariableRefType.CONST for index in indexes):
+                eprint("error: invalid const arg")
+                eprint(line)
+                return None
+
+        ops.append(Operation(line, indexes))
+    return ops
+
+class Constraint:
+
+    def __init__(self, line, lcargs):
+        self.command = line.command()
+        self.args = lcargs
+        self.line = line
+
+    def args_comment(self):
+        return ", ".join("%s" % symbol for symbol in self.line.args())
+
+def symbols_list_to_lcargs(line, alloc, constants):
+    lcargs = []
+    for symbol in line.args():
+        if symbol in alloc:
+            # Lookup variable index
+            index = alloc[symbol].index
+            lcargs.append(index)
+        elif symbol in constants:
+            value = constants[symbol]
+            lcargs.append(value)
+        else:
+            eprint("error: missing unallocated symbol '%s'" % symbol)
+            eprint(line)
+            return None
+    return lcargs
+
+def generate_constraints_table(contract, alloc, constants):
+    relevant_lines = extract_relevant_lines(contract, constraint_commands)
+    constraints = []
+    for line in relevant_lines:
+        if (lcargs := symbols_list_to_lcargs(line, alloc, constants)) is None:
+            return None
+        constraints.append(Constraint(line, lcargs))
+    return constraints
+
+class Contract:
+
+    def __init__(self, constants, alloc, ops, constraints):
+        self.constants = constants
+        self.alloc = alloc
+        self.ops = ops
+        self.constraints = constraints
+
+    def __repr__(self):
+        repr_str = ""
+
+        repr_str += "Constants:\n"
+        for symbol, value in self.constants.items():
+            repr_str += "    // %s\n" % symbol
+            repr_str += "    %s: %s\n" % value
+
+        repr_str += "Alloc table:\n"
+        for symbol, variable in self.alloc.items():
+            repr_str += "    // %s\n" % symbol
+            repr_str += "    %s %s\n" % (variable.type, variable.index)
+
+        repr_str += "Operations:\n"
+        for op in self.ops:
+            repr_str += "    // %s\n" % op.line
+            repr_str += "    %s %s\n" % (op.command, op.args)
+
+        repr_str += "Constraints:\n"
+        for constraint in self.constraints:
+            if constraint.args:
+                repr_str += "    // %s\n" % constraint.args_comment()
+            repr_str += "    %s %s\n" % (constraint.command, constraint.args)
+
+        repr_str += "Stats:\n"
+        repr_str += "    Constants: %s\n" % len(self.constants)
+        repr_str += "    Alloc: %s\n" % len(self.alloc)
+        repr_str += "    Operations: %s\n" % len(self.ops)
+        repr_str += "    Constraint Instructions: %s\n" % len(self.constraints)
+
+        return repr_str
+
+def compile(contract, constants):
+    # Allocation table
+    # symbol: Private/Public, is_param, index
+    if (alloc := generate_alloc_table(contract)) is None:
+        return None
+    # Operations lines list
+    if (ops := generate_ops_table(contract, alloc, constants)) is None:
+        return None
+    # Constraint commands
+    if (constraints := generate_constraints_table(
+            contract, alloc, constants)) is None:
+        return None
+    return Contract(constants, alloc, ops, constraints)
+
+def parse_constants(contents):
+    relevant_lines = [line for line in contents if line.command() == "constant"]
+    constants = {}
+    for line in relevant_lines:
+        assert line.command() == "constant"
+        if len(line.args()) != 2:
+            eprint("error: wrong number of args for constant")
+            eprint(line)
+            return None
+        symbol, value = line.args()
+
+        try:
+            int(value, 16)
+        except ValueError:
+            eprint("error: invalid constant value for '%s'" % symbol)
+            eprint(line)
+            return None
+
+        if len(value) != 32*2 + 2 or value[:2] != "0x":
+            eprint("error: invalid hex value for constant")
+            eprint(line)
+            return None
+
+        # Remove 0x prefix
+        value = value[2:]
+
+        constants[symbol] = (len(constants), value)
+    return constants
+
+def process(contents):
+    # Remove left whitespace
+    contents = clean(contents)
+    # Parse all constants
+    if (constants := parse_constants(contents)) is None:
+        return None
+    # Divide into contract sections
+    if (pre_contracts := divide_sections(contents)) is None:
+        return None
+    # Process each contract
+    contracts = {}
+    for contract_name, pre_contract in pre_contracts.items():
+        if (contract := compile(pre_contract, constants)) is None:
+            return None
+        contracts[contract_name] = contract
+    return contracts
+
+def main(argv):
+    parser = argparse.ArgumentParser()
+    parser.add_argument("filename", help="VM PISM file: proofs/vm.pism")
+    parser.add_argument("--output", type=argparse.FileType('wb', 0),
+                        default=sys.stdout.buffer, help="Output file")
+    group = parser.add_mutually_exclusive_group()
+    group.add_argument('--display', action='store_true',
+                       help="show the compiled code in human readable format")
+    group.add_argument('--rust', action='store_true',
+                       help="output compiled code to rust for testing")
+    group.add_argument('--supervisor', action='store_true',
+                       help="output compiled code to zkvm supervisor")
+    args = parser.parse_args()
+
+    src_filename = args.filename
+    contents = open(src_filename).read()
+    if (contracts := process(contents)) is None:
+        return -2
+
+    def default_display():
+        for contract_name, contract in contracts.items():
+            print("Contract:", contract_name)
+            print(contract)
+
+    if args.display:
+        default_display()
+    elif args.rust:
+        import compile_export_rust
+        for contract_name, contract in contracts.items():
+            compile_export_rust.display(contract)
+    elif args.supervisor:
+        import compile_export_supervisor
+        for contract_name, contract in contracts.items():
+            compile_export_supervisor.export(args.output, contract_name,
+                                             contract)
+    else:
+        default_display()
+
+    return 0
+
+if __name__ == "__main__":
+    sys.exit(main(sys.argv))
+

+ 40 - 0
old/mint.aux

@@ -0,0 +1,40 @@
+{
+    "constants": {
+        "G_SPEND": {
+            "maps_to": "zcash_proofs::constants::SPENDING_KEY_GENERATOR"
+        },
+        "G_PROOF": {
+            "maps_to": "zcash_proofs::constants::PROOF_GENERATION_KEY_GENERATOR"
+        },
+        "CRH_IVK": {
+            "maps_to": "zcash_primitives::constants::CRH_IVK_PERSONALIZATION"
+        },
+        "PRF_NF": {
+            "maps_to": "zcash_primitives::constants::PRF_NF_PERSONALIZATION"
+        },
+        "G_VCV": {
+            "maps_to": "zcash_proofs::constants::VALUE_COMMITMENT_VALUE_GENERATOR"
+        },
+        "G_VCR": {
+            "maps_to": "zcash_proofs::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR"
+        },
+        "JUBJUB_FR_CAPACITY": {
+            "maps_to": "jubjub::Fr::CAPACITY as usize"
+        },
+        "NOTE_COMMIT": {
+            "maps_to": "pedersen_hash::Personalization::NoteCommitment"
+        },
+        "MERKLE_0": {
+            "maps_to": "pedersen_hash::Personalization::MerkleTree(0)"
+        },
+        "MERKLE_1": {
+            "maps_to": "pedersen_hash::Personalization::MerkleTree(1)"
+        },
+        "MERKLE_2": {
+            "maps_to": "pedersen_hash::Personalization::MerkleTree(2)"
+        },
+        "MERKLE_3": {
+            "maps_to": "pedersen_hash::Personalization::MerkleTree(3)"
+        }
+    }
+}

+ 528 - 0
old/pism.py

@@ -0,0 +1,528 @@
+import json
+import os
+import sys
+
+import codegen
+
+symbol_table = {
+    "contract": 1,
+    "param": 2,
+    "start": 0,
+    "end": 0,
+}
+
+types_map = {
+    "U64": "u64",
+    "Fr": "jubjub::Fr",
+    "Point": "jubjub::SubgroupPoint",
+    "Scalar": "bls12_381::Scalar",
+    "Bool": "bool"
+}
+
+feature_includes = {"G_SPEND": "use crate::crypto::merkle_node::SAPLING_COMMITMENT_TREE_DEPTH;\n"}
+
+command_desc = {
+    "witness": (
+        ("EdwardsPoint",    True),
+        ("Point",           False)
+    ),
+    "assert_not_small_order": (
+        ("EdwardsPoint",    False),
+    ),
+    "u64_as_binary_le": (
+        ("Vec<Boolean>",    True),
+        ("U64",             False),
+    ),
+    "fr_as_binary_le": (
+        ("Vec<Boolean>",    True),
+        ("Fr",              False)
+    ),
+    "ec_mul_const": (
+        ("EdwardsPoint",    True),
+        ("Vec<Boolean>",    False),
+        ("FixedGenerator",  False)
+    ),
+    "ec_mul": (
+        ("EdwardsPoint",    True),
+        ("Vec<Boolean>",    False),
+        ("EdwardsPoint",    False),
+    ),
+    "ec_add": (
+        ("EdwardsPoint",    True),
+        ("EdwardsPoint",    False),
+        ("EdwardsPoint",    False),
+    ),
+    "ec_repr": (
+        ("Vec<Boolean>",    True),
+        ("EdwardsPoint",    False),
+    ),
+    "ec_get_u": (
+        ("ScalarNum",       True),
+        ("EdwardsPoint",    False),
+    ),
+    "emit_ec": (
+        ("EdwardsPoint",    False),
+    ),
+    "alloc_binary": (
+        ("Vec<Boolean>",    True),
+    ),
+    "binary_clone": (
+        ("Vec<Boolean>",    True),
+        ("Vec<Boolean>",    False),
+    ),
+    "binary_extend": (
+        ("Vec<Boolean>",    False),
+        ("Vec<Boolean>",    False),
+    ),
+    "binary_push": (
+        ("Vec<Boolean>",    False),
+        ("Boolean",         False),
+    ),
+    "binary_truncate": (
+        ("Vec<Boolean>",    False),
+        ("BinarySize",      False),
+    ),
+    "static_assert_binary_size": (
+        ("Vec<Boolean>",    False),
+        ("INTEGER",         False),
+    ),
+    "blake2s": (
+        ("Vec<Boolean>",    True),
+        ("Vec<Boolean>",    False),
+        ("BlakePersonalization", False),
+    ),
+    "pedersen_hash": (
+        ("EdwardsPoint",    True),
+        ("Vec<Boolean>",    False),
+        ("PedersenPersonalization", False),
+    ),
+    "emit_binary": (
+        ("Vec<Boolean>",    False),
+    ),
+    "alloc_bit": (
+        ("Boolean",         True),
+        ("Bool",            False),
+    ),
+    "alloc_const_bit": (
+        ("Boolean",         True),
+        ("BOOL_CONST",      False),
+    ),
+    "clone_bit": (
+        ("Boolean",         True),
+        ("Boolean",         False),
+    ),
+    "alloc_scalar": (
+        ("ScalarNum",       True),
+        ("Scalar",          False),
+    ),
+    "scalar_as_binary": (
+        ("Vec<Boolean>",    True),
+        ("ScalarNum",       False),
+    ),
+    "emit_scalar": (
+        ("ScalarNum",       False),
+    ),
+    "scalar_enforce_equal": (
+        ("ScalarNum",       False),
+        ("ScalarNum",       False),
+    ),
+    "conditionally_reverse": (
+        ("ScalarNum",       True),
+        ("ScalarNum",       True),
+        ("ScalarNum",       False),
+        ("ScalarNum",       False),
+        ("Boolean",         False),
+    ),
+}
+
+def eprint(*args):
+    print(*args, file=sys.stderr)
+
+class Line:
+
+    def __init__(self, text, line_number):
+        self.text = text
+        self.orig = text
+        self.lineno = line_number
+
+        self.clean()
+
+    def clean(self):
+        # Remove the comments
+        self.text = self.text.split("#", 1)[0]
+        # Remove whitespace
+        self.text = self.text.strip()
+
+    def is_empty(self):
+        return bool(self.text)
+
+    def __repr__(self):
+        return "Line %s: %s" % (self.lineno, self.orig.lstrip())
+
+    def command(self):
+        if not self.is_empty():
+            return None
+        return self.text.split(" ")[0]
+
+    def args(self):
+        if not self.is_empty():
+            return None
+        return self.text.split(" ")[1:]
+
+def clean(contents):
+    # Split input into lines
+    contents = contents.split("\n")
+    contents = [Line(line, i) for i, line in enumerate(contents)]
+    # Remove empty blank lines
+    contents = [line for line in contents if line.is_empty()]
+    return contents
+
+def make_segments(contents):
+    constants = [line for line in contents if line.command() == "constant"]
+
+    segments = []
+    current_segment = []
+    for line in contents:
+        if line.command() == "contract":
+            current_segment = []
+
+        current_segment.append(line)
+
+        if line.command() == "end":
+            segments.append(current_segment)
+            current_segment = []
+
+    return constants, segments
+
+def build_constants_table(constants):
+    table = {}
+    for line in constants:
+        args = line.args()
+        if len(args) != 2:
+            eprint("error: wrong number of args")
+            eprint(line)
+            return None
+        name, type = args
+        table[name] = type
+    return table
+
+def extract(segment):
+    assert segment
+    # Does it have a declaration?
+    if not segment[0].command() == "contract":
+        eprint("error: missing contract declaration")
+        eprint(segment[0])
+        return None
+    # Does it have an end?
+    if not segment[-1].command() == "end":
+        eprint("error: missing contract end")
+        eprint(segment[-1])
+        return None
+    # Does it have a start?
+    if not [line for line in segment if line.command() == "start"]:
+        eprint("error: missing contract start")
+        eprint(segment[0])
+        return None
+
+    for line in segment:
+        command, args = line.command(), line.args()
+
+        if command in symbol_table:
+            if symbol_table[command] != len(args):
+                eprint("error: wrong number of args for command '%s'" % command)
+                eprint(line)
+                return None
+        elif command in command_desc:
+            if len(command_desc[command]) != len(args):
+                eprint("error: wrong number of args for command '%s'" % command)
+                eprint(line)
+                return None
+        else:
+            eprint("error: missing symbol for command '%s'" % command)
+            eprint(line)
+            return None
+
+    contract_name = segment[0].args()[0]
+
+    start_index = [index for index, line in enumerate(segment)
+                   if line.command() == "start"]
+    if len(start_index) > 1:
+        eprint("error: multiple start statements in contract '%s'" %
+               contract_name)
+        for index in start_index:
+            eprint(segment[index])
+        eprint("Aborting.")
+        return None
+    assert len(start_index) == 1
+    start_index = start_index[0]
+
+    header = segment[1:start_index]
+    code = segment[start_index + 1:-1]
+
+    params = {}
+    for param_decl in header:
+        args = param_decl.args()
+        assert len(args) == 2
+        name, type = args
+        params[name] = type
+
+    program = []
+    for line in code:
+        command, args = line.command(), line.args()
+        program.append((command, args, line))
+
+    return Contract(contract_name, params, program)
+
+def to_initial_caps(snake_str):
+    components = snake_str.split("_")
+    return "".join(x.title() for x in components)
+
+class Contract:
+
+    def __init__(self, name, params, program):
+        self.name = name
+        self.params = params
+        self.program = program
+
+    def _includes(self):
+        return \
+r"""#![allow(unused_imports)]
+#![allow(unused_mut)]
+use bellman::{
+    gadgets::{
+        boolean,
+        boolean::{AllocatedBit, Boolean},
+        multipack,
+        blake2s,
+        num,
+        Assignment,
+    },
+    groth16, Circuit, ConstraintSystem, SynthesisError,
+};
+use bls12_381::Bls12;
+use ff::{PrimeField, Field};
+use group::Curve;
+use zcash_proofs::circuit::{ecc, pedersen_hash};
+"""
+
+    def _compile_header(self):
+        code = "pub struct %s {\n" % to_initial_caps(self.name)
+        for param_name, param_type in self.params.items():
+            try:
+                mapped_type = types_map[param_type]
+            except KeyError:
+                return None
+            code += "    pub %s: Option<%s>,\n" % (param_name, mapped_type)
+        code += "}\n"
+        return code
+
+    def _compile_body(self):
+        self.stack = {}
+        code = "\n"
+        #indent = " " * 8
+        for command, args, line in self.program:
+            if (code_text := self._compile_line(command, args, line)) is None:
+                return None
+            code += "// %s\n" % str(line)
+            code += code_text + "\n\n"
+        return code
+
+    def _preprocess_args(self, args, line):
+        nargs = []
+        for arg in args:
+            if not arg.startswith("param:"):
+                nargs.append((arg, False))
+                continue
+            _, argname = arg.split(":", 1)
+            if argname not in self.params:
+                eprint("error: non-existant param referenced")
+                eprint(line)
+                return None
+            nargs.append((argname, True))
+        return nargs
+
+    def type_checking(self, command, args, line):
+        assert command in command_desc
+        type_list = command_desc[command]
+        if len(type_list) != len(args):
+            eprint("error: wrong number of arguments!")
+            eprint(line)
+            return False
+
+        for (expected_type, new_val), (argname, is_param) in \
+            zip(type_list, args):
+            # Only type check input arguments, not output values
+            if new_val:
+                continue
+
+            if expected_type == "INTEGER" or expected_type == "BOOL_CONST":
+                continue
+
+            if is_param:
+                actual_type = self.params[argname]
+            elif argname in self.constants:
+                actual_type = self.constants[argname]
+            else:
+                # Check the stack here
+                if argname not in self.stack:
+                    eprint("error: cannot find value '%s' on the stack!" %
+                           argname)
+                    eprint(line)
+                    return False
+
+                actual_type = self.stack[argname]
+
+            if expected_type != actual_type:
+                eprint("error: wrong type for arg '%s'!" % argname)
+                eprint(line)
+                return False
+
+        return True
+
+    def _check_args(self, command, args, line):
+        assert command in command_desc
+        type_list = command_desc[command]
+        assert len(type_list) == len(args)
+
+        for (expected_type, is_new_val), (arg, is_param) in zip(type_list, args):
+            if is_param:
+                continue
+            if is_new_val:
+                continue
+            if arg in self.stack:
+                continue
+            if arg in self.constants:
+                continue
+
+            if expected_type == "INTEGER" or expected_type == "BOOL_CONST":
+                continue
+
+            eprint("error: cannot find '%s' in the stack" % arg)
+            eprint(line)
+            return False
+        return True
+
+    def _compile_line(self, command, args, line):
+        if (args := self._preprocess_args(args, line)) is None:
+            return None
+        if not self.type_checking(command, args, line):
+            return None
+
+        if not self._check_args(command, args, line):
+            return None
+
+        self.modify_stack(command, args)
+
+        args = [self.carg(arg) for arg in args]
+
+        try:
+            codegen_method = getattr(codegen, command)
+        except AttributeError:
+            eprint("error: missing command '%s' does not exist" % command)
+            eprint(line)
+            return None
+
+        return codegen_method(line, *args)
+
+    def carg(self, arg):
+        argname, is_param = arg
+        if is_param:
+            return "self.%s" % argname
+        if argname in self.rename_consts:
+            return self.rename_consts[argname]
+        return argname
+
+    def modify_stack(self, command, args):
+        type_list = command_desc[command]
+        assert len(type_list) == len(args)
+        for (expected_type, new_val), (argname, is_param) in \
+            zip(type_list, args):
+            if is_param:
+                assert not new_val
+                continue
+
+            # Now apply the new values to the stack
+            if new_val:
+                self.stack[argname] = expected_type
+
+    def compile(self, constants, aux):
+        self.constants = constants
+        code = ""
+
+        code += self._includes()
+
+        self.rename_consts = {}
+        if "constants" in aux:
+            for const_name, value in aux["constants"].items():
+                if "maps_to" not in value:
+                    eprint("error: bad aux config '%s', missing maps_to" %
+                           const_name)
+                    return None
+
+                if const_name in feature_includes:
+                    code += feature_includes[const_name]
+
+                mapped_type = value["maps_to"]
+                self.rename_consts[const_name] = mapped_type
+
+        code += "\n"
+
+        if (header := self._compile_header()) is None:
+            return None
+        code += header
+
+        code += \
+r"""impl Circuit<bls12_381::Scalar> for %s {
+    fn synthesize<CS: ConstraintSystem<bls12_381::Scalar>>(
+        self,
+        cs: &mut CS,
+    ) -> Result<(), SynthesisError> {
+""" % to_initial_caps(self.name)
+
+        if (body := self._compile_body()) is None:
+            return None
+        code += body
+        code += "Ok(())\n"
+
+        code += "    }\n"
+        code += "}\n"
+
+        return code
+
+def process(contents, aux):
+    contents = clean(contents)
+    constants, segments = make_segments(contents)
+    if (constants := build_constants_table(constants)) is None:
+        return False
+
+    codes = []
+    for segment in segments:
+        if (contract := extract(segment)) is None:
+            return False
+        if (code := contract.compile(constants, aux)) is None:
+            return False
+        codes.append(code)
+
+    # Success! Output finished product.
+    [print(code) for code in codes]
+
+    return True
+
+def main(argv):
+    if len(argv) != 3:
+        eprint("pism FILENAME AUX_FILENAME")
+        return -1
+
+    aux_filename = argv[2]
+    aux = json.loads(open(aux_filename).read())
+
+    src_filename = argv[1]
+    contents = open(src_filename).read()
+    if not process(contents, aux):
+        return -2
+
+    return 0
+
+if __name__ == "__main__":
+    sys.exit(main(sys.argv))
+

+ 20 - 0
old/preprocess.py

@@ -0,0 +1,20 @@
+import os.path
+import sys
+from jinja2 import Environment, FileSystemLoader, Template
+
+def main(argv):
+    if len(argv) != 2:
+        print("error: missing arg", file=sys.stderr)
+        return -1
+
+    path = argv[1]
+    dirname, filename = os.path.dirname(path), os.path.basename(path)
+    env = Environment(loader = FileSystemLoader([dirname]))
+    template = env.get_template(filename)
+    print(template.render())
+
+    return 0
+
+if __name__ == "__main__":
+    sys.exit(main(sys.argv))
+

+ 5 - 0
old/run_mint.sh

@@ -0,0 +1,5 @@
+#!/bin/bash -x
+python3 scripts/preprocess.py proofs/mint2.psm > /tmp/mint2.psm || exit $?
+python3 scripts/compile.py --supervisor /tmp/mint2.psm --output mint.zcd || exit $?
+cargo run --release --bin mint
+

+ 4 - 0
old/run_mint_contract.sh

@@ -0,0 +1,4 @@
+#!/bin/bash -x
+python scripts/preprocess.py proofs/mint.pism > /tmp/mint.pism
+python scripts/pism.py /tmp/mint.pism proofs/mint.aux | rustfmt > src/mint_contract.rs
+cargo run --release --bin mint

+ 4 - 0
old/run_spend_contract.sh

@@ -0,0 +1,4 @@
+#!/bin/bash -x
+python scripts/preprocess.py proofs/spend.pism > /tmp/spend.pism
+python scripts/pism.py /tmp/spend.pism proofs/mint.aux | rustfmt > src/spend_contract.rs
+cargo run --release --bin spend

+ 92 - 0
proof/mint.pism

@@ -0,0 +1,92 @@
+# :set syntax=pism
+# :source ../scripts/pism.vim
+constant G_VCV FixedGenerator
+constant G_VCR FixedGenerator
+constant CRH_IVK BlakePersonalization
+#constant JUBJUB_FR_CAPACITY BinarySize
+#constant NOTE_COMMIT PedersenPersonalization
+
+contract mint_contract
+    # Value commitment
+    param value U64
+    param asset_id Fr
+    param randomness_value Fr
+    param randomness_asset Fr
+
+    param serial Fr
+    param randomness_coin Fr
+    param public Point
+start
+    # Witness input values
+    u64_as_binary_le value param:value
+    fr_as_binary_le asset_id param:asset_id
+    fr_as_binary_le randomness_value param:randomness_value
+    fr_as_binary_le randomness_asset param:randomness_asset
+    fr_as_binary_le serial param:serial
+    fr_as_binary_le randomness_coin param:randomness_coin
+
+    witness public param:public
+    assert_not_small_order public
+
+    # Make value commitment
+    # V = v * G_VCV + r * G_VCR
+
+    ec_mul_const vcv value G_VCV
+    ec_mul_const rcv randomness_value G_VCR
+    ec_add cv vcv rcv
+    # emit cv
+    emit_ec cv
+
+    # Make asset_id commitment
+    # A = a * G_VCV + r_a * G_VCR
+
+    ec_mul_const vca asset_id G_VCV
+    ec_mul_const rca randomness_asset G_VCR
+    ec_add ca vca rca
+    # emit ca
+    emit_ec ca
+
+
+    # Make the coin
+    # C = Hash(public_key, value, asset_id, serial, randomness_coin)
+
+    # Build the preimage to hash
+    alloc_binary preimage
+
+    # public_key
+    ec_repr repr_public public
+    binary_extend preimage repr_public
+
+    # value
+    binary_extend preimage value
+
+# Fr values are 252 bits so we need to pad it with extra 0s
+# to match the Rust values which are 256 bits
+{% macro binary_put_fr(binary, var) -%}
+    binary_extend {{ binary }} {{ var }}
+    {% for n in range(4) %}
+        alloc_const_bit zero_bit false
+        binary_push {{ binary }} zero_bit
+    {% endfor %}
+{%- endmacro %}
+
+    # serial
+    {{ binary_put_fr("preimage", "serial") }}
+
+    # randomness_coin
+    {{ binary_put_fr("preimage", "randomness_coin") }}
+
+    # asset_id
+    {{ binary_put_fr("preimage", "asset_id") }}
+
+    # Public key:       SubgroupPoint   = 256 bits
+    # Value:            u64             = 64 bits
+    # AssetID:          Fr              = 252 + 4 bits padding
+    # Serial:           Fr              = 252 + 4 bits padding
+    # Randomness coin   Fr              = 252 + 4 bits padding
+    # TOTAL: 1088 bits for preimage
+    static_assert_binary_size preimage 1088
+    blake2s coin preimage CRH_IVK
+    emit_binary coin
+end
+

+ 158 - 0
proof/spend.pism

@@ -0,0 +1,158 @@
+constant G_VCV FixedGenerator
+constant G_VCR FixedGenerator
+constant G_SPEND FixedGenerator
+constant PRF_NF BlakePersonalization
+constant CRH_IVK BlakePersonalization
+constant NOTE_COMMIT PedersenPersonalization
+{% for i in range(32) %}
+    constant MERKLE_{{ i }} PedersenPersonalization
+{% endfor %}
+
+contract spend_contract
+    # Value commitment
+    param value U64
+    param asset_id Fr
+    param randomness_value Fr
+    param randomness_asset Fr
+
+    param serial Fr
+    param randomness_coin Fr
+    param secret Fr
+    param signature_secret Fr
+
+{% for i in range(32) %}
+    param branch_{{ i }} Scalar
+    param is_right_{{ i }} Bool
+{% endfor %}
+start
+    # Witness input values
+    u64_as_binary_le value param:value
+    fr_as_binary_le asset_id param:asset_id
+    fr_as_binary_le randomness_value param:randomness_value
+    fr_as_binary_le randomness_asset param:randomness_asset
+
+    # Make value commitment
+    # V = v * G_VCV + r * G_VCR
+
+    ec_mul_const vcv value G_VCV
+    ec_mul_const rcv randomness_value G_VCR
+    ec_add cv vcv rcv
+    # emit cv
+    emit_ec cv
+
+    # Make asset_id commitment
+    # A = a * G_VCV + r * G_VCR
+
+    ec_mul_const vca asset_id G_VCV
+    ec_mul_const rca randomness_asset G_VCR
+    ec_add ca vca rca
+    # emit ca
+    emit_ec ca
+
+    # Make the nullifier
+    # N = Hash(secret, serial)
+    fr_as_binary_le serial param:serial
+    fr_as_binary_le secret param:secret
+
+    alloc_binary nf_preimage
+
+# Fr values are 252 bits so we need to pad it with extra 0s
+# to match the Rust values which are 256 bits
+{% macro binary_put_fr(binary, var) -%}
+    binary_extend {{ binary }} {{ var }}
+    {% for n in range(4) %}
+        alloc_const_bit zero_bit false
+        binary_push {{ binary }} zero_bit
+    {% endfor %}
+{%- endmacro %}
+
+    # secret
+    binary_clone secret2 secret
+    {{ binary_put_fr("nf_preimage", "secret2") }}
+
+    # serial
+    binary_clone serial2 serial
+    {{ binary_put_fr("nf_preimage", "serial2") }}
+
+    # Secret:           Fr              = 252 + 4 bits padding
+    # Serial:           Fr              = 252 + 4 bits padding
+    # TOTAL: 512 bits for preimage
+    static_assert_binary_size nf_preimage 512
+    blake2s nf nf_preimage PRF_NF
+    emit_binary nf
+
+    # Derive the public key
+    # P = secret * G
+    ec_mul_const public secret G_SPEND
+
+    # Make the coin (same as mint contract)
+    # C = Hash(public_key, value, asset_id, serial, randomness_coin)
+    fr_as_binary_le randomness_coin param:randomness_coin
+
+    # Build the preimage to hash
+    alloc_binary preimage
+
+    # public_key
+    ec_repr repr_public public
+    binary_extend preimage repr_public
+
+    # value
+    binary_extend preimage value
+
+    # serial
+    {{ binary_put_fr("preimage", "serial") }}
+
+    # randomness_coin
+    {{ binary_put_fr("preimage", "randomness_coin") }}
+
+    # asset_id
+    {{ binary_put_fr("preimage", "asset_id") }}
+
+    # Public key:       SubgroupPoint   = 256 bits
+    # Value:            u64             = 64 bits
+    # AssetID:          Fr              = 252 + 4 bits padding
+    # Serial:           Fr              = 252 + 4 bits padding
+    # Randomness coin   Fr              = 252 + 4 bits padding
+    # TOTAL: 1088 bits for preimage
+    static_assert_binary_size preimage 1088
+    blake2s coin preimage CRH_IVK
+    # Debug stuff. Normally we don't reveal the coin in the spend proof.
+    #binary_clone coin2 coin
+    #emit_binary coin2
+
+    # coin_commit = PedersenHash(coin)
+    pedersen_hash cm coin NOTE_COMMIT
+    # left = coin_commit.u
+    ec_get_u current cm
+
+    # Our merkle tree has a height of 32
+{% for i in range(32) %}
+    # left = current
+    # right = branch[{{ i }}]
+    alloc_scalar branch param:branch_{{ i }}
+
+    # is_right = is_right[{{ i }}]
+    alloc_bit is_right param:is_right_{{ i }}
+
+    # reverse(a, b, condition) = if condition (b, a) else (a, b)
+    conditionally_reverse left right current branch is_right
+
+    # coin_commit = PedersenHash(left || right)
+    scalar_as_binary left left
+    scalar_as_binary right right
+    alloc_binary preimage
+    binary_extend preimage left
+    binary_extend preimage right
+    pedersen_hash cm preimage MERKLE_{{ i }}
+    # current = coin_commit.u
+    ec_get_u current cm
+{% endfor %}
+    # Reveal the merkle root
+    emit_scalar current
+
+    # Emit the signature public key
+    fr_as_binary_le signature_secret param:signature_secret
+    ec_mul_const signature_public signature_secret G_SPEND
+    emit_ec signature_public
+end
+

+ 74 - 0
script/run_demo.sh

@@ -0,0 +1,74 @@
+#!/bin/bash
+
+
+arg=$1
+gatewayd_path="./target/release/gatewayd"
+cashierd_path="./target/release/cashierd"
+darkfid_path="./target/release/darkfid"
+drk_path="./target/release/drk"
+
+echo Running demo...
+
+if [ "$arg" = "-d" ]; then
+	echo DEBUG MODE	
+	gatewayd_path="./target/debug/gatewayd"
+	cashierd_path="./target/debug/cashierd"
+	darkfid_path="./target/debug/darkfid"
+	drk_path="./target/debug/drk"
+fi
+
+echo Open new tab and run: 
+echo "	$ " $drk_path --help
+
+trap cleanup SIGINT 
+
+function cleanup()
+{
+	screen -X -S "gatewayd" quit
+	screen -X -S "cashierd" quit
+	screen -X -S "darkfid" quit
+	echo Exit demo...
+}
+
+# Start gateway daemon 
+screen -S "gatewayd" -dm "$gatewayd_path" -v 
+status=$?
+if [ $status -ne 0 ]; then
+  echo "Failed to start gateway daemon: $status"
+  exit $status
+fi
+
+# Start cashier daemon 
+screen -S "cashierd" -dm "$cashierd_path" -v
+status=$?
+if [ $status -ne 0 ]; then
+  echo "Failed to start cashier daemon: $status"
+  exit $status
+fi
+
+# Start darkfi daemon 
+screen -S "darkfid" -dm "$darkfid_path" -v
+status=$?
+if [ $status -ne 0 ]; then
+  echo "Failed to start darkfi daemon: $status"
+  exit $status
+fi
+
+# Exit with an error if it detects that either of the processes has exited.
+# Otherwise it loops forever, waking up every 60 seconds 
+while sleep 60; do
+  ps aux |grep "gatewayd" |grep -q -v grep
+  PROCESS_1_STATUS=$?
+  ps aux |grep "cashierd" |grep -q -v grep
+  PROCESS_2_STATUS=$?
+  ps aux |grep "darkfid" |grep -q -v grep
+  PROCESS_3_STATUS=$?
+
+  if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 -o $PROCESS_3_STATUS -ne 0 ]; then
+    echo "One of the processes has already exited."
+	cleanup
+    exit 1
+  fi
+done
+
+