ソースを参照

zk: Optimise mint circuit to allow k=8 rows.

parazyd 4 年 前
コミット
be8154223d
1 ファイル変更50 行追加20 行削除
  1. 50 20
      src/zk/circuit/mint_contract.rs

+ 50 - 20
src/zk/circuit/mint_contract.rs

@@ -100,10 +100,7 @@ impl Circuit<pallas::Base> for MintContract {
             meta.enable_equality(*advice);
         }
 
-        // 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.
-        let lagrange_coeffs = [
+        let ecc_lagrange_coeffs = [
             meta.fixed_column(),
             meta.fixed_column(),
             meta.fixed_column(),
@@ -113,25 +110,39 @@ impl Circuit<pallas::Base> for MintContract {
             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();
+
+        let poseidon_lagrange_coeffs = [
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+            meta.fixed_column(),
+        ];
+
+        let rc_a = poseidon_lagrange_coeffs[0..3].try_into().unwrap();
+        let rc_b = poseidon_lagrange_coeffs[3..6].try_into().unwrap();
 
         // Also use the first Lagrange coefficient column for loading global constants.
-        meta.enable_constant(lagrange_coeffs[0]);
+        meta.enable_constant(ecc_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);
+        let ecc_config = EccChip::<OrchardFixedBases>::configure(
+            meta,
+            advices,
+            ecc_lagrange_coeffs,
+            range_check,
+        );
 
         // Configuration for the Poseidon hash
         let poseidon_config = PoseidonChip::configure::<poseidon::P128Pow5T3>(
             meta,
-            advices[6..9].try_into().unwrap(),
-            advices[5],
+            advices[7..10].try_into().unwrap(),
+            advices[6],
             rc_a,
             rc_b,
         );
@@ -148,31 +159,31 @@ impl Circuit<pallas::Base> for MintContract {
 
         let pub_x = assign_free_advice(
             layouter.namespace(|| "load pubkey x"),
-            config.advices[0],
+            config.advices[6],
             self.pub_x,
         )?;
 
         let pub_y = assign_free_advice(
             layouter.namespace(|| "load pubkey y"),
-            config.advices[0],
+            config.advices[6],
             self.pub_y,
         )?;
 
         let value =
-            assign_free_advice(layouter.namespace(|| "load value"), config.advices[0], self.value)?;
+            assign_free_advice(layouter.namespace(|| "load value"), config.advices[6], self.value)?;
 
         let token =
-            assign_free_advice(layouter.namespace(|| "load token"), config.advices[0], self.token)?;
+            assign_free_advice(layouter.namespace(|| "load token"), config.advices[6], self.token)?;
 
         let serial = assign_free_advice(
             layouter.namespace(|| "load serial"),
-            config.advices[0],
+            config.advices[6],
             self.serial,
         )?;
 
         let coin_blind = assign_free_advice(
             layouter.namespace(|| "load coin_blind"),
-            config.advices[0],
+            config.advices[6],
             self.coin_blind,
         )?;
 
@@ -210,7 +221,7 @@ impl Circuit<pallas::Base> for MintContract {
         // This constant one is used for short multiplication
         let one = assign_free_advice(
             layouter.namespace(|| "load constant one"),
-            config.advices[0],
+            config.advices[6],
             Value::known(pallas::Base::one()),
         )?;
 
@@ -306,7 +317,9 @@ mod tests {
     use crate::{
         crypto::{
             keypair::PublicKey,
+            proof::{ProvingKey, VerifyingKey},
             util::{mod_r_p, pedersen_commitment_scalar},
+            Proof,
         },
         Result,
     };
@@ -321,6 +334,7 @@ mod tests {
     };
     use pasta_curves::arithmetic::CurveAffine;
     use rand::rngs::OsRng;
+    use std::time::Instant;
 
     #[test]
     fn mint_circuit_assert() -> Result<()> {
@@ -360,10 +374,26 @@ mod tests {
         let root = BitMapBackend::new("mint_circuit_layout.png", (3840, 2160)).into_drawing_area();
         root.fill(&WHITE).unwrap();
         let root = root.titled("Mint Circuit Layout", ("sans-serif", 60)).unwrap();
-        CircuitLayout::default().render(9, &circuit, &root).unwrap();
+        CircuitLayout::default().render(8, &circuit, &root).unwrap();
 
-        let prover = MockProver::run(9, &circuit, vec![public_inputs])?;
+        let prover = MockProver::run(8, &circuit, vec![public_inputs.clone()])?;
         prover.assert_satisfied();
+
+        let now = Instant::now();
+        let proving_key = ProvingKey::build(8, &circuit);
+        println!("ProvingKey built [{:?}]", now.elapsed());
+        let now = Instant::now();
+        let proof = Proof::create(&proving_key, &[circuit], &public_inputs, &mut OsRng)?;
+        println!("Proof created [{:?}]", now.elapsed());
+
+        let circuit = MintContract::default();
+        let now = Instant::now();
+        let verifying_key = VerifyingKey::build(8, &circuit);
+        println!("VerifyingKey built [{:?}]", now.elapsed());
+        let now = Instant::now();
+        proof.verify(&verifying_key, &public_inputs)?;
+        println!("Proof verified [{:?}]", now.elapsed());
+
         Ok(())
     }
 }