Просмотр исходного кода

circuit: Clean up mint and spend contracts.

parazyd 4 лет назад
Родитель
Сommit
2d59247f6f
2 измененных файлов с 63 добавлено и 212 удалено
  1. 24 100
      src/circuit/mint_contract.rs
  2. 39 112
      src/circuit/spend_contract.rs

+ 24 - 100
src/circuit/mint_contract.rs

@@ -1,29 +1,24 @@
-use pasta_curves::pallas;
-
 use halo2::{
 use halo2::{
     circuit::{Layouter, SimpleFloorPlanner},
     circuit::{Layouter, SimpleFloorPlanner},
     plonk,
     plonk,
-    plonk::{Advice, Circuit, Column, ConstraintSystem, Instance as InstanceColumn, Selector},
-    poly::Rotation,
+    plonk::{Advice, Circuit, Column, ConstraintSystem, Instance as InstanceColumn},
 };
 };
 use halo2_gadgets::{
 use halo2_gadgets::{
     ecc::{
     ecc::{
         chip::{EccChip, EccConfig},
         chip::{EccChip, EccConfig},
         FixedPoint,
         FixedPoint,
     },
     },
-    poseidon::{
-        Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig,
-        StateWord, Word,
-    },
+    poseidon::{Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig},
     primitives::poseidon::{ConstantLength, P128Pow5T3},
     primitives::poseidon::{ConstantLength, P128Pow5T3},
     sinsemilla::{
     sinsemilla::{
         chip::{SinsemillaChip, SinsemillaConfig},
         chip::{SinsemillaChip, SinsemillaConfig},
         merkle::chip::{MerkleChip, MerkleConfig},
         merkle::chip::{MerkleChip, MerkleConfig},
     },
     },
     utilities::{
     utilities::{
-        copy, lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
+        lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
     },
     },
 };
 };
