Browse Source

move examples/halo2 to example/halo2

narodnik 4 năm trước cách đây
mục cha
commit
14a242172e

+ 0 - 0
examples/halo2/.gitignore → example/halo2/.gitignore


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 613 - 157
example/halo2/Cargo.lock


+ 12 - 40
example/halo2/Cargo.toml

@@ -1,47 +1,19 @@
 [package]
-name = "halo2_examples"
+name = "drk_halo2"
 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
+authors = ["Ivan Jelincic <parazyd@dyne.org>"]
+edition = "2021"
 
 [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"
+ff = "0.11.0"
+pasta_curves = "0.2.1"
 
-[dependencies.sinsemilla]
-git = "https://github.com/parazyd/orchard.git"
-#rev = "0d14f2390734e4710fc24a976f037dae3a6e7ac8"
-rev = "f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
+[dependencies.halo2]
+version = "=0.1.0-beta.1"
+features = ["dev-graph", "gadget-traces", "sanity-checks"]
 
- [dependencies.orchard]
-git = "https://github.com/parazyd/orchard.git"
-rev = "f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
+[dependencies.halo2_gadgets]
+git = "https://github.com/parazyd/halo2_gadgets.git"
+rev = "8238cb3471b798c76dd53b278524fc80685c7d4f"
+features = ["dev-graph", "test-dependencies"]

+ 0 - 0
examples/halo2/Makefile → example/halo2/Makefile


+ 0 - 6
example/halo2/README.md

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

+ 568 - 38
example/halo2/src/bin/burn.rs

@@ -1,73 +1,603 @@
 use std::iter;
+use std::time::Instant;
 
-use group::{ff::PrimeFieldBits, Curve};
 use halo2::{
-    arithmetic::{CurveAffine, Field, FieldExt},
-    pasta::{Fp, Fq},
+    circuit::{Layouter, SimpleFloorPlanner},
+    dev::MockProver,
+    plonk::{
+        Advice, Circuit, Column, ConstraintSystem, Error, Instance as InstanceColumn, Selector,
+    },
+    poly::Rotation,
+};
+use halo2_gadgets::{
+    ecc::{
+        chip::{EccChip, EccConfig},
+        FixedPoint, FixedPoints,
+    },
+    poseidon::{
+        Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig,
+        StateWord, Word,
+    },
+    primitives,
+    primitives::{
+        poseidon::{ConstantLength, P128Pow5T3},
+        sinsemilla::S_PERSONALIZATION,
+    },
+    sinsemilla::{
+        chip::{SinsemillaChip, SinsemillaConfig},
+        merkle::chip::{MerkleChip, MerkleConfig},
+        merkle::MerklePath,
+    },
+    utilities::{
+        lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
+    },
+};
+use pasta_curves::{
+    arithmetic::{CurveAffine, Field},
+    group::{ff::PrimeFieldBits, Curve},
+    pallas,
 };
-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;
+use drk_halo2::{
+    constants::{
+        sinsemilla::{OrchardCommitDomains, OrchardHashDomains, MERKLE_CRH_PERSONALIZATION},
+        OrchardFixedBases,
+    },
+    crypto::pedersen_commitment,
+    proof::{Proof, ProvingKey, VerifyingKey},
+    spec::i2lebsp,
+};
+
+#[derive(Clone, Debug)]
+struct BurnConfig {
+    primary: Column<InstanceColumn>,
+    q_add: Selector,
+    advices: [Column<Advice>; 10],
+    ecc_config: EccConfig,
+    merkle_config_1: MerkleConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
+    merkle_config_2: MerkleConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
+    sinsemilla_config_1:
+        SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
+    sinsemilla_config_2:
+        SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
+    poseidon_config: PoseidonConfig<pallas::Base>,
+}
+
+impl BurnConfig {
+    fn ecc_chip(&self) -> EccChip<OrchardFixedBases> {
+        EccChip::construct(self.ecc_config.clone())
+    }
+
+    /*
+    fn sinsemilla_chip_1(
+        &self,
+    ) -> SinsemillaChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
+        SinsemillaChip::construct(self.sinsemilla_config_1.clone())
+    }
+
+    fn sinsemilla_chip_2(
+        &self,
+    ) -> SinsemillaChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
+        SinsemillaChip::construct(self.sinsemilla_config_2.clone())
+    }
+    */
+
+    fn merkle_chip_1(
+        &self,
+    ) -> MerkleChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
+        MerkleChip::construct(self.merkle_config_1.clone())
+    }
+
+    fn merkle_chip_2(
+        &self,
+    ) -> MerkleChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
+        MerkleChip::construct(self.merkle_config_2.clone())
+    }
+
+    fn poseidon_chip(&self) -> PoseidonChip<pallas::Base> {
+        PoseidonChip::construct(self.poseidon_config.clone())
+    }
+}
+
+// The public input array offsets
+const BURN_NULLIFIER_OFFSET: usize = 0;
+const BURN_VALCOMX_OFFSET: usize = 1;
+const BURN_VALCOMY_OFFSET: usize = 2;
+const BURN_ASSCOMX_OFFSET: usize = 3;
+const BURN_ASSCOMY_OFFSET: usize = 4;
+const BURN_MERKLEROOT_OFFSET: usize = 5;
+const BURN_SIGKEYX_OFFSET: usize = 6;
+const BURN_SIGKEYY_OFFSET: usize = 7;
+
+#[derive(Default, Debug)]
+struct BurnCircuit {
+    secret_key: Option<pallas::Base>,
+    serial: Option<pallas::Base>,
+    value: Option<pallas::Base>,
+    asset: Option<pallas::Base>,
+    coin_blind: Option<pallas::Base>,
+    value_blind: Option<pallas::Scalar>,
+    asset_blind: Option<pallas::Scalar>,
+    leaf: Option<pallas::Base>,
+    leaf_pos: Option<u32>,
+    merkle_path: Option<[pallas::Base; 32]>,
+    sig_secret: Option<pallas::Scalar>,
+}
+
+impl UtilitiesInstructions<pallas::Base> for BurnCircuit {
+    type Var = CellValue<pallas::Base>;
+}
+
+impl Circuit<pallas::Base> for BurnCircuit {
+    type Config = BurnConfig;
+    type FloorPlanner = SimpleFloorPlanner;
+
+    fn without_witnesses(&self) -> Self {
+        Self::default()
+    }
+
+    fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
+        // Advice columns used in the circuit
+        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 three field elements
+        let q_add = meta.selector();
+        meta.create_gate("a+b+c", |meta| {
+            let q_add = meta.query_selector(q_add);
+            let sum = meta.query_advice(advices[5], Rotation::cur());
+            let a = meta.query_advice(advices[6], Rotation::cur());
+            let b = meta.query_advice(advices[7], Rotation::cur());
+            let c = meta.query_advice(advices[8], Rotation::cur());
+
+            vec![q_add * (a + b + c - sum)]
+        });
+
+        // Fixed columns for the Sinsemilla generator lookup table
+        let table_idx = meta.lookup_table_column();
+        let lookup = (
+            table_idx,
+            meta.lookup_table_column(),
+            meta.lookup_table_column(),
+        );
+
+        // Instance column used for public inputs
+        let primary = meta.instance_column();
+        meta.enable_equality(primary.into());
+
+        // Permutation over all advice columns
+        for advice in advices.iter() {
+            meta.enable_equality((*advice).into());
+        }
+
+        // Poseidon requires four advice columns, while ECC incomplete addition
+        // requires six. We can reduce the proof size by sharing fixed columns
+        // between the ECC and Poseidon chips.
+        // TODO: For multiple invocations they could/should be configured in
+        // parallel rather than sharing perhaps?
+        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();
+
+        // Also use the first Lagrange coefficient column for loading global constants.
+        meta.enable_constant(lagrange_coeffs[0]);
+
+        // Use one of the right-most advice columns for all of our range checks.
+        let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx);
+
+        // Configuration for curve point operations.
+        // This uses 10 advice columns and spans the whole circuit.
+        let ecc_config = EccChip::<OrchardFixedBases>::configure(
+            meta,
+            advices,
+            lagrange_coeffs,
+            range_check.clone(),
+        );
+
+        // Configuration for the Poseidon hash
+        let poseidon_config = PoseidonChip::configure(
+            meta,
+            P128Pow5T3,
+            advices[6..9].try_into().unwrap(),
+            advices[5],
+            rc_a,
+            rc_b,
+        );
+
+        // Configuration for a Sinsemilla hash instantiation and a
+        // Merkle hash instantiation using this Sinsemilla instance.
+        // Since the Sinsemilla config uses only 5 advice columns,
+        // we can fit two instances side-by-side.
+        let (sinsemilla_config_1, merkle_config_1) = {
+            let sinsemilla_config_1 = SinsemillaChip::configure(
+                meta,
+                advices[..5].try_into().unwrap(),
+                advices[6],
+                lagrange_coeffs[0],
+                lookup,
+                range_check.clone(),
+            );
+            let merkle_config_1 = MerkleChip::configure(meta, sinsemilla_config_1.clone());
+            (sinsemilla_config_1, merkle_config_1)
+        };
+
+        // Configuration for a Sinsemilla hash instantiation and a
+        // Merkle hash instantiation using this Sinsemilla instance.
+        // Since the Sinsemilla config uses only 5 advice columns,
+        // we can fit two instances side-by-side.
+        let (sinsemilla_config_2, merkle_config_2) = {
+            let sinsemilla_config_2 = SinsemillaChip::configure(
+                meta,
+                advices[5..].try_into().unwrap(),
+                advices[7],
+                lagrange_coeffs[1],
+                lookup,
+                range_check,
+            );
+            let merkle_config_2 = MerkleChip::configure(meta, sinsemilla_config_2.clone());
+
+            (sinsemilla_config_2, merkle_config_2)
+        };
+
+        BurnConfig {
+            primary,
+            q_add,
+            advices,
+            ecc_config,
+            merkle_config_1,
+            merkle_config_2,
+            sinsemilla_config_1,
+            sinsemilla_config_2,
+            poseidon_config,
+        }
+    }
+
+    fn synthesize(
+        &self,
+        config: Self::Config,
+        mut layouter: impl Layouter<pallas::Base>,
+    ) -> Result<(), Error> {
+        // Load the Sinsemilla generator lookup table used by the whole circuit.
+        SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?;
+
+        // Construct the ECC chip.
+        let ecc_chip = config.ecc_chip();
+
+        // Construct the merkle chips
+        let merkle_chip_1 = config.merkle_chip_1();
+        let merkle_chip_2 = config.merkle_chip_2();
+
+        // =========
+        // Nullifier
+        // =========
+        let hashed_secret_key = self.load_private(
+            layouter.namespace(|| "load sinsemilla(secret key)"),
+            config.advices[0],
+            self.secret_key,
+        )?;
+
+        let serial = self.load_private(
+            layouter.namespace(|| "load serial"),
+            config.advices[0],
+            self.serial,
+        )?;
+
+        let message = [hashed_secret_key, serial];
+        let hash = {
+            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::<_, _, P128Pow5T3, 3, 2>::from_inner(StateWord::new(
+                            var, value,
+                        )))
+                    };
+                    Ok([message_word(0)?, message_word(1)?])
+                },
+            )?;
+
+            let poseidon_hasher = PoseidonHash::init(
+                config.poseidon_chip(),
+                layouter.namespace(|| "Poseidon init"),
+                ConstantLength::<2>,
+            )?;
+
+            let poseidon_output = poseidon_hasher.hash(
+                layouter.namespace(|| "Poseidon hash (secretkey, serial)"),
+                poseidon_message,
+            )?;
+
+            let poseidon_output: CellValue<pallas::Base> = poseidon_output.inner().into();
+            poseidon_output
+        };
+
+        layouter.constrain_instance(hash.cell(), config.primary, BURN_NULLIFIER_OFFSET)?;
+
+        // ===========
+        // Merkle root
+        // ===========
+        let leaf = self.load_private(
+            layouter.namespace(|| "load leaf"),
+            config.advices[0],
+            self.leaf,
+        )?;
+
+        let path = MerklePath {
+            chip_1: merkle_chip_1,
+            chip_2: merkle_chip_2,
+            domain: OrchardHashDomains::MerkleCrh,
+            leaf_pos: self.leaf_pos,
+            path: self.merkle_path,
+        };
+
+        let computed_final_root =
+            path.calculate_root(layouter.namespace(|| "calculate root"), leaf)?;
+
+        layouter.constrain_instance(
+            computed_final_root.cell(),
+            config.primary,
+            BURN_MERKLEROOT_OFFSET,
+        )?;
+
+        // ================
+        // Value commitment
+        // ================
+
+        // This constant one is used for multiplication
+        let one = self.load_private(
+            layouter.namespace(|| "load constant one"),
+            config.advices[0],
+            Some(pallas::Base::one()),
+        )?;
+
+        let value = self.load_private(
+            layouter.namespace(|| "load value"),
+            config.advices[0],
+            self.value,
+        )?;
+
+        // 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 value commitment coordinates
+        let value_commit = commitment.add(layouter.namespace(|| "valuecommit"), &blind)?;
+        layouter.constrain_instance(
+            value_commit.inner().x().cell(),
+            config.primary,
+            BURN_VALCOMX_OFFSET,
+        )?;
+        layouter.constrain_instance(
+            value_commit.inner().y().cell(),
+            config.primary,
+            BURN_VALCOMY_OFFSET,
+        )?;
+
+        // ================
+        // Asset commitment
+        // ================
+
+        let asset = self.load_private(
+            layouter.namespace(|| "load asset"),
+            config.advices[0],
+            self.asset,
+        )?;
+
+        // 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 asset commitment coordinates
+        let asset_commit = commitment.add(layouter.namespace(|| "assetcommit"), &blind)?;
+        layouter.constrain_instance(
+            asset_commit.inner().x().cell(),
+            config.primary,
+            BURN_ASSCOMX_OFFSET,
+        )?;
+        layouter.constrain_instance(
+            asset_commit.inner().y().cell(),
+            config.primary,
+            BURN_ASSCOMY_OFFSET,
+        )?;
+
+        // ========================
+        // Signature key derivation
+        // ========================
+        let (sig_pub, _) = {
+            let spend_auth_g = OrchardFixedBases::SpendAuthG;
+            let spend_auth_g = FixedPoint::from_inner(ecc_chip, spend_auth_g);
+            // TODO: Do we need to load sig_secret somewhere first?
+            spend_auth_g.mul(layouter.namespace(|| "[x_s] SpendAuthG"), self.sig_secret)?
+        };
+
+        layouter.constrain_instance(
+            sig_pub.inner().x().cell(),
+            config.primary,
+            BURN_SIGKEYX_OFFSET,
+        )?;
+        layouter.constrain_instance(
+            sig_pub.inner().y().cell(),
+            config.primary,
+            BURN_SIGKEYY_OFFSET,
+        )?;
+
+        // At this point we've enforced all of our public inputs.
+        Ok(())
+    }
+}
+
+fn root(path: [pallas::Base; 32], leaf_pos: u32, leaf: pallas::Base) -> pallas::Base {
+    let domain = primitives::sinsemilla::HashDomain::new(MERKLE_CRH_PERSONALIZATION);
+
+    let pos_bool = i2lebsp::<32>(leaf_pos as u64);
+
+    let mut node = leaf;
+    for (l, (sibling, pos)) in path.iter().zip(pos_bool.iter()).enumerate() {
+        let (left, right) = if *pos {
+            (*sibling, node)
+        } else {
+            (node, *sibling)
+        };
+
+        let l_star = i2lebsp::<10>(l as u64);
+        let left: Vec<_> = left.to_le_bits().iter().by_val().take(255).collect();
+        let right: Vec<_> = right.to_le_bits().iter().by_val().take(255).collect();
+
+        let mut message = l_star.to_vec();
+        message.extend_from_slice(&left);
+        message.extend_from_slice(&right);
+
+        node = domain.hash(message.into_iter()).unwrap();
+    }
+    node
+}
 
 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();