+use pasta_curves::pallas;
 
 
 use crate::crypto::constants::{
 use crate::crypto::constants::{
     sinsemilla::{OrchardCommitDomains, OrchardHashDomains},
     sinsemilla::{OrchardCommitDomains, OrchardHashDomains},
@@ -33,7 +28,6 @@ use crate::crypto::constants::{
 #[derive(Clone, Debug)]
 #[derive(Clone, Debug)]
 pub struct MintConfig {
 pub struct MintConfig {
     primary: Column<InstanceColumn>,
     primary: Column<InstanceColumn>,
-    q_add: Selector,
     advices: [Column<Advice>; 10],
     advices: [Column<Advice>; 10],
     ecc_config: EccConfig,
     ecc_config: EccConfig,
     merkle_config_1: MerkleConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
     merkle_config_1: MerkleConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
@@ -101,29 +95,6 @@ impl Circuit<pallas::Base> for MintContract {
             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
         // Fixed columns for the Sinsemilla generator lookup table
         let table_idx = meta.lookup_table_column();
         let table_idx = meta.lookup_table_column();
         let lookup = (table_idx, meta.lookup_table_column(), meta.lookup_table_column());
         let lookup = (table_idx, meta.lookup_table_column(), meta.lookup_table_column());
@@ -217,7 +188,6 @@ impl Circuit<pallas::Base> for MintContract {
 
 
         MintConfig {
         MintConfig {
             primary,
             primary,
-            q_add,
             advices,
             advices,
             ecc_config,
             ecc_config,
             merkle_config_1,
             merkle_config_1,
@@ -271,71 +241,21 @@ impl Circuit<pallas::Base> for MintContract {
         // =========
         // =========
         // Coin hash
         // 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(plonk::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 = {
+            let poseidon_message = [pub_x, pub_y, value, asset, serial, coin_blind];
 
 
-        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(plonk::Error::SynthesisError),
-                )?;
-                Ok(CellValue::new(cell, scalar_val))
-            },
-        )?;
+            let poseidon_hasher = PoseidonHash::<_, _, P128Pow5T3, _, 3, 2>::init(
+                config.poseidon_chip(),
+                layouter.namespace(|| "Poseidon init"),
+                ConstantLength::<6>,
+            )?;
+
+            let poseidon_output =
+                poseidon_hasher.hash(layouter.namespace(|| "Poseidon hash"), poseidon_message)?;
+
+            let poseidon_output: CellValue<pallas::Base> = poseidon_output.inner().into();
+            poseidon_output
+        };
 
 
         // Constrain the coin C
         // Constrain the coin C
         layouter.constrain_instance(coin.cell(), config.primary, MINT_COIN_OFFSET)?;
         layouter.constrain_instance(coin.cell(), config.primary, MINT_COIN_OFFSET)?;
@@ -366,13 +286,15 @@ impl Circuit<pallas::Base> for MintContract {
             value_commit_r.mul(layouter.namespace(|| "[value_blind] ValueCommitR"), rcv)?
             value_commit_r.mul(layouter.namespace(|| "[value_blind] ValueCommitR"), rcv)?
         };
         };
 
 
-        // Constrain the value commitment coordinates
         let value_commit = commitment.add(layouter.namespace(|| "valuecommit"), &blind)?;
         let value_commit = commitment.add(layouter.namespace(|| "valuecommit"), &blind)?;
+
+        // Constrain the value commitment coordinates
         layouter.constrain_instance(
         layouter.constrain_instance(
             value_commit.inner().x().cell(),
             value_commit.inner().x().cell(),
             config.primary,
             config.primary,
             MINT_VALCOMX_OFFSET,
             MINT_VALCOMX_OFFSET,
         )?;
         )?;
+
         layouter.constrain_instance(
         layouter.constrain_instance(
             value_commit.inner().y().cell(),
             value_commit.inner().y().cell(),
             config.primary,
             config.primary,
@@ -397,13 +319,15 @@ impl Circuit<pallas::Base> for MintContract {
             asset_commit_r.mul(layouter.namespace(|| "[asset_blind] ValueCommitR"), rca)?
             asset_commit_r.mul(layouter.namespace(|| "[asset_blind] ValueCommitR"), rca)?
         };
         };
 
 
-        // Constrain the asset commitment coordinates
         let asset_commit = commitment.add(layouter.namespace(|| "assetcommit"), &blind)?;
         let asset_commit = commitment.add(layouter.namespace(|| "assetcommit"), &blind)?;
+
+        // Constrain the asset commitment coordinates
         layouter.constrain_instance(
         layouter.constrain_instance(
             asset_commit.inner().x().cell(),
             asset_commit.inner().x().cell(),
             config.primary,
             config.primary,
             MINT_ASSCOMX_OFFSET,
             MINT_ASSCOMX_OFFSET,
         )?;
         )?;
+
         layouter.constrain_instance(
         layouter.constrain_instance(
             asset_commit.inner().y().cell(),
             asset_commit.inner().y().cell(),
             config.primary,
             config.primary,

+ 39 - 112
src/circuit/spend_contract.rs

@@ -1,5 +1,3 @@
-use pasta_curves as pasta;
-
 use halo2::{
 use halo2::{
     circuit::{Layouter, SimpleFloorPlanner},
     circuit::{Layouter, SimpleFloorPlanner},
     plonk::{
     plonk::{
@@ -12,10 +10,7 @@ use halo2_gadgets::{
         chip::{EccChip, EccConfig},
         chip::{EccChip, EccConfig},
         FixedPoint,
         FixedPoint,
     },
     },
-    poseidon::{
-        Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig,
-        StateWord, Word,
-    },
+    poseidon::{Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig},
     primitives::poseidon::{ConstantLength, P128Pow5T3},
     primitives::poseidon::{ConstantLength, P128Pow5T3},
     sinsemilla::{
     sinsemilla::{
         chip::{SinsemillaChip, SinsemillaConfig},
         chip::{SinsemillaChip, SinsemillaConfig},
@@ -25,9 +20,10 @@ use halo2_gadgets::{
         },
         },
     },
     },
     utilities::{
     utilities::{
-        copy, lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
+        lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
     },
     },
 };
 };
+use pasta_curves::pallas;
 
 
 use crate::crypto::constants::{
 use crate::crypto::constants::{
     sinsemilla::{OrchardCommitDomains, OrchardHashDomains},
     sinsemilla::{OrchardCommitDomains, OrchardHashDomains},
@@ -46,7 +42,7 @@ pub struct SpendConfig {
         SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
         SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
     sinsemilla_config_2:
     sinsemilla_config_2:
         SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
         SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
-    poseidon_config: PoseidonConfig<pasta::Fp>,
+    poseidon_config: PoseidonConfig<pallas::Base>,
 }
 }
 
 
 impl SpendConfig {
 impl SpendConfig {
@@ -80,7 +76,7 @@ impl SpendConfig {
         MerkleChip::construct(self.merkle_config_2.clone())
         MerkleChip::construct(self.merkle_config_2.clone())
     }
     }
 
 
-    fn poseidon_chip(&self) -> PoseidonChip<pasta::Fp> {
+    fn poseidon_chip(&self) -> PoseidonChip<pallas::Base> {
         PoseidonChip::construct(self.poseidon_config.clone())
         PoseidonChip::construct(self.poseidon_config.clone())
     }
     }
 }
 }
@@ -97,23 +93,23 @@ const BURN_SIGKEYY_OFFSET: usize = 7;
 
 
 #[derive(Default, Debug)]
 #[derive(Default, Debug)]
 pub struct SpendContract {
 pub struct SpendContract {
-    pub secret_key: Option<pasta::Fp>,
-    pub serial: Option<pasta::Fp>,
-    pub value: Option<pasta::Fp>,
-    pub asset: Option<pasta::Fp>,
-    pub coin_blind: Option<pasta::Fp>,
-    pub value_blind: Option<pasta::Fq>,
-    pub asset_blind: Option<pasta::Fq>,
+    pub secret_key: Option<pallas::Base>,
+    pub serial: Option<pallas::Base>,
+    pub value: Option<pallas::Base>,
+    pub asset: Option<pallas::Base>,
+    pub coin_blind: Option<pallas::Base>,
+    pub value_blind: Option<pallas::Scalar>,
+    pub asset_blind: Option<pallas::Scalar>,
     pub leaf_pos: Option<u32>,
     pub leaf_pos: Option<u32>,
-    pub merkle_path: Option<[pasta::Fp; 32]>,
-    pub sig_secret: Option<pasta::Fq>,
+    pub merkle_path: Option<[pallas::Base; 32]>,
+    pub sig_secret: Option<pallas::Scalar>,
 }
 }
 
 
-impl UtilitiesInstructions<pasta::Fp> for SpendContract {
-    type Var = CellValue<pasta::Fp>;
+impl UtilitiesInstructions<pallas::Base> for SpendContract {
+    type Var = CellValue<pallas::Base>;
 }
 }
 
 
-impl Circuit<pasta::Fp> for SpendContract {
+impl Circuit<pallas::Base> for SpendContract {
     type Config = SpendConfig;
     type Config = SpendConfig;
     type FloorPlanner = SimpleFloorPlanner;
     type FloorPlanner = SimpleFloorPlanner;
 
 
@@ -121,7 +117,7 @@ impl Circuit<pasta::Fp> for SpendContract {
         Self::default()
         Self::default()
     }
     }
 
 
-    fn configure(meta: &mut ConstraintSystem<pasta::Fp>) -> Self::Config {
+    fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
         // Advice columns used in the circuit
         // Advice columns used in the circuit
         let advices = [
         let advices = [
             meta.advice_column(),
             meta.advice_column(),
@@ -255,7 +251,7 @@ impl Circuit<pasta::Fp> for SpendContract {
     fn synthesize(
     fn synthesize(
         &self,
         &self,
         config: Self::Config,
         config: Self::Config,
-        mut layouter: impl Layouter<pasta::Fp>,
+        mut layouter: impl Layouter<pallas::Base>,
     ) -> Result<(), Error> {
     ) -> Result<(), Error> {
         // Load the Sinsemilla generator lookup table used by the whole circuit.
         // Load the Sinsemilla generator lookup table used by the whole circuit.
         SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?;
         SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?;
@@ -282,38 +278,19 @@ impl Circuit<pasta::Fp> for SpendContract {
             self.serial,
             self.serial,
         )?;
         )?;
 
 
-        let message = [secret_key, serial];
         let hash = {
         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_message = [secret_key, serial];
 
 
-            let poseidon_hasher = PoseidonHash::init(
+            let poseidon_hasher = PoseidonHash::<_, _, P128Pow5T3, _, 3, 2>::init(
                 config.poseidon_chip(),
                 config.poseidon_chip(),
                 layouter.namespace(|| "Poseidon init"),
                 layouter.namespace(|| "Poseidon init"),
                 ConstantLength::<2>,
                 ConstantLength::<2>,
             )?;
             )?;
 
 
-            let poseidon_output = poseidon_hasher.hash(
-                layouter.namespace(|| "Poseidon hash (secretkey, serial)"),
-                poseidon_message,
-            )?;
+            let poseidon_output =
+                poseidon_hasher.hash(layouter.namespace(|| "Poseidon hash"), poseidon_message)?;
 
 
-            let poseidon_output: CellValue<pasta::Fp> = poseidon_output.inner().into();
+            let poseidon_output: CellValue<pallas::Base> = poseidon_output.inner().into();
             poseidon_output
             poseidon_output
         };
         };
 
 
@@ -348,71 +325,21 @@ impl Circuit<pasta::Fp> for SpendContract {
         // =========
         // =========
         // Coin hash
         // 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<pasta::Fp> = poseidon_output.inner().into();
-                poseidon_output
-            };
-
-            hashes.push(hash);
-        }
+        let coin = {
+            let poseidon_message = [pub_x, pub_y, value, asset, serial, coin_blind];
 
 
-        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))
-            },
-        )?;
+            let poseidon_hasher = PoseidonHash::<_, _, P128Pow5T3, _, 3, 2>::init(
+                config.poseidon_chip(),
+                layouter.namespace(|| "Poseidon init"),
+                ConstantLength::<6>,
+            )?;
+
+            let poseidon_output =
+                poseidon_hasher.hash(layouter.namespace(|| "Poseidon hash"), poseidon_message)?;
+
+            let poseidon_output: CellValue<pallas::Base> = poseidon_output.inner().into();
+            poseidon_output
+        };
 
 
         // ===========
         // ===========
         // Merkle root
         // Merkle root
@@ -443,7 +370,7 @@ impl Circuit<pasta::Fp> for SpendContract {
         let one = self.load_private(
         let one = self.load_private(
             layouter.namespace(|| "load constant one"),
             layouter.namespace(|| "load constant one"),
             config.advices[0],
             config.advices[0],
-            Some(pasta::Fp::one()),
+            Some(pallas::Base::one()),
         )?;
         )?;
 
 
         let value =
         let value =