+    // The number of rows in our circuit cannot exceed 2^k
+    let k: u32 = 11;
 
-    let public_key = OrchardFixedBases::SpendAuthG.generator() * secret_key;
-    let coords = public_key.to_affine().coordinates().unwrap();
+    let secret_key = pallas::Scalar::random(&mut OsRng);
+    let serial = pallas::Base::random(&mut OsRng);
 
-    let value = 110;
+    let value = 42;
     let asset = 1;
 
-    let value_blind = Fq::random(&mut OsRng);
-    let asset_blind = Fq::random(&mut OsRng);
+    // Nullifier = poseidon(sinsemilla(secret_key), serial)
+    let domain = primitives::sinsemilla::HashDomain::new(S_PERSONALIZATION);
+    let bits_secretkey: Vec<bool> = secret_key.to_le_bits().iter().by_val().collect();
+    let hashed_secret_key = domain.hash(iter::empty().chain(bits_secretkey)).unwrap();
+
+    let nullifier = [hashed_secret_key, serial];
+    let nullifier =
+        primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(nullifier);
 
-    let coin_blind = Fp::random(&mut OsRng);
+    // Public key derivation
+    let public_key = OrchardFixedBases::SpendAuthG.generator() * secret_key;
+    let coords = public_key.to_affine().coordinates().unwrap();
 
-    // FIXME:
+    // Construct Coin
+    let mut coin = pallas::Base::zero();
+    let coin_blind = pallas::Base::random(&mut OsRng);
     let messages = [
         [*coords.x(), *coords.y()],
-        [Fp::from(value), Fp::from(asset)],
+        [pallas::Base::from(value), pallas::Base::from(asset)],
         [serial, coin_blind],
     ];
-    let mut coin = Fp::zero();
+
     for msg in messages.iter() {
-        coin += Hash::init(OrchardNullifier, ConstantLength::<2>).hash(*msg);
+        let hash = primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(*msg);
+        coin += hash;
     }
 
-    // TODO: Merkle
+    // Merkle root
+    let leaf = pallas::Base::random(&mut OsRng);
+    let pos = rand::random::<u32>();
+    let path: Vec<_> = (0..32).map(|_| pallas::Base::random(&mut OsRng)).collect();
+    let merkle_root = root(path.clone().try_into().unwrap(), pos, leaf);
 
+    // Value and asset commitments
+    let value_blind = pallas::Scalar::random(&mut OsRng);
+    let asset_blind = pallas::Scalar::random(&mut OsRng);
     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 asset_coords = asset_commit.to_affine().coordinates().unwrap();
 
-    let sig_secret = Fq::random(&mut OsRng);
+    // Derive signature public key from signature secret key
+    let sig_secret = pallas::Scalar::random(&mut OsRng);
     let sig_pubkey = OrchardFixedBases::SpendAuthG.generator() * sig_secret;
-    let sig_pk_coords = sig_pubkey.to_affine().coordinates().unwrap();
+    let sig_coords = sig_pubkey.to_affine().coordinates().unwrap();
 
-    let mut public_inputs = vec![
+    let 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(),
+        merkle_root,
+        *sig_coords.x(),
+        *sig_coords.y(),
     ];
+
+    let circuit = BurnCircuit {
+        secret_key: Some(hashed_secret_key),
+        serial: Some(serial),
+        value: Some(pallas::Base::from(value)),
+        asset: Some(pallas::Base::from(asset)),
+        coin_blind: Some(coin_blind),
+        value_blind: Some(value_blind),
+        asset_blind: Some(asset_blind),
+        leaf: Some(leaf),
+        leaf_pos: Some(pos),
+        merkle_path: Some(path.try_into().unwrap()),
+        sig_secret: Some(sig_secret),
+    };
+
+    let prover = MockProver::run(k, &circuit, vec![public_inputs.clone()]).unwrap();
+    assert_eq!(prover.verify(), Ok(()));
+
+    // Actual ZK proof
+    let start = Instant::now();
+    let vk = VerifyingKey::build(k, BurnCircuit::default());
+    let pk = ProvingKey::build(k, BurnCircuit::default());
+    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());
 }

+ 246 - 230
example/halo2/src/bin/mint.rs

@@ -1,58 +1,93 @@
-use std::{convert::TryInto, time::Instant};
+use std::time::Instant;
 
-use group::{ff::Field, Curve, Group};
 use halo2::{
-    arithmetic::CurveAffine,
-    circuit::{floor_planner, Layouter},
+    circuit::{Layouter, SimpleFloorPlanner},
     dev::MockProver,
-    pasta::{vesta, Ep, Fp, Fq},
-    plonk,
-    plonk::{Circuit, ConstraintSystem, Error},
-    poly::commitment,
-    transcript::{Blake2bRead, Blake2bWrite},
+    plonk::{
+        Advice, Circuit, Column, ConstraintSystem, Error, Instance as InstanceColumn, Selector,
+    },
+    poly::Rotation,
 };
-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_gadgets::{
+    ecc::{
+        chip::{EccChip, EccConfig},
+        FixedPoint,
+    },
+    poseidon::{
+        Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig,
+        StateWord, Word,
+    },
+    primitives,
+    primitives::poseidon::{ConstantLength, P128Pow5T3},
+    utilities::{
+        copy, lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
+    },
 };
-use halo2_utilities::{
-    lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
+use pasta_curves::{
+    arithmetic::{CurveAffine, Field},
+    group::{Curve, Group},
+    pallas,
 };
-use orchard::constants::fixed_bases::OrchardFixedBases;
 use rand::rngs::OsRng;
 
-use halo2_examples::{circuit::Config, pedersen_commitment};
+use drk_halo2::{
+    constants::OrchardFixedBases,
+    crypto::pedersen_commitment,
+    proof::{Proof, ProvingKey, VerifyingKey},
+};
+
+#[derive(Clone, Debug)]
+struct MintConfig {
+    primary: Column<InstanceColumn>,
+    q_add: Selector,
+    advices: [Column<Advice>; 10],
+    ecc_config: EccConfig,
+    poseidon_config: PoseidonConfig<pallas::Base>,
+}
+
+impl MintConfig {
+    fn ecc_chip(&self) -> EccChip<OrchardFixedBases> {
+        EccChip::construct(self.ecc_config.clone())
+    }
+
+    fn poseidon_chip(&self) -> PoseidonChip<pallas::Base> {
+        PoseidonChip::construct(self.poseidon_config.clone())
+    }
+}
 
-const K: u32 = 9;
+// The public input array offsets
+const MINT_COIN_OFFSET: usize = 0;
+const MINT_VALCOMX_OFFSET: usize = 1;
+const MINT_VALCOMY_OFFSET: usize = 2;
+const MINT_ASSCOMX_OFFSET: usize = 3;
+const MINT_ASSCOMY_OFFSET: usize = 4;
 
 #[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
+    pub_x: Option<pallas::Base>,         // x coordinate for pubkey
+    pub_y: Option<pallas::Base>,         // y coordinate for pubkey
+    value: Option<pallas::Base>,         // The value of this coin
+    asset: Option<pallas::Base>,         // The asset ID
+    serial: Option<pallas::Base>,        // Unique serial number corresponding to this coin
+    coin_blind: Option<pallas::Base>,    // Random blinding factor for coin
+    value_blind: Option<pallas::Scalar>, // Random blinding factor for value commitment
+    asset_blind: Option<pallas::Scalar>, // Random blinding factor for the asset ID
 }
 
-impl UtilitiesInstructions<Fp> for MintCircuit {
-    type Var = CellValue<Fp>;
+impl UtilitiesInstructions<pallas::Base> for MintCircuit {
+    type Var = CellValue<pallas::Base>;
 }
 
-impl Circuit<Fp> for MintCircuit {
-    type Config = Config;
-    type FloorPlanner = floor_planner::V1;
-    //type FloorPlanner = SimpleFloorPlanner;
+impl Circuit<pallas::Base> for MintCircuit {
+    type Config = MintConfig;
+    type FloorPlanner = SimpleFloorPlanner;
 
     fn without_witnesses(&self) -> Self {
         Self::default()
     }
 
-    fn configure(meta: &mut ConstraintSystem<Fp>) -> Self::Config {
+    fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
+        // Advice columns used in the circuit
         let advices = [
             meta.advice_column(),
             meta.advice_column(),
@@ -66,24 +101,51 @@ impl Circuit<Fp> for MintCircuit {
             meta.advice_column(),
         ];
 
+        // Addition of two field elements
+        /*
+        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 q_add = meta.selector();
+        meta.create_gate("a+b+c", |meta| {
+            let q_add = meta.query_selector(q_add);
+            let sum = meta.query_advice(advices[5], Rotation::cur());
+            let a = meta.query_advice(advices[6], Rotation::cur());
+            let b = meta.query_advice(advices[7], Rotation::cur());
+            let c = meta.query_advice(advices[8], Rotation::cur());
 
-        let table_idx = meta.lookup_table_column();
+            vec![q_add * (a + b + c - sum)]
+        });
 
-        // let lookup = (
-        // table_idx,
-        // meta.lookup_table_column(),
-        // meta.lookup_table_column(),
-        // );
+        // Fixed columns for the Sinsemilla generator lookup table
+        let table_idx = meta.lookup_table_column();
+        let _lookup = (
+            table_idx,
+            meta.lookup_table_column(),
+            meta.lookup_table_column(),
+        );
 
+        // Instance column used for public inputs
         let primary = meta.instance_column();
-
         meta.enable_equality(primary.into());
 
+        // Permutation over all advice columns
         for advice in advices.iter() {
             meta.enable_equality((*advice).into());
         }
 
+        // Poseidon requires four advice columns, while ECC incomplete addition
+        // requires six. We can reduce the proof size by sharing fixed columns
+        // between the ECC and Poseidon chips.
+        // TODO: For multiple invocations they could/should be configured in
+        // parallel rather than sharing perhaps?
         let lagrange_coeffs = [
             meta.fixed_column(),
             meta.fixed_column(),
@@ -94,31 +156,31 @@ impl Circuit<Fp> for MintCircuit {
             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();
 
+        // Also use the first Lagrange coefficient column for loading global constants.
         meta.enable_constant(lagrange_coeffs[0]);
 
+        // Use one of the right-most advice columns for all of our range checks.
         let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx);
 
-        let ecc_config = EccChip::<OrchardFixedBases>::configure(
-            meta,
-            advices,
-            lagrange_coeffs,
-            range_check.clone(),
-        );
+        // Configuration for curve point operations.
+        // This uses 10 advice columns and spans the whole circuit.
+        let ecc_config =
+            EccChip::<OrchardFixedBases>::configure(meta, advices, lagrange_coeffs, range_check);
 
+        // Configuration for the Poseidon hash
         let poseidon_config = PoseidonChip::configure(
             meta,
-            OrchardNullifier,
+            P128Pow5T3,
             advices[6..9].try_into().unwrap(),
             advices[5],
             rc_a,
             rc_b,
         );
 
-        Config {
+        MintConfig {
             primary,
             q_add,
             advices,
@@ -130,120 +192,139 @@ impl Circuit<Fp> for MintCircuit {
     fn synthesize(
         &self,
         config: Self::Config,
-        mut layouter: impl Layouter<Fp>,
+        mut layouter: impl Layouter<pallas::Base>,
     ) -> Result<(), Error> {
-        // Construct the ECC chip.
-        let ecc_chip = EccChip::construct(config.ecc_config.clone());
+        let ecc_chip = config.ecc_chip();
 
         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();
+        // =========
+        // Coin hash
+        // =========
         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();
-            }
+        let mut hashes = vec![];
+
+        for message in messages.iter() {
+            let hash = {
+                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::<_, _, P128Pow5T3, 3, 2>::from_inner(StateWord::new(
+                                var, value,
+                            )))
+                        };
+                        Ok([message_word(0)?, message_word(1)?])
+                    },
+                )?;
+
+                let poseidon_hasher = PoseidonHash::init(
+                    config.poseidon_chip(),
+                    layouter.namespace(|| "Poseidon init"),
+                    ConstantLength::<2>,
+                )?;
+
+                let poseidon_output = poseidon_hasher.hash(
+                    layouter.namespace(|| "Poseidon hash (a, b)"),
+                    poseidon_message,
+                )?;
+
+                let poseidon_output: CellValue<pallas::Base> = poseidon_output.inner().into();
+                poseidon_output
+            };
+
+            hashes.push(hash);
         }
 
-        // if coin != Fp::zero() {
-        // println!("circuit hash: {:?}", coin);
-        // }
-
-        let hash = self.load_private(
-            layouter.namespace(|| "load hash"),
-            config.advices[0],
-            Some(coin),
+        let coin = layouter.assign_region(
+            || " `coin` = hash(a,b) + hash(c, d) + hash(e, f)",
+            |mut region| {
+                config.q_add.enable(&mut region, 0)?;
+
+                copy(&mut region, || "copy ab", config.advices[6], 0, &hashes[0])?;
+                copy(&mut region, || "copy cd", config.advices[7], 0, &hashes[1])?;
+                copy(&mut region, || "copy ef", config.advices[8], 0, &hashes[2])?;
+
+                let scalar_val = hashes[0]
+                    .value()
+                    .zip(hashes[1].value())
+                    .zip(hashes[2].value())
+                    .map(|(abcd, ef)| abcd.0 + abcd.1 + ef);
+
+                let cell = region.assign_advice(
+                    || "hash(a,b)+hash(c,d)+hash(e,f)",
+                    config.advices[5],
+                    0,
+                    || scalar_val.ok_or(Error::SynthesisError),
+                )?;
+                Ok(CellValue::new(cell, scalar_val))
+            },
         )?;
 
-        // Constrain the coin C; index in public values is 0
-        layouter.constrain_instance(hash.cell(), config.primary, 0)?;
+        // Constrain the coin C
+        layouter.constrain_instance(coin.cell(), config.primary, MINT_COIN_OFFSET)?;
 
-        // ====================
-        // = Value commitment =
-        // ====================
+        // ================
+        // Value commitment
+        // ================
 
-        // This constant one is used for multiplication
-        let one = self.load_constant(
-            layouter.namespace(|| "constant one"),
+        // This constant one is used for short multiplication
+        let one = self.load_private(
+            layouter.namespace(|| "load constant one"),
             config.advices[0],
-            Fp::one(),
+            Some(pallas::Base::one()),
         )?;
 
-        // v*G_1
+        // 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
+        // r_V * G_2
         let (blind, _rcv) = {
             let rcv = self.value_blind;
             let value_commit_r = OrchardFixedBases::ValueCommitR;
@@ -251,137 +332,83 @@ impl Circuit<Fp> for MintCircuit {
             value_commit_r.mul(layouter.namespace(|| "[value_blind] ValueCommitR"), rcv)?
         };
 
-        // Constrain the x and y; indexes in public values are 1 and 2
+        // Constrain the value commitment coordinates
         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 =
-        // ====================
+        layouter.constrain_instance(
+            value_commit.inner().x().cell(),
+            config.primary,
+            MINT_VALCOMX_OFFSET,
+        )?;
+        layouter.constrain_instance(
+            value_commit.inner().y().cell(),
+            config.primary,
+            MINT_VALCOMY_OFFSET,
+        )?;
 
-        // a*G_1
+        // ================
+        // 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
+        // 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);
+            let asset_commit_r = FixedPoint::from_inner(ecc_chip, 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
+        // Constrain the asset commitment coordinates
         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,
+        layouter.constrain_instance(
+            asset_commit.inner().x().cell(),
+            config.primary,
+            MINT_ASSCOMX_OFFSET,
+        )?;
+        layouter.constrain_instance(
+            asset_commit.inner().y().cell(),
+            config.primary,
+            MINT_ASSCOMY_OFFSET,
         )?;
-        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)
-        }
+        // At this point we've enforced all of our public inputs.
+        Ok(())
     }
-
-    // fn new(bytes: Vec<u8>) -> Self {
-    // Proof(bytes)
-    // }
 }
 
 fn main() {
-    let pubkey = Ep::random(&mut OsRng);
+    // The number of rows in our circuit cannot exceed 2^k
+    let k: u32 = 9;
+
+    let pubkey = pallas::Point::random(&mut OsRng);
     let coords = pubkey.to_affine().coordinates().unwrap();
 
-    let value = 110;
+    let value = 42;
     let asset = 1;
 
-    let value_blind = Fq::random(&mut OsRng);
-    let asset_blind = Fq::random(&mut OsRng);
+    let value_blind = pallas::Scalar::random(&mut OsRng);
+    let asset_blind = pallas::Scalar::random(&mut OsRng);
 
-    let serial = Fp::random(&mut OsRng);
-    let coin_blind = Fp::random(&mut OsRng);
+    let serial = pallas::Base::random(&mut OsRng);
+    let coin_blind = pallas::Base::random(&mut OsRng);
 
-    let mut coin = Fp::zero();
+    // poseidon_hash(x, y) + poseidon_hash(value, asset) + poseidon_hash(serial, coin_blind)
+    let mut coin = pallas::Base::zero();
 
     let messages = [
         [*coords.x(), *coords.y()],
-        [Fp::from(value), Fp::from(asset)],
+        [pallas::Base::from(value), pallas::Base::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 hash = primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(*msg);
+        coin += hash;
     }
 
     let value_commit = pedersen_commitment(value, value_blind);
@@ -390,7 +417,7 @@ fn main() {
     let asset_commit = pedersen_commitment(asset, asset_blind);
     let asset_coords = asset_commit.to_affine().coordinates().unwrap();
 
-    let mut public_inputs = vec![
+    let public_inputs = vec![
         coin,
         *value_coords.x(),
         *value_coords.y(),
@@ -401,33 +428,22 @@ fn main() {
     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)),
+        value: Some(pallas::Base::from(value)),
+        asset: Some(pallas::Base::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();
+    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 vk = VerifyingKey::build(k, MintCircuit::default());
+    let pk = ProvingKey::build(k, MintCircuit::default());
+    println!("Setup: [{:?}]", start.elapsed());
 
     let start = Instant::now();
     let proof = Proof::create(&pk, &[circuit], &public_inputs).unwrap();

+ 67 - 116
example/halo2/src/bin/poseidon.rs

@@ -1,55 +1,61 @@
-use std::convert::TryInto;
 use std::time::Instant;
 
 use halo2::{
-    circuit::{floor_planner, Layouter},
-    pasta::{vesta, Fp},
-    plonk,
+    circuit::{Layouter, SimpleFloorPlanner},
+    dev::MockProver,
     plonk::{
         Advice, Circuit, Column, ConstraintSystem, Error, Instance as InstanceColumn, Selector,
     },
-    poly::{commitment, Rotation},
-    transcript::{Blake2bRead, Blake2bWrite},
+    poly::Rotation,
 };
-
-use halo2_poseidon::{
-    gadget::{Hash as PoseidonHash, Word},
-    pow5t3::{Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig, StateWord},
-    primitive::{ConstantLength, Hash, P128Pow5T3 as OrchardNullifier},
+use halo2_gadgets::{
+    poseidon::{
+        Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig,
+        StateWord, Word,
+    },
+    primitives,
+    primitives::poseidon::{ConstantLength, P128Pow5T3},
+    utilities::{copy, CellValue, UtilitiesInstructions, Var},
 };
-use halo2_utilities::{copy, CellValue, UtilitiesInstructions, Var};
+use pasta_curves::pallas;
 
-const K: u32 = 6;
+use drk_halo2::proof::{Proof, ProvingKey, VerifyingKey};
 
 #[derive(Clone, Debug)]
 struct Config {
     primary: Column<InstanceColumn>,
     q_add: Selector,
     advices: [Column<Advice>; 10],
-    poseidon_config: PoseidonConfig<Fp>,
+    poseidon_config: PoseidonConfig<pallas::Base>,
+}
+
+impl Config {
+    fn poseidon_chip(&self) -> PoseidonChip<pallas::Base> {
+        PoseidonChip::construct(self.poseidon_config.clone())
+    }
 }
 
 #[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
+    a: Option<pallas::Base>,
+    b: Option<pallas::Base>,
+    c: Option<pallas::Base>,
 }
 
-impl UtilitiesInstructions<Fp> for HashCircuit {
-    type Var = CellValue<Fp>;
+impl UtilitiesInstructions<pallas::Base> for HashCircuit {
+    type Var = CellValue<pallas::Base>;
 }
 
-impl Circuit<Fp> for HashCircuit {
+impl Circuit<pallas::Base> for HashCircuit {
     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 {
-        // 10 advice columns
+    fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
+        // Advice columns used in the circuit
         let advices = [
             meta.advice_column(),
             meta.advice_column(),
@@ -63,9 +69,8 @@ impl Circuit<Fp> for HashCircuit {
             meta.advice_column(),
         ];
 
-        // Addition of two field elements: poseidon_hash(a, b) + c
+        // Addition of two field elements
         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());
@@ -75,13 +80,20 @@ impl Circuit<Fp> for HashCircuit {
             vec![q_add * (hash + c - sum)]
         });
 
+        // Instance column used for public inputs
         let primary = meta.instance_column();
         meta.enable_equality(primary.into());
 
+        // Permutation over all advice columns
         for advice in advices.iter() {
             meta.enable_equality((*advice).into());
         }
 
+        // Poseidon requires four advice columns, while ECC incomplete addition
+        // requires six. We can reduce the proof size by sharing fixed columns
+        // between the ECC and Poseidon chips.
+        // TODO: For multiple invocations they could/should be configured in
+        // parallel rather than sharing perhaps?
         let lagrange_coeffs = [
             meta.fixed_column(),
             meta.fixed_column(),
@@ -92,15 +104,16 @@ impl Circuit<Fp> for HashCircuit {
             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();
 
+        // Also use the first Lagrange coefficient column for loading global constants.
         meta.enable_constant(lagrange_coeffs[0]);
 
+        // Configuration for the Poseidon hash
         let poseidon_config = PoseidonChip::configure(
             meta,
-            OrchardNullifier,
+            P128Pow5T3,
             advices[6..9].try_into().unwrap(),
             advices[5],
             rc_a,
@@ -118,7 +131,7 @@ impl Circuit<Fp> for HashCircuit {
     fn synthesize(
         &self,
         config: Self::Config,
-        mut layouter: impl Layouter<Fp>,
+        mut layouter: impl Layouter<pallas::Base>,
     ) -> 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)?;
@@ -139,17 +152,16 @@ impl Circuit<Fp> for HashCircuit {
                             || value.ok_or(Error::SynthesisError),
                         )?;
                         region.constrain_equal(var, message[i].cell())?;
-                        Ok(Word::<_, _, OrchardNullifier, 3, 2>::from_inner(
-                            StateWord::new(var, value),
-                        ))
+                        Ok(Word::<_, _, P128Pow5T3, 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()),
+                config.poseidon_chip(),
                 layouter.namespace(|| "Poseidon init"),
                 ConstantLength::<2>,
             )?;
@@ -159,7 +171,7 @@ impl Circuit<Fp> for HashCircuit {
                 poseidon_message,
             )?;
 
-            let poseidon_output: CellValue<Fp> = poseidon_output.inner().into();
+            let poseidon_output: CellValue<pallas::Base> = poseidon_output.inner().into();
             poseidon_output
         };
 
@@ -184,91 +196,24 @@ impl Circuit<Fp> for HashCircuit {
             },
         )?;
 
-        layouter.constrain_instance(scalar.cell(), config.primary, 0)
-    }
-}
+        // Constrain sum to equal the public input
+        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 }
+        // At this point we've enforced all of our public inputs.
+        Ok(())
     }
 }
 
-#[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);
+    // The number of rows in our circuit cannot exceed 2^k
+    let k: u32 = 6;
+
+    let a = pallas::Base::from(13);
+    let b = pallas::Base::from(69);
+    let c = pallas::Base::from(42);
 
     let message = [a, b];
-    let output = Hash::init(OrchardNullifier, ConstantLength::<2>).hash(message);
+    let output = primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(message);
 
     let circuit = HashCircuit {
         a: Some(a),
@@ -278,14 +223,20 @@ fn main() {
 
     let sum = output + c;
 
+    // Incorrect:
+    let public_inputs = vec![sum + pallas::Base::one()];
+    let prover = MockProver::run(k, &circuit, vec![public_inputs]).unwrap();
+    assert!(prover.verify().is_err());
+
     // Correct:
     let public_inputs = vec![sum];
-    // Incorrect:
-    // let public_inputs = vec![sum + Fp::one()];
+    let prover = MockProver::run(k, &circuit, vec![public_inputs.clone()]).unwrap();
+    assert_eq!(prover.verify(), Ok(()));
 
+    // Actual ZK proof
     let start = Instant::now();
-    let vk = VerifyingKey::build();
-    let pk = ProvingKey::build();
+    let vk = VerifyingKey::build(k, HashCircuit::default());
+    let pk = ProvingKey::build(k, HashCircuit::default());
     println!("Setup: [{:?}]", start.elapsed());
 
     let start = Instant::now();

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

@@ -1,130 +0,0 @@
-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());
-}
-

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

@@ -1,267 +0,0 @@
-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());
-}
-

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

@@ -1,16 +0,0 @@
-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>,
-}

+ 0 - 0
examples/halo2/src/constants.rs → example/halo2/src/constants.rs


+ 0 - 0
examples/halo2/src/constants/fixed_bases.rs → example/halo2/src/constants/fixed_bases.rs


+ 0 - 0
examples/halo2/src/constants/fixed_bases/commit_ivk_r.rs → example/halo2/src/constants/fixed_bases/commit_ivk_r.rs


+ 0 - 0
examples/halo2/src/constants/fixed_bases/note_commit_r.rs → example/halo2/src/constants/fixed_bases/note_commit_r.rs


+ 0 - 0
examples/halo2/src/constants/fixed_bases/nullifier_k.rs → example/halo2/src/constants/fixed_bases/nullifier_k.rs


+ 0 - 0
examples/halo2/src/constants/fixed_bases/spend_auth_g.rs → example/halo2/src/constants/fixed_bases/spend_auth_g.rs


+ 0 - 0
examples/halo2/src/constants/fixed_bases/value_commit_r.rs → example/halo2/src/constants/fixed_bases/value_commit_r.rs


+ 0 - 0
examples/halo2/src/constants/fixed_bases/value_commit_v.rs → example/halo2/src/constants/fixed_bases/value_commit_v.rs


+ 0 - 0
examples/halo2/src/constants/sinsemilla.rs → example/halo2/src/constants/sinsemilla.rs


+ 0 - 0
examples/halo2/src/constants/util.rs → example/halo2/src/constants/util.rs


+ 0 - 0
examples/halo2/src/crypto.rs → example/halo2/src/crypto.rs


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

@@ -1,19 +1,4 @@
-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
-}
+pub mod constants;
+pub mod crypto;
+pub mod proof;
+pub mod spec;

+ 0 - 0
examples/halo2/src/proof.rs → example/halo2/src/proof.rs


+ 0 - 0
examples/halo2/src/spec.rs → example/halo2/src/spec.rs


+ 0 - 1531
examples/halo2/Cargo.lock

@@ -1,1531 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "addr2line"
-version = "0.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd"
-dependencies = [
- "gimli",
-]
-
-[[package]]
-name = "adler"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
-
-[[package]]
-name = "adler32"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
-
-[[package]]
-name = "aho-corasick"
-version = "0.7.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "anyhow"
-version = "1.0.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1"
-
-[[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.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
-
-[[package]]
-name = "autocfg"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
-
-[[package]]
-name = "backtrace"
-version = "0.3.62"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "091bcdf2da9950f96aa522681ce805e6857f6ca8df73833d35736ab2dc78e152"
-dependencies = [
- "addr2line",
- "cc",
- "cfg-if",
- "libc",
- "miniz_oxide 0.4.4",
- "object",
- "rustc-demangle",
-]
-
-[[package]]
-name = "bigint"
-version = "4.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0e8c8a600052b52482eff2cf4d810e462fdff1f656ac1ecb6232132a1ed7def"
-dependencies = [
- "byteorder",
- "crunchy",
-]
-
-[[package]]
-name = "bit-set"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de"
-dependencies = [
- "bit-vec",
-]
-
-[[package]]
-name = "bit-vec"
-version = "0.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
-
-[[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[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 = "bls12_381"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d28daeeded7949f1c7c72693377c98473b00be0aa0023760a84a300e4e7c74b"
-dependencies = [
- "ff",
- "rand_core",
- "subtle",
-]
-
-[[package]]
-name = "bumpalo"
-version = "3.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
-
-[[package]]
-name = "bytemuck"
-version = "1.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72957246c41db82b8ef88a5486143830adeb8227ef9837740bdec67724cf2c5b"
-
-[[package]]
-name = "byteorder"
-version = "1.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
-
-[[package]]
-name = "cc"
-version = "1.0.71"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "chrono"
-version = "0.4.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
-dependencies = [
- "libc",
- "num-integer",
- "num-traits",
- "time",
- "winapi",
-]
-
-[[package]]
-name = "cmake"
-version = "0.1.46"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7b858541263efe664aead4a5209a4ae5c5d2811167d4ed4ee0944503f8d2089"
-dependencies = [
- "cc",
-]
-
-[[package]]
-name = "color_quant"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
-
-[[package]]
-name = "constant_time_eq"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
-
-[[package]]
-name = "core-foundation"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3"
-dependencies = [
- "core-foundation-sys",
- "libc",
-]
-
-[[package]]
-name = "core-foundation-sys"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
-
-[[package]]
-name = "core-graphics"
-version = "0.22.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "269f35f69b542b80e736a20a89a05215c0ce80c2c03c514abb2e318b78379d86"
-dependencies = [
- "bitflags",
- "core-foundation",
- "core-graphics-types",
- "foreign-types",
- "libc",
-]
-
-[[package]]
-name = "core-graphics-types"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"
-dependencies = [
- "bitflags",
- "core-foundation",
- "foreign-types",
- "libc",
-]
-
-[[package]]
-name = "core-text"
-version = "19.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25"
-dependencies = [
- "core-foundation",
- "core-graphics",
- "foreign-types",
- "libc",
-]
-
-[[package]]
-name = "crc32fast"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
-dependencies = [
- "cfg-if",
-]
-
-[[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 = "darling"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
-dependencies = [
- "darling_core",
- "darling_macro",
-]
-
-[[package]]
-name = "darling_core"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
-dependencies = [
- "fnv",
- "ident_case",
- "proc-macro2",
- "quote",
- "strsim",
- "syn",
-]
-
-[[package]]
-name = "darling_macro"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
-dependencies = [
- "darling_core",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "deflate"
-version = "0.8.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
-dependencies = [
- "adler32",
- "byteorder",
-]
-
-[[package]]
-name = "derive_builder"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0"
-dependencies = [
- "darling",
- "derive_builder_core",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "derive_builder_core"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef"
-dependencies = [
- "darling",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "digest"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
-dependencies = [
- "generic-array",
-]
-
-[[package]]
-name = "dirs-next"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
-dependencies = [
- "cfg-if",
- "dirs-sys-next",
-]
-
-[[package]]
-name = "dirs-sys-next"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
-dependencies = [
- "libc",
- "redox_users",
- "winapi",
-]
-
-[[package]]
-name = "drk_halo2"
-version = "0.1.0"
-dependencies = [
- "ff",
- "halo2",
- "halo2_gadgets",
- "pasta_curves",
- "rand",
-]
-
-[[package]]
-name = "dwrote"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b"
-dependencies = [
- "lazy_static",
- "libc",
- "winapi",
- "wio",
-]
-
-[[package]]
-name = "either"
-version = "1.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
-
-[[package]]
-name = "expat-sys"
-version = "2.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa"
-dependencies = [
- "cmake",
- "pkg-config",
-]
-
-[[package]]
-name = "ff"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2958d04124b9f27f175eaeb9a9f383d026098aa837eadd8ba22c11f13a05b9e"
-dependencies = [
- "bitvec",
- "rand_core",
- "subtle",
-]
-
-[[package]]
-name = "float-ord"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e"
-
-[[package]]
-name = "fnv"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
-
-[[package]]
-name = "font-kit"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46c9a156ec38864999bc9c4156e5f3b50224d4a5578028a64e5a3875caa9ee28"
-dependencies = [
- "bitflags",
- "byteorder",
- "core-foundation",
- "core-graphics",
- "core-text",
- "dirs-next",
- "dwrote",
- "float-ord",
- "freetype",
- "lazy_static",
- "libc",
- "log",
- "pathfinder_geometry",
- "pathfinder_simd",
- "servo-fontconfig",
- "walkdir",
- "winapi",
-]
-
-[[package]]
-name = "foreign-types"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
-dependencies = [
- "foreign-types-shared",
-]
-
-[[package]]
-name = "foreign-types-shared"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
-
-[[package]]
-name = "freetype"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bee38378a9e3db1cc693b4f88d166ae375338a0ff75cb8263e1c601d51f35dc6"
-dependencies = [
- "freetype-sys",
- "libc",
-]
-
-[[package]]
-name = "freetype-sys"
-version = "0.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a"
-dependencies = [
- "cmake",
- "libc",
- "pkg-config",
-]
-
-[[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 = "gif"
-version = "0.11.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b"
-dependencies = [
- "color_quant",
- "weezl",
-]
-
-[[package]]
-name = "gimli"
-version = "0.25.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
-
-[[package]]
-name = "group"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89"
-dependencies = [
- "byteorder",
- "ff",
- "rand_core",
- "subtle",
-]
-
-[[package]]
-name = "halo2"
-version = "0.1.0-beta.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f186b85ed81082fb1cf59d52b0111f02915e89a4ac61d292b38d075e570f3a9"
-dependencies = [
- "backtrace",
- "blake2b_simd",
- "ff",
- "group",
- "pasta_curves",
- "plotters",
- "rand",
- "rayon",
- "tabbycat",
-]
-
-[[package]]
-name = "halo2_gadgets"
-version = "0.0.0"
-source = "git+https://github.com/parazyd/halo2_gadgets.git?rev=8238cb3471b798c76dd53b278524fc80685c7d4f#8238cb3471b798c76dd53b278524fc80685c7d4f"
-dependencies = [
- "arrayvec 0.7.2",
- "bigint",
- "bitvec",
- "ff",
- "group",
- "halo2",
- "lazy_static",
- "memuse",
- "nonempty",
- "pasta_curves",
- "plotters",
- "proptest",
- "rand",
- "reddsa",
- "subtle",
-]
-
-[[package]]
-name = "hermit-abi"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "ident_case"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
-
-[[package]]
-name = "image"
-version = "0.23.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1"
-dependencies = [
- "bytemuck",
- "byteorder",
- "color_quant",
- "jpeg-decoder",
- "num-iter",
- "num-rational",
- "num-traits",
- "png",
-]
-
-[[package]]
-name = "jpeg-decoder"
-version = "0.1.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
-
-[[package]]
-name = "js-sys"
-version = "0.3.55"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
-dependencies = [
- "wasm-bindgen",
-]
-
-[[package]]
-name = "jubjub"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2e7baec19d4e83f9145d4891178101a604565edff9645770fc979804138b04c"
-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.105"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013"
-
-[[package]]
-name = "log"
-version = "0.4.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "memchr"
-version = "2.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
-
-[[package]]
-name = "memoffset"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "memuse"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f69d25cd7528769ad3d897e99eb942774bff8b23165012af490351a44c5b583b"
-dependencies = [
- "nonempty",
-]
-
-[[package]]
-name = "miniz_oxide"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
-dependencies = [
- "adler32",
-]
-
-[[package]]
-name = "miniz_oxide"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
-dependencies = [
- "adler",
- "autocfg",
-]
-
-[[package]]
-name = "nonempty"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7"
-
-[[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-iter"
-version = "0.1.42"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
-dependencies = [
- "autocfg",
- "num-integer",
- "num-traits",
-]
-
-[[package]]
-name = "num-rational"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
-dependencies = [
- "autocfg",
- "num-integer",
- "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 = "object"
-version = "0.27.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "pasta_curves"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d647d91972bad78120fd61e06b225fcda117805c9bbf17676b51bd03a251278b"
-dependencies = [
- "blake2b_simd",
- "ff",
- "group",
- "lazy_static",
- "rand",
- "static_assertions",
- "subtle",
-]
-
-[[package]]
-name = "pathfinder_geometry"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3"
-dependencies = [
- "log",
- "pathfinder_simd",
-]
-
-[[package]]
-name = "pathfinder_simd"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39fe46acc5503595e5949c17b818714d26fdf9b4920eacf3b2947f0199f4a6ff"
-dependencies = [
- "rustc_version",
-]
-
-[[package]]
-name = "pest"
-version = "2.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
-dependencies = [
- "ucd-trie",
-]
-
-[[package]]
-name = "pkg-config"
-version = "0.3.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f"
-
-[[package]]
-name = "plotters"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a"
-dependencies = [
- "chrono",
- "font-kit",
- "image",
- "lazy_static",
- "num-traits",
- "pathfinder_geometry",
- "plotters-backend",
- "plotters-bitmap",
- "plotters-svg",
- "ttf-parser",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "plotters-backend"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c"
-
-[[package]]
-name = "plotters-bitmap"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21362fa905695e5618aefd169358f52e0e8bc4a8e05333cf780fda8cddc00b54"
-dependencies = [
- "gif",
- "image",
- "plotters-backend",
-]
-
-[[package]]
-name = "plotters-svg"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9"
-dependencies = [
- "plotters-backend",
-]
-
-[[package]]
-name = "png"
-version = "0.16.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
-dependencies = [
- "bitflags",
- "crc32fast",
- "deflate",
- "miniz_oxide 0.3.7",
-]
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
-dependencies = [
- "unicode-xid",
-]
-
-[[package]]
-name = "proptest"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e0d9cc07f18492d879586c92b485def06bc850da3118075cd45d50e9c95b0e5"
-dependencies = [
- "bit-set",
- "bitflags",
- "byteorder",
- "lazy_static",
- "num-traits",
- "quick-error 2.0.1",
- "rand",
- "rand_chacha",
- "rand_xorshift",
- "regex-syntax",
- "rusty-fork",
- "tempfile",
-]
-
-[[package]]
-name = "quick-error"
-version = "1.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
-
-[[package]]
-name = "quick-error"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
-
-[[package]]
-name = "quote"
-version = "1.0.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
-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 = "rand_xorshift"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
-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=416a6a8ebf8bd42c114c938883016c04f338de72#416a6a8ebf8bd42c114c938883016c04f338de72"
-dependencies = [
- "blake2b_simd",
- "byteorder",
- "digest",
- "group",
- "jubjub",
- "pasta_curves",
- "rand_core",
- "serde",
- "thiserror",
- "zeroize",
-]
-
-[[package]]
-name = "redox_syscall"
-version = "0.2.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "redox_users"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
-dependencies = [
- "getrandom",
- "redox_syscall",
-]
-
-[[package]]
-name = "regex"
-version = "1.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
-
-[[package]]
-name = "remove_dir_all"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "rustc-demangle"
-version = "0.1.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
-
-[[package]]
-name = "rustc_version"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee"
-dependencies = [
- "semver",
-]
-
-[[package]]
-name = "rusty-fork"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f"
-dependencies = [
- "fnv",
- "quick-error 1.2.3",
- "tempfile",
- "wait-timeout",
-]
-
-[[package]]
-name = "same-file"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "scopeguard"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
-
-[[package]]
-name = "semver"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
-dependencies = [
- "semver-parser",
-]
-
-[[package]]
-name = "semver-parser"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
-dependencies = [
- "pest",
-]
-
-[[package]]
-name = "serde"
-version = "1.0.130"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.130"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "servo-fontconfig"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7e3e22fe5fd73d04ebf0daa049d3efe3eae55369ce38ab16d07ddd9ac5c217c"
-dependencies = [
- "libc",
- "servo-fontconfig-sys",
-]
-
-[[package]]
-name = "servo-fontconfig-sys"
-version = "5.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e36b879db9892dfa40f95da1c38a835d41634b825fbd8c4c418093d53c24b388"
-dependencies = [
- "expat-sys",
- "freetype-sys",
- "pkg-config",
-]
-
-[[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
-[[package]]
-name = "strsim"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
-
-[[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.81"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-xid",
-]
-
-[[package]]
-name = "synstructure"
-version = "0.12.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "unicode-xid",
-]
-
-[[package]]
-name = "tabbycat"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c45590f0f859197b4545be1b17b2bc3cc7bb075f7d1cc0ea1dc6521c0bf256a3"
-dependencies = [
- "anyhow",
- "derive_builder",
- "regex",
-]
-
-[[package]]
-name = "tap"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
-
-[[package]]
-name = "tempfile"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
-dependencies = [
- "cfg-if",
- "libc",
- "rand",
- "redox_syscall",
- "remove_dir_all",
- "winapi",
-]
-
-[[package]]
-name = "thiserror"
-version = "1.0.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "1.0.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "time"
-version = "0.1.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
-dependencies = [
- "libc",
- "wasi",
- "winapi",
-]
-
-[[package]]
-name = "ttf-parser"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ae2f58a822f08abdaf668897e96a5656fe72f5a9ce66422423e8849384872e6"
-
-[[package]]
-name = "typenum"
-version = "1.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec"
-
-[[package]]
-name = "ucd-trie"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
-
-[[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 = "wait-timeout"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "walkdir"
-version = "2.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
-dependencies = [
- "same-file",
- "winapi",
- "winapi-util",
-]
-
-[[package]]
-name = "wasi"
-version = "0.10.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
-
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.78"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
-dependencies = [
- "cfg-if",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.78"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
-dependencies = [
- "bumpalo",
- "lazy_static",
- "log",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.78"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.78"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.78"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
-
-[[package]]
-name = "web-sys"
-version = "0.3.55"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "weezl"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e"
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "wio"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "wyz"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188"
-dependencies = [
- "tap",
-]
-
-[[package]]
-name = "zeroize"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf68b08513768deaa790264a7fac27a58cbf2705cfcdc9448362229217d7e970"
-dependencies = [
- "zeroize_derive",
-]
-
-[[package]]
-name = "zeroize_derive"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdff2024a851a322b08f179173ae2ba620445aef1e838f0c196820eade4ae0c7"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]

+ 0 - 19
examples/halo2/Cargo.toml

@@ -1,19 +0,0 @@
-[package]
-name = "drk_halo2"
-version = "0.1.0"
-authors = ["Ivan Jelincic <parazyd@dyne.org>"]
-edition = "2021"
-
-[dependencies]
-rand = "0.8.4"
-ff = "0.11.0"
-pasta_curves = "0.2.1"
-
-[dependencies.halo2]
-version = "=0.1.0-beta.1"
-features = ["dev-graph", "gadget-traces", "sanity-checks"]
-
-[dependencies.halo2_gadgets]
-git = "https://github.com/parazyd/halo2_gadgets.git"
-rev = "8238cb3471b798c76dd53b278524fc80685c7d4f"
-features = ["dev-graph", "test-dependencies"]

+ 0 - 603
examples/halo2/src/bin/burn.rs

@@ -1,603 +0,0 @@
-use std::iter;
-use std::time::Instant;
-
-use halo2::{
-    circuit::{Layouter, SimpleFloorPlanner},
-    dev::MockProver,
-    plonk::{
-        Advice, Circuit, Column, ConstraintSystem, Error, Instance as InstanceColumn, Selector,
-    },
-    poly::Rotation,
-};
-use halo2_gadgets::{
-    ecc::{
-        chip::{EccChip, EccConfig},
-        FixedPoint, FixedPoints,
-    },
-    poseidon::{
-        Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig,
-        StateWord, Word,
-    },
-    primitives,
-    primitives::{
-        poseidon::{ConstantLength, P128Pow5T3},
-        sinsemilla::S_PERSONALIZATION,
-    },
-    sinsemilla::{
-        chip::{SinsemillaChip, SinsemillaConfig},
-        merkle::chip::{MerkleChip, MerkleConfig},
-        merkle::MerklePath,
-    },
-    utilities::{
-        lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
-    },
-};
-use pasta_curves::{
-    arithmetic::{CurveAffine, Field},
-    group::{ff::PrimeFieldBits, Curve},
-    pallas,
-};
-use rand::rngs::OsRng;
-
-use drk_halo2::{
-    constants::{
-        sinsemilla::{OrchardCommitDomains, OrchardHashDomains, MERKLE_CRH_PERSONALIZATION},
-        OrchardFixedBases,
-    },
-    crypto::pedersen_commitment,
-    proof::{Proof, ProvingKey, VerifyingKey},
-    spec::i2lebsp,
-};
-
-#[derive(Clone, Debug)]
-struct BurnConfig {
-    primary: Column<InstanceColumn>,
-    q_add: Selector,
-    advices: [Column<Advice>; 10],
-    ecc_config: EccConfig,
-    merkle_config_1: MerkleConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
-    merkle_config_2: MerkleConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
-    sinsemilla_config_1:
-        SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
-    sinsemilla_config_2:
-        SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
-    poseidon_config: PoseidonConfig<pallas::Base>,
-}
-
-impl BurnConfig {
-    fn ecc_chip(&self) -> EccChip<OrchardFixedBases> {
-        EccChip::construct(self.ecc_config.clone())
-    }
-
-    /*
-    fn sinsemilla_chip_1(
-        &self,
-    ) -> SinsemillaChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
-        SinsemillaChip::construct(self.sinsemilla_config_1.clone())
-    }
-
-    fn sinsemilla_chip_2(
-        &self,
-    ) -> SinsemillaChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
-        SinsemillaChip::construct(self.sinsemilla_config_2.clone())
-    }
-    */
-
-    fn merkle_chip_1(
-        &self,
-    ) -> MerkleChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
-        MerkleChip::construct(self.merkle_config_1.clone())
-    }
-
-    fn merkle_chip_2(
-        &self,
-    ) -> MerkleChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
-        MerkleChip::construct(self.merkle_config_2.clone())
-    }
-
-    fn poseidon_chip(&self) -> PoseidonChip<pallas::Base> {
-        PoseidonChip::construct(self.poseidon_config.clone())
-    }
-}
-
-// The public input array offsets
-const BURN_NULLIFIER_OFFSET: usize = 0;
-const BURN_VALCOMX_OFFSET: usize = 1;
-const BURN_VALCOMY_OFFSET: usize = 2;
-const BURN_ASSCOMX_OFFSET: usize = 3;
-const BURN_ASSCOMY_OFFSET: usize = 4;
-const BURN_MERKLEROOT_OFFSET: usize = 5;
-const BURN_SIGKEYX_OFFSET: usize = 6;
-const BURN_SIGKEYY_OFFSET: usize = 7;
-
-#[derive(Default, Debug)]
-struct BurnCircuit {
-    secret_key: Option<pallas::Base>,
-    serial: Option<pallas::Base>,
-    value: Option<pallas::Base>,
-    asset: Option<pallas::Base>,
-    coin_blind: Option<pallas::Base>,
-    value_blind: Option<pallas::Scalar>,
-    asset_blind: Option<pallas::Scalar>,
-    leaf: Option<pallas::Base>,
-    leaf_pos: Option<u32>,
-    merkle_path: Option<[pallas::Base; 32]>,
-    sig_secret: Option<pallas::Scalar>,
-}
-
-impl UtilitiesInstructions<pallas::Base> for BurnCircuit {
-    type Var = CellValue<pallas::Base>;
-}
-
-impl Circuit<pallas::Base> for BurnCircuit {
-    type Config = BurnConfig;
-    type FloorPlanner = SimpleFloorPlanner;
-
-    fn without_witnesses(&self) -> Self {
-        Self::default()
-    }
-
-    fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
-        // Advice columns used in the circuit
-        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 three field elements
-        let q_add = meta.selector();
-        meta.create_gate("a+b+c", |meta| {
-            let q_add = meta.query_selector(q_add);
-            let sum = meta.query_advice(advices[5], Rotation::cur());
-            let a = meta.query_advice(advices[6], Rotation::cur());
-            let b = meta.query_advice(advices[7], Rotation::cur());
-            let c = meta.query_advice(advices[8], Rotation::cur());
-
-            vec![q_add * (a + b + c - sum)]
-        });
-
-        // Fixed columns for the Sinsemilla generator lookup table
-        let table_idx = meta.lookup_table_column();
-        let lookup = (
-            table_idx,
-            meta.lookup_table_column(),
-            meta.lookup_table_column(),
-        );
-
-        // Instance column used for public inputs
-        let primary = meta.instance_column();
-        meta.enable_equality(primary.into());
-
-        // Permutation over all advice columns
-        for advice in advices.iter() {
-            meta.enable_equality((*advice).into());
-        }
-
-        // Poseidon requires four advice columns, while ECC incomplete addition
-        // requires six. We can reduce the proof size by sharing fixed columns
-        // between the ECC and Poseidon chips.
-        // TODO: For multiple invocations they could/should be configured in
-        // parallel rather than sharing perhaps?
-        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();
-
-        // Also use the first Lagrange coefficient column for loading global constants.
-        meta.enable_constant(lagrange_coeffs[0]);
-
-        // Use one of the right-most advice columns for all of our range checks.
-        let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx);
-
-        // Configuration for curve point operations.
-        // This uses 10 advice columns and spans the whole circuit.
-        let ecc_config = EccChip::<OrchardFixedBases>::configure(
-            meta,
-            advices,
-            lagrange_coeffs,
-            range_check.clone(),
-        );
-
-        // Configuration for the Poseidon hash
-        let poseidon_config = PoseidonChip::configure(
-            meta,
-            P128Pow5T3,
-            advices[6..9].try_into().unwrap(),
-            advices[5],
-            rc_a,
-            rc_b,
-        );
-
-        // Configuration for a Sinsemilla hash instantiation and a
-        // Merkle hash instantiation using this Sinsemilla instance.
-        // Since the Sinsemilla config uses only 5 advice columns,
-        // we can fit two instances side-by-side.
-        let (sinsemilla_config_1, merkle_config_1) = {
-            let sinsemilla_config_1 = SinsemillaChip::configure(
-                meta,
-                advices[..5].try_into().unwrap(),
-                advices[6],
-                lagrange_coeffs[0],
-                lookup,
-                range_check.clone(),
-            );
-            let merkle_config_1 = MerkleChip::configure(meta, sinsemilla_config_1.clone());
-            (sinsemilla_config_1, merkle_config_1)
-        };
-
-        // Configuration for a Sinsemilla hash instantiation and a
-        // Merkle hash instantiation using this Sinsemilla instance.
-        // Since the Sinsemilla config uses only 5 advice columns,
-        // we can fit two instances side-by-side.
-        let (sinsemilla_config_2, merkle_config_2) = {
-            let sinsemilla_config_2 = SinsemillaChip::configure(
-                meta,
-                advices[5..].try_into().unwrap(),
-                advices[7],
-                lagrange_coeffs[1],
-                lookup,
-                range_check,
-            );
-            let merkle_config_2 = MerkleChip::configure(meta, sinsemilla_config_2.clone());
-
-            (sinsemilla_config_2, merkle_config_2)
-        };
-
-        BurnConfig {
-            primary,
-            q_add,
-            advices,
-            ecc_config,
-            merkle_config_1,
-            merkle_config_2,
-            sinsemilla_config_1,
-            sinsemilla_config_2,
-            poseidon_config,
-        }
-    }
-
-    fn synthesize(
-        &self,
-        config: Self::Config,
-        mut layouter: impl Layouter<pallas::Base>,
-    ) -> Result<(), Error> {
-        // Load the Sinsemilla generator lookup table used by the whole circuit.
-        SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?;
-
-        // Construct the ECC chip.
-        let ecc_chip = config.ecc_chip();
-
-        // Construct the merkle chips
-        let merkle_chip_1 = config.merkle_chip_1();
-        let merkle_chip_2 = config.merkle_chip_2();
-
-        // =========
-        // Nullifier
-        // =========
-        let hashed_secret_key = self.load_private(
-            layouter.namespace(|| "load sinsemilla(secret key)"),
-            config.advices[0],
-            self.secret_key,
-        )?;
-
-        let serial = self.load_private(
-            layouter.namespace(|| "load serial"),
-            config.advices[0],
-            self.serial,
-        )?;
-
-        let message = [hashed_secret_key, serial];
-        let hash = {
-            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::<_, _, P128Pow5T3, 3, 2>::from_inner(StateWord::new(
-                            var, value,
-                        )))
-                    };
-                    Ok([message_word(0)?, message_word(1)?])
-                },
-            )?;
-
-            let poseidon_hasher = PoseidonHash::init(
-                config.poseidon_chip(),
-                layouter.namespace(|| "Poseidon init"),
-                ConstantLength::<2>,
-            )?;
-
-            let poseidon_output = poseidon_hasher.hash(
-                layouter.namespace(|| "Poseidon hash (secretkey, serial)"),
-                poseidon_message,
-            )?;
-
-            let poseidon_output: CellValue<pallas::Base> = poseidon_output.inner().into();
-            poseidon_output
-        };
-
-        layouter.constrain_instance(hash.cell(), config.primary, BURN_NULLIFIER_OFFSET)?;
-
-        // ===========
-        // Merkle root
-        // ===========
-        let leaf = self.load_private(
-            layouter.namespace(|| "load leaf"),
-            config.advices[0],
-            self.leaf,
-        )?;
-
-        let path = MerklePath {
-            chip_1: merkle_chip_1,
-            chip_2: merkle_chip_2,
-            domain: OrchardHashDomains::MerkleCrh,
-            leaf_pos: self.leaf_pos,
-            path: self.merkle_path,
-        };
-
-        let computed_final_root =
-            path.calculate_root(layouter.namespace(|| "calculate root"), leaf)?;
-
-        layouter.constrain_instance(
-            computed_final_root.cell(),
-            config.primary,
-            BURN_MERKLEROOT_OFFSET,
-        )?;
-
-        // ================
-        // Value commitment
-        // ================
-
-        // This constant one is used for multiplication
-        let one = self.load_private(
-            layouter.namespace(|| "load constant one"),
-            config.advices[0],
-            Some(pallas::Base::one()),
-        )?;
-
-        let value = self.load_private(
-            layouter.namespace(|| "load value"),
-            config.advices[0],
-            self.value,
-        )?;
-
-        // 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 value commitment coordinates
-        let value_commit = commitment.add(layouter.namespace(|| "valuecommit"), &blind)?;
-        layouter.constrain_instance(
-            value_commit.inner().x().cell(),
-            config.primary,
-            BURN_VALCOMX_OFFSET,
-        )?;
-        layouter.constrain_instance(
-            value_commit.inner().y().cell(),
-            config.primary,
-            BURN_VALCOMY_OFFSET,
-        )?;
-
-        // ================
-        // Asset commitment
-        // ================
-
-        let asset = self.load_private(
-            layouter.namespace(|| "load asset"),
-            config.advices[0],
-            self.asset,
-        )?;
-
-        // 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 asset commitment coordinates
-        let asset_commit = commitment.add(layouter.namespace(|| "assetcommit"), &blind)?;
-        layouter.constrain_instance(
-            asset_commit.inner().x().cell(),
-            config.primary,
-            BURN_ASSCOMX_OFFSET,
-        )?;
-        layouter.constrain_instance(
-            asset_commit.inner().y().cell(),
-            config.primary,
-            BURN_ASSCOMY_OFFSET,
-        )?;
-
-        // ========================
-        // Signature key derivation
-        // ========================
-        let (sig_pub, _) = {
-            let spend_auth_g = OrchardFixedBases::SpendAuthG;
-            let spend_auth_g = FixedPoint::from_inner(ecc_chip, spend_auth_g);
-            // TODO: Do we need to load sig_secret somewhere first?
-            spend_auth_g.mul(layouter.namespace(|| "[x_s] SpendAuthG"), self.sig_secret)?
-        };
-
-        layouter.constrain_instance(
-            sig_pub.inner().x().cell(),
-            config.primary,
-            BURN_SIGKEYX_OFFSET,
-        )?;
-        layouter.constrain_instance(
-            sig_pub.inner().y().cell(),
-            config.primary,
-            BURN_SIGKEYY_OFFSET,
-        )?;
-
-        // At this point we've enforced all of our public inputs.
-        Ok(())
-    }
-}
-
-fn root(path: [pallas::Base; 32], leaf_pos: u32, leaf: pallas::Base) -> pallas::Base {
-    let domain = primitives::sinsemilla::HashDomain::new(MERKLE_CRH_PERSONALIZATION);
-
-    let pos_bool = i2lebsp::<32>(leaf_pos as u64);
-
-    let mut node = leaf;
-    for (l, (sibling, pos)) in path.iter().zip(pos_bool.iter()).enumerate() {
-        let (left, right) = if *pos {
-            (*sibling, node)
-        } else {
-            (node, *sibling)
-        };
-
-        let l_star = i2lebsp::<10>(l as u64);
-        let left: Vec<_> = left.to_le_bits().iter().by_val().take(255).collect();
-        let right: Vec<_> = right.to_le_bits().iter().by_val().take(255).collect();
-
-        let mut message = l_star.to_vec();
-        message.extend_from_slice(&left);
-        message.extend_from_slice(&right);
-
-        node = domain.hash(message.into_iter()).unwrap();
-    }
-    node
-}
-
-fn main() {
-    // The number of rows in our circuit cannot exceed 2^k
-    let k: u32 = 11;
-
-    let secret_key = pallas::Scalar::random(&mut OsRng);
-    let serial = pallas::Base::random(&mut OsRng);
-
-    let value = 42;
-    let asset = 1;
-
-    // Nullifier = poseidon(sinsemilla(secret_key), serial)
-    let domain = primitives::sinsemilla::HashDomain::new(S_PERSONALIZATION);
-    let bits_secretkey: Vec<bool> = secret_key.to_le_bits().iter().by_val().collect();
-    let hashed_secret_key = domain.hash(iter::empty().chain(bits_secretkey)).unwrap();
-
-    let nullifier = [hashed_secret_key, serial];
-    let nullifier =
-        primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(nullifier);
-
-    // Public key derivation
-    let public_key = OrchardFixedBases::SpendAuthG.generator() * secret_key;
-    let coords = public_key.to_affine().coordinates().unwrap();
-
-    // Construct Coin
-    let mut coin = pallas::Base::zero();
-    let coin_blind = pallas::Base::random(&mut OsRng);
-    let messages = [
-        [*coords.x(), *coords.y()],
-        [pallas::Base::from(value), pallas::Base::from(asset)],
-        [serial, coin_blind],
-    ];
-
-    for msg in messages.iter() {
-        let hash = primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(*msg);
-        coin += hash;
-    }
-
-    // Merkle root
-    let leaf = pallas::Base::random(&mut OsRng);
-    let pos = rand::random::<u32>();
-    let path: Vec<_> = (0..32).map(|_| pallas::Base::random(&mut OsRng)).collect();
-    let merkle_root = root(path.clone().try_into().unwrap(), pos, leaf);
-
-    // Value and asset commitments
-    let value_blind = pallas::Scalar::random(&mut OsRng);
-    let asset_blind = pallas::Scalar::random(&mut OsRng);
-    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 = asset_commit.to_affine().coordinates().unwrap();
-
-    // Derive signature public key from signature secret key
-    let sig_secret = pallas::Scalar::random(&mut OsRng);
-    let sig_pubkey = OrchardFixedBases::SpendAuthG.generator() * sig_secret;
-    let sig_coords = sig_pubkey.to_affine().coordinates().unwrap();
-
-    let public_inputs = vec![
-        nullifier,
-        *value_coords.x(),
-        *value_coords.y(),
-        *asset_coords.x(),
-        *asset_coords.y(),
-        merkle_root,
-        *sig_coords.x(),
-        *sig_coords.y(),
-    ];
-
-    let circuit = BurnCircuit {
-        secret_key: Some(hashed_secret_key),
-        serial: Some(serial),
-        value: Some(pallas::Base::from(value)),
-        asset: Some(pallas::Base::from(asset)),
-        coin_blind: Some(coin_blind),
-        value_blind: Some(value_blind),
-        asset_blind: Some(asset_blind),
-        leaf: Some(leaf),
-        leaf_pos: Some(pos),
-        merkle_path: Some(path.try_into().unwrap()),
-        sig_secret: Some(sig_secret),
-    };
-
-    let prover = MockProver::run(k, &circuit, vec![public_inputs.clone()]).unwrap();
-    assert_eq!(prover.verify(), Ok(()));
-
-    // Actual ZK proof
-    let start = Instant::now();
-    let vk = VerifyingKey::build(k, BurnCircuit::default());
-    let pk = ProvingKey::build(k, BurnCircuit::default());
-    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());
-}

+ 0 - 455
examples/halo2/src/bin/mint.rs

@@ -1,455 +0,0 @@
-use std::time::Instant;
-
-use halo2::{
-    circuit::{Layouter, SimpleFloorPlanner},
-    dev::MockProver,
-    plonk::{
-        Advice, Circuit, Column, ConstraintSystem, Error, Instance as InstanceColumn, Selector,
-    },
-    poly::Rotation,
-};
-use halo2_gadgets::{
-    ecc::{
-        chip::{EccChip, EccConfig},
-        FixedPoint,
-    },
-    poseidon::{
-        Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig,
-        StateWord, Word,
-    },
-    primitives,
-    primitives::poseidon::{ConstantLength, P128Pow5T3},
-    utilities::{
-        copy, lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
-    },
-};
-use pasta_curves::{
-    arithmetic::{CurveAffine, Field},
-    group::{Curve, Group},
-    pallas,
-};
-use rand::rngs::OsRng;
-
-use drk_halo2::{
-    constants::OrchardFixedBases,
-    crypto::pedersen_commitment,
-    proof::{Proof, ProvingKey, VerifyingKey},
-};
-
-#[derive(Clone, Debug)]
-struct MintConfig {
-    primary: Column<InstanceColumn>,
-    q_add: Selector,
-    advices: [Column<Advice>; 10],
-    ecc_config: EccConfig,
-    poseidon_config: PoseidonConfig<pallas::Base>,
-}
-
-impl MintConfig {
-    fn ecc_chip(&self) -> EccChip<OrchardFixedBases> {
-        EccChip::construct(self.ecc_config.clone())
-    }
-
-    fn poseidon_chip(&self) -> PoseidonChip<pallas::Base> {
-        PoseidonChip::construct(self.poseidon_config.clone())
-    }
-}
-
-// The public input array offsets
-const MINT_COIN_OFFSET: usize = 0;
-const MINT_VALCOMX_OFFSET: usize = 1;
-const MINT_VALCOMY_OFFSET: usize = 2;
-const MINT_ASSCOMX_OFFSET: usize = 3;
-const MINT_ASSCOMY_OFFSET: usize = 4;
-
-#[derive(Default, Debug)]
-struct MintCircuit {
-    pub_x: Option<pallas::Base>,         // x coordinate for pubkey
-    pub_y: Option<pallas::Base>,         // y coordinate for pubkey
-    value: Option<pallas::Base>,         // The value of this coin
-    asset: Option<pallas::Base>,         // The asset ID
-    serial: Option<pallas::Base>,        // Unique serial number corresponding to this coin
-    coin_blind: Option<pallas::Base>,    // Random blinding factor for coin
-    value_blind: Option<pallas::Scalar>, // Random blinding factor for value commitment
-    asset_blind: Option<pallas::Scalar>, // Random blinding factor for the asset ID
-}
-
-impl UtilitiesInstructions<pallas::Base> for MintCircuit {
-    type Var = CellValue<pallas::Base>;
-}
-
-impl Circuit<pallas::Base> for MintCircuit {
-    type Config = MintConfig;
-    type FloorPlanner = SimpleFloorPlanner;
-
-    fn without_witnesses(&self) -> Self {
-        Self::default()
-    }
-
-    fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
-        // Advice columns used in the circuit
-        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
-        /*
-        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 q_add = meta.selector();
-        meta.create_gate("a+b+c", |meta| {
-            let q_add = meta.query_selector(q_add);
-            let sum = meta.query_advice(advices[5], Rotation::cur());
-            let a = meta.query_advice(advices[6], Rotation::cur());
-            let b = meta.query_advice(advices[7], Rotation::cur());
-            let c = meta.query_advice(advices[8], Rotation::cur());
-
-            vec![q_add * (a + b + c - sum)]
-        });
-
-        // Fixed columns for the Sinsemilla generator lookup table
-        let table_idx = meta.lookup_table_column();
-        let _lookup = (
-            table_idx,
-            meta.lookup_table_column(),
-            meta.lookup_table_column(),
-        );
-
-        // Instance column used for public inputs
-        let primary = meta.instance_column();
-        meta.enable_equality(primary.into());
-
-        // Permutation over all advice columns
-        for advice in advices.iter() {
-            meta.enable_equality((*advice).into());
-        }
-
-        // Poseidon requires four advice columns, while ECC incomplete addition
-        // requires six. We can reduce the proof size by sharing fixed columns
-        // between the ECC and Poseidon chips.
-        // TODO: For multiple invocations they could/should be configured in
-        // parallel rather than sharing perhaps?
-        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();
-
-        // Also use the first Lagrange coefficient column for loading global constants.
-        meta.enable_constant(lagrange_coeffs[0]);
-
-        // Use one of the right-most advice columns for all of our range checks.
-        let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx);
-
-        // Configuration for curve point operations.
-        // This uses 10 advice columns and spans the whole circuit.
-        let ecc_config =
-            EccChip::<OrchardFixedBases>::configure(meta, advices, lagrange_coeffs, range_check);
-
-        // Configuration for the Poseidon hash
-        let poseidon_config = PoseidonChip::configure(
-            meta,
-            P128Pow5T3,
-            advices[6..9].try_into().unwrap(),
-            advices[5],
-            rc_a,
-            rc_b,
-        );
-
-        MintConfig {
-            primary,
-            q_add,
-            advices,
-            ecc_config,
-            poseidon_config,
-        }
-    }
-
-    fn synthesize(
-        &self,
-        config: Self::Config,
-        mut layouter: impl Layouter<pallas::Base>,
-    ) -> Result<(), Error> {
-        let ecc_chip = config.ecc_chip();
-
-        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
-        // =========
-        let messages = [[pub_x, pub_y], [value, asset], [serial, coin_blind]];
-        let mut hashes = vec![];
-
-        for message in messages.iter() {
-            let hash = {
-                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::<_, _, P128Pow5T3, 3, 2>::from_inner(StateWord::new(
-                                var, value,
-                            )))
-                        };
-                        Ok([message_word(0)?, message_word(1)?])
-                    },
-                )?;
-
-                let poseidon_hasher = PoseidonHash::init(
-                    config.poseidon_chip(),
-                    layouter.namespace(|| "Poseidon init"),
-                    ConstantLength::<2>,
-                )?;
-
-                let poseidon_output = poseidon_hasher.hash(
-                    layouter.namespace(|| "Poseidon hash (a, b)"),
-                    poseidon_message,
-                )?;
-
-                let poseidon_output: CellValue<pallas::Base> = poseidon_output.inner().into();
-                poseidon_output
-            };
-
-            hashes.push(hash);
-        }
-
-        let coin = layouter.assign_region(
-            || " `coin` = hash(a,b) + hash(c, d) + hash(e, f)",
-            |mut region| {
-                config.q_add.enable(&mut region, 0)?;
-
-                copy(&mut region, || "copy ab", config.advices[6], 0, &hashes[0])?;
-                copy(&mut region, || "copy cd", config.advices[7], 0, &hashes[1])?;
-                copy(&mut region, || "copy ef", config.advices[8], 0, &hashes[2])?;
-
-                let scalar_val = hashes[0]
-                    .value()
-                    .zip(hashes[1].value())
-                    .zip(hashes[2].value())
-                    .map(|(abcd, ef)| abcd.0 + abcd.1 + ef);
-
-                let cell = region.assign_advice(
-                    || "hash(a,b)+hash(c,d)+hash(e,f)",
-                    config.advices[5],
-                    0,
-                    || scalar_val.ok_or(Error::SynthesisError),
-                )?;
-                Ok(CellValue::new(cell, scalar_val))
-            },
-        )?;
-
-        // Constrain the coin C
-        layouter.constrain_instance(coin.cell(), config.primary, MINT_COIN_OFFSET)?;
-
-        // ================
-        // Value commitment
-        // ================
-
-        // This constant one is used for short multiplication
-        let one = self.load_private(
-            layouter.namespace(|| "load constant one"),
-            config.advices[0],
-            Some(pallas::Base::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 value commitment coordinates
-        let value_commit = commitment.add(layouter.namespace(|| "valuecommit"), &blind)?;
-        layouter.constrain_instance(
-            value_commit.inner().x().cell(),
-            config.primary,
-            MINT_VALCOMX_OFFSET,
-        )?;
-        layouter.constrain_instance(
-            value_commit.inner().y().cell(),
-            config.primary,
-            MINT_VALCOMY_OFFSET,
-        )?;
-
-        // ================
-        // 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, asset_commit_r);
-            asset_commit_r.mul(layouter.namespace(|| "[asset_blind] ValueCommitR"), rca)?
-        };
-
-        // Constrain the asset commitment coordinates
-        let asset_commit = commitment.add(layouter.namespace(|| "assetcommit"), &blind)?;
-        layouter.constrain_instance(
-            asset_commit.inner().x().cell(),
-            config.primary,
-            MINT_ASSCOMX_OFFSET,
-        )?;
-        layouter.constrain_instance(
-            asset_commit.inner().y().cell(),
-            config.primary,
-            MINT_ASSCOMY_OFFSET,
-        )?;
-
-        // At this point we've enforced all of our public inputs.
-        Ok(())
-    }
-}
-
-fn main() {
-    // The number of rows in our circuit cannot exceed 2^k
-    let k: u32 = 9;
-
-    let pubkey = pallas::Point::random(&mut OsRng);
-    let coords = pubkey.to_affine().coordinates().unwrap();
-
-    let value = 42;
-    let asset = 1;
-
-    let value_blind = pallas::Scalar::random(&mut OsRng);
-    let asset_blind = pallas::Scalar::random(&mut OsRng);
-
-    let serial = pallas::Base::random(&mut OsRng);
-    let coin_blind = pallas::Base::random(&mut OsRng);
-
-    // poseidon_hash(x, y) + poseidon_hash(value, asset) + poseidon_hash(serial, coin_blind)
-    let mut coin = pallas::Base::zero();
-
-    let messages = [
-        [*coords.x(), *coords.y()],
-        [pallas::Base::from(value), pallas::Base::from(asset)],
-        [serial, coin_blind],
-    ];
-
-    for msg in messages.iter() {
-        let hash = primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(*msg);
-        coin += hash;
-    }
-
-    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 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(pallas::Base::from(value)),
-        asset: Some(pallas::Base::from(asset)),
-        serial: Some(serial),
-        coin_blind: Some(coin_blind),
-        value_blind: Some(value_blind),
-        asset_blind: Some(asset_blind),
-    };
-
-    let prover = MockProver::run(k, &circuit, vec![public_inputs.clone()]).unwrap();
-    assert_eq!(prover.verify(), Ok(()));
-
-    // Actual ZK proof
-    let start = Instant::now();
-    let vk = VerifyingKey::build(k, MintCircuit::default());
-    let pk = ProvingKey::build(k, MintCircuit::default());
-    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());
-}

+ 0 - 249
examples/halo2/src/bin/poseidon.rs

@@ -1,249 +0,0 @@
-use std::time::Instant;
-
-use halo2::{
-    circuit::{Layouter, SimpleFloorPlanner},
-    dev::MockProver,
-    plonk::{
-        Advice, Circuit, Column, ConstraintSystem, Error, Instance as InstanceColumn, Selector,
-    },
-    poly::Rotation,
-};
-use halo2_gadgets::{
-    poseidon::{
-        Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig,
-        StateWord, Word,
-    },
-    primitives,
-    primitives::poseidon::{ConstantLength, P128Pow5T3},
-    utilities::{copy, CellValue, UtilitiesInstructions, Var},
-};
-use pasta_curves::pallas;
-
-use drk_halo2::proof::{Proof, ProvingKey, VerifyingKey};
-
-#[derive(Clone, Debug)]
-struct Config {
-    primary: Column<InstanceColumn>,
-    q_add: Selector,
-    advices: [Column<Advice>; 10],
-    poseidon_config: PoseidonConfig<pallas::Base>,
-}
-
-impl Config {
-    fn poseidon_chip(&self) -> PoseidonChip<pallas::Base> {
-        PoseidonChip::construct(self.poseidon_config.clone())
-    }
-}
-
-#[derive(Default, Debug)]
-struct HashCircuit {
-    a: Option<pallas::Base>,
-    b: Option<pallas::Base>,
-    c: Option<pallas::Base>,
-}
-
-impl UtilitiesInstructions<pallas::Base> for HashCircuit {
-    type Var = CellValue<pallas::Base>;
-}
-
-impl Circuit<pallas::Base> for HashCircuit {
-    type Config = Config;
-    type FloorPlanner = SimpleFloorPlanner;
-
-    fn without_witnesses(&self) -> Self {
-        Self::default()
-    }
-
-    fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
-        // Advice columns used in the circuit
-        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
-        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)]
-        });
-
-        // Instance column used for public inputs
-        let primary = meta.instance_column();
-        meta.enable_equality(primary.into());
-
-        // Permutation over all advice columns
-        for advice in advices.iter() {
-            meta.enable_equality((*advice).into());
-        }
-
-        // Poseidon requires four advice columns, while ECC incomplete addition
-        // requires six. We can reduce the proof size by sharing fixed columns
-        // between the ECC and Poseidon chips.
-        // TODO: For multiple invocations they could/should be configured in
-        // parallel rather than sharing perhaps?
-        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();
-
-        // Also use the first Lagrange coefficient column for loading global constants.
-        meta.enable_constant(lagrange_coeffs[0]);
-
-        // Configuration for the Poseidon hash
-        let poseidon_config = PoseidonChip::configure(
-            meta,
-            P128Pow5T3,
-            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<pallas::Base>,
-    ) -> 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::<_, _, P128Pow5T3, 3, 2>::from_inner(StateWord::new(
-                            var, value,
-                        )))
-                    };
-                    Ok([message_word(0)?, message_word(1)?])
-                },
-            )?;
-
-            let poseidon_hasher = PoseidonHash::init(
-                config.poseidon_chip(),
-                layouter.namespace(|| "Poseidon init"),
-                ConstantLength::<2>,
-            )?;
-
-            let poseidon_output = poseidon_hasher.hash(
-                layouter.namespace(|| "Poseidon hash (a, b)"),
-                poseidon_message,
-            )?;
-
-            let poseidon_output: CellValue<pallas::Base> = 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))
-            },
-        )?;
-
-        // Constrain sum to equal the public input
-        layouter.constrain_instance(scalar.cell(), config.primary, 0)?;
-
-        // At this point we've enforced all of our public inputs.
-        Ok(())
-    }
-}
-
-fn main() {
-    // The number of rows in our circuit cannot exceed 2^k
-    let k: u32 = 6;
-
-    let a = pallas::Base::from(13);
-    let b = pallas::Base::from(69);
-    let c = pallas::Base::from(42);
-
-    let message = [a, b];
-    let output = primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(message);
-
-    let circuit = HashCircuit {
-        a: Some(a),
-        b: Some(b),
-        c: Some(c),
-    };
-
-    let sum = output + c;
-
-    // Incorrect:
-    let public_inputs = vec![sum + pallas::Base::one()];
-    let prover = MockProver::run(k, &circuit, vec![public_inputs]).unwrap();
-    assert!(prover.verify().is_err());
-
-    // Correct:
-    let public_inputs = vec![sum];
-    let prover = MockProver::run(k, &circuit, vec![public_inputs.clone()]).unwrap();
-    assert_eq!(prover.verify(), Ok(()));
-
-    // Actual ZK proof
-    let start = Instant::now();
-    let vk = VerifyingKey::build(k, HashCircuit::default());
-    let pk = ProvingKey::build(k, HashCircuit::default());
-    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());
-}

+ 0 - 4
examples/halo2/src/lib.rs

@@ -1,4 +0,0 @@
-pub mod constants;
-pub mod crypto;
-pub mod proof;
-pub mod spec;

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác