Quellcode durchsuchen

[crypsinous:zk/lead_circuit] move public input coin_nonce2 to the end

mohab metwally vor 4 Jahren
Ursprung
Commit
4ba9bbf284
6 geänderte Dateien mit 171 neuen und 120 gelöschten Zeilen
  1. 4 2
      example/lead.rs
  2. 9 3
      example/lessthan.rs
  3. 12 5
      src/blockchain/epoch.rs
  4. 2 3
      src/crypto/leadcoin.rs
  5. 120 107
      src/zk/circuit/lead_contract.rs
  6. 24 0
      src/zk/gadget/less_than.rs

+ 4 - 2
example/lead.rs

@@ -39,7 +39,7 @@ fn main() {
     //
     const LEN: usize = 10;
     let epoch_item = EpochItem {
-        value: 0,  //static stake value
+        value: 332233,  //static stake value
     };
     //
     let settings = Settings{
@@ -72,9 +72,11 @@ fn main() {
     let coin = coins[coin_idx];
     let contract = coin.create_contract();
 
+    /*
     let lead_pk = stakeholder.get_provkingkey();
     let lead_vk = stakeholder.get_verifyingkey();
 
+
     //
     //let proof = lead_proof::create_lead_proof(lead_pk.clone(), coin.clone());
 
@@ -90,7 +92,7 @@ fn main() {
     let bk_info = BlockInfo::new(st_hash, 1, 0, empty_txs, metadata, sm);
     let blks = [bk_info];
     stakeholder.blockchain.add(&blks);
-
+    */
     // calculate public inputs
     let public_inputs = coin.public_inputs();
     let prover = MockProver::run(k, &contract, vec![public_inputs]).unwrap();

+ 9 - 3
example/lessthan.rs

@@ -72,11 +72,13 @@ impl Circuit<pallas::Base> for LessThanCircuit {
             config.0.k_values_table,
         )?;
 
+
         less_than_chip.witness_less_than(
             layouter.namespace(|| "a < b"),
             self.a,
             self.b,
             0,
+            true,
         )?;
 
         Ok(())
@@ -86,7 +88,7 @@ impl Circuit<pallas::Base> for LessThanCircuit {
 fn main() {
     let k = 13;
     let valid_a_vals = vec![
-        pallas::Base::from(3),
+        pallas::Base::from(4),
         pallas::Base::zero(),
         pallas::Base::one()
     ];
@@ -120,6 +122,10 @@ fn main() {
         .into_drawing_area();
     CircuitLayout::default().render(k, &circuit, &root).unwrap();
 
+    let one = pallas::Base::one();
+    let zero = pallas::Base::zero();
+    let public_inputs = vec![one];
+
     for i in 0..valid_a_vals.len() {
         let a = valid_a_vals[i];
         let b = valid_b_vals[i];
@@ -128,7 +134,7 @@ fn main() {
 
         let circuit = LessThanCircuit { a: Value::known(a), b: Value::known(b) };
 
-        let prover = MockProver::run(k, &circuit, vec![]).unwrap();
+        let prover = MockProver::run(k, &circuit, public_inputs).unwrap();
         prover.assert_satisfied();
     }
 
@@ -141,7 +147,7 @@ fn main() {
 
         let circuit = LessThanCircuit { a: Value::known(a), b: Value::known(b) };
 
-        let prover = MockProver::run(k, &circuit, vec![]).unwrap();
+        let prover = MockProver::run(k, &circuit, public_inputs).unwrap();
         assert!(prover.verify().is_err())
     }
 

+ 12 - 5
src/blockchain/epoch.rs

@@ -197,7 +197,12 @@ impl Epoch {
             let c_sn : pallas::Base = poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init().hash(sn_msg);
 
 
-            let coin_commit_msg = c_pk*c_v*c_seed;
+            let coin_commit_msg_input = [
+                c_pk,
+                c_v,
+                c_seed
+            ];
+            let coin_commit_msg : pallas::Base = poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<3>, 3, 2>::init().hash(coin_commit_msg_input);
             let c_cm: pallas::Point = pedersen_commitment_base(coin_commit_msg, c_cm1_blind);
             let c_cm_coordinates = c_cm.to_affine().coordinates().unwrap();
             let c_cm_base: pallas::Base = c_cm_coordinates.x() * c_cm_coordinates.y();
@@ -213,10 +218,12 @@ impl Epoch {
             ];
             let c_seed2 : pallas::Base = poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init().hash(coin_nonce2_msg);
 
-            let c_seed2_pt_x = c_seed2.clone();
-            let c_seed2_pt_y = c_seed2.clone();
-
-            let coin2_commit_msg = c_pk*c_seed2_pt_x*c_seed2_pt_y*c_v;
+            let coin2_commit_msg_input = [
+                c_pk,
+                c_v,
+                c_seed,
+            ];
+            let coin2_commit_msg : pallas::Base = poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<3>, 3, 2>::init().hash(coin2_commit_msg_input);
             let c_cm2 = pedersen_commitment_base(coin2_commit_msg, c_cm2_blind);
 
             let c_root_sk = root_sks[i];

+ 2 - 3
src/crypto/leadcoin.rs

@@ -74,15 +74,14 @@ impl LeadCoin {
             current
         };
         let public_inputs: Vec<pallas::Base> = vec![
-            po_nonce,
             po_pk,
             po_sn,
             *po_cm.x(),
             *po_cm.y(),
             *po_cm2.x(),
             *po_cm2.y(),
-            cm_root.0,
-            po_cmp,
+            po_nonce,
+            //cm_root.0,
         ];
         public_inputs
     }

+ 120 - 107
src/zk/circuit/lead_contract.rs

@@ -1,7 +1,7 @@
 use halo2_gadgets::{
     ecc::{
         chip::{EccChip, EccConfig},
-        FixedPoint, FixedPointShort, ScalarFixed, ScalarFixedShort,
+        FixedPoint, FixedPointBaseField, FixedPointShort, ScalarFixed, ScalarFixedShort,
     },
     poseidon::{primitives as poseidon, Hash as PoseidonHash, Pow5Chip as PoseidonChip, Pow5Config as PoseidonConfig},
     sinsemilla::{
@@ -22,7 +22,7 @@ use crate::crypto::{
     constants::{
         sinsemilla::{OrchardCommitDomains, OrchardHashDomains},
         util::gen_const_array,
-        OrchardFixedBases, OrchardFixedBasesFull, ValueCommitV, MERKLE_DEPTH_ORCHARD,
+        OrchardFixedBases, OrchardFixedBasesFull, ValueCommitV, MERKLE_DEPTH_ORCHARD, NullifierK,
     },
     merkle_node::MerkleNode,
 };
@@ -97,15 +97,15 @@ impl LeadConfig {
     }
 }
 
-const LEAD_COIN_NONCE2_OFFSET: usize = 0;
-const LEAD_COIN_PK_OFFSET: usize = 1;
-const LEAD_COIN_SERIAL_NUMBER_OFFSET: usize = 2;
-const LEAD_COIN_COMMIT_X_OFFSET: usize = 3;
-const LEAD_COIN_COMMIT_Y_OFFSET: usize = 4;
-const LEAD_COIN_COMMIT2_X_OFFSET: usize = 5;
-const LEAD_COIN_COMMIT2_Y_OFFSET: usize = 6;
+
+const LEAD_COIN_PK_OFFSET: usize = 0;
+const LEAD_COIN_SERIAL_NUMBER_OFFSET: usize = 1;
+const LEAD_COIN_COMMIT_X_OFFSET: usize = 2;
+const LEAD_COIN_COMMIT_Y_OFFSET: usize = 3;
+const LEAD_COIN_COMMIT2_X_OFFSET: usize = 4;
+const LEAD_COIN_COMMIT2_Y_OFFSET: usize = 5;
+const LEAD_COIN_NONCE2_OFFSET: usize = 6;
 const LEAD_COIN_COMMIT_PATH_OFFSET: usize = 7;
-const LEAD_THRESHOLD_OFFSET: usize = 8;
 
 pub fn concat_u8(lhs: &[u8], rhs: &[u8]) -> Vec<u8> {
     [lhs, rhs].concat()
@@ -277,22 +277,27 @@ impl Circuit<pallas::Base> for LeadContract {
         config: Self::Config,
         mut layouter: impl Layouter<pallas::Base>,
     ) -> Result<(), Error> {
-        SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?;
-        let ecc_chip = config.ecc_chip();
-        let ar_chip = config.arith_chip();
-        let _ps_chip = config.poseidon_chip();
+        let less_than_chip = config.lessthan_chip();
 
         NativeRangeCheckChip::<WINDOW_SIZE, NUM_OF_BITS, NUM_OF_WINDOWS>::load_k_table(
             &mut layouter,
             config.lessthan_config.k_values_table,
         )?;
 
-        let less_than_chip = config.lessthan_chip();
+        SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?;
+        let ecc_chip = config.ecc_chip();
+        let ar_chip = config.arith_chip();
+        let _ps_chip = config.poseidon_chip();
+
+
+
 
         // ===============
         // load witnesses
         // ===============
 
+
+
         let one = self.load_private(
             layouter.namespace(|| "one"),
             config.advices[0],
@@ -329,6 +334,19 @@ impl Circuit<pallas::Base> for LeadContract {
             self.coin_pk,
         )?;
 
+        //used for fine tuning the leader election frequency
+        let scalar = self.load_private(
+            layouter.namespace(|| "load scalar "),
+            config.advices[0],
+            Value::known(pallas::Base::from(1024)),
+        )?;
+        //leadership coefficient
+
+        let c = self.load_private(
+            layouter.namespace(|| ""),
+            config.advices[0],
+            Value::known(pallas::Base::one()), // note! this parameter to be tuned.
+        )?;
 
         let _slot = self.load_private(layouter.namespace(|| ""), config.advices[0], self.slot)?;
 
@@ -353,11 +371,6 @@ impl Circuit<pallas::Base> for LeadContract {
             let poseidon_output: AssignedCell<Fp, Fp> = poseidon_output;
             poseidon_output
         };
-        layouter.constrain_instance(
-            coin2_nonce.cell(),
-            config.primary,
-            LEAD_COIN_NONCE2_OFFSET,
-        )?;
 
         // ================
         // coin public key pk=PRF_{root_sk}(tau)
@@ -415,39 +428,43 @@ impl Circuit<pallas::Base> for LeadContract {
             LEAD_COIN_SERIAL_NUMBER_OFFSET,
         )?;
 
-        // ================================================
-        // coin commiment H=COMMIT(pk||V||nonce||r)
-        // ================================================
-        let coin_val = {
-            let coin_val_mul = ar_chip.mul(layouter.namespace(|| ""), &coin_pk, &coin_value)?;
-            ar_chip.mul(layouter.namespace(|| ""), &coin_nonce, &coin_val_mul)?
-        };
-        let (com, _) = {
-            let coin_commit_v = ValueCommitV;
-            let coin_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), coin_commit_v);
 
-            let coin_hash_pt = ScalarFixedShort::new(
-                ecc_chip.clone(),
-                layouter.namespace(|| "coin_val*1"),
-                (coin_value.clone(), one.clone()),
-            )?;
-            coin_commit_v.mul(layouter.namespace(|| "coin commit v"), coin_hash_pt)?
+        let com = {
+            let nullifier_msg : AssignedCell<Fp,Fp> = {
+                let poseidon_message = [
+                    coin_pk.clone(),
+                    coin_value.clone(),
+                    coin_nonce.clone(),
+                ];
+                let poseidon_hasher = PoseidonHash::<_, _, poseidon::P128Pow5T3, poseidon::ConstantLength<3>, 3, 2>::init(
+                    config.poseidon_chip(),
+                    layouter.namespace(|| "Poseidon init"),
+                )?;
+
+                let poseidon_output =
+                    poseidon_hasher.hash(layouter.namespace(|| "Poseidon hash"), poseidon_message)?;
+                let poseidon_output: AssignedCell<Fp, Fp> = poseidon_output;
+                poseidon_output
+            };
+            // ================================================
+            // coin commiment H=COMMIT(pk||V||nonce||r)
+            // ================================================
+            let coin_commit_v = FixedPointBaseField::from_inner(ecc_chip.clone(), NullifierK);
+            coin_commit_v.mul(layouter.namespace(|| "coin commit v"), nullifier_msg)?
         };
 
         // r*G_2
         let (blind, _) = {
-            let coin_commit_r = OrchardFixedBasesFull::ValueCommitR;
-            let coin_commit_r = FixedPoint::from_inner(ecc_chip.clone(), coin_commit_r);
             let rcv = ScalarFixed::new(
                 ecc_chip.clone(),
                 layouter.namespace(|| "coin1 blind scalar"),
                 self.coin1_blind,
             )?;
+            let coin_commit_r = FixedPoint::from_inner(ecc_chip.clone(), OrchardFixedBasesFull::ValueCommitR);
             coin_commit_r.mul(layouter.namespace(|| "coin serial number commit R"), rcv)?
         };
 
         let coin_commit = com.add(layouter.namespace(|| "nonce commit"), &blind)?;
-
         let coin_commit_x: AssignedCell<Fp, Fp> = coin_commit.inner().x();
         let coin_commit_y: AssignedCell<Fp, Fp> = coin_commit.inner().y();
 
@@ -466,40 +483,43 @@ impl Circuit<pallas::Base> for LeadContract {
         // ================================================
         // coin2 commiment H=COMMIT(pk||V||nonce2||r2)
         // ================================================
-        let coin2_hash_cm = ar_chip.mul(
-            layouter.namespace(|| ""),
-            &coin_pk_commit,
-            &coin2_nonce
-        )?;
-        let coin2_hash = ar_chip.mul(layouter.namespace(|| ""), &coin_value.clone(), &coin2_hash_cm)?;
 
-        let (com, _) = {
-            let coin_commit_v = ValueCommitV;
-            let coin_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), coin_commit_v);
-            let coin2_hash_pt = ScalarFixedShort::new(
-                ecc_chip.clone(),
-                layouter.namespace(|| "coin2_hash*1"),
-                (coin2_hash, one.clone()),
-            )?;
-            coin_commit_v.mul(layouter.namespace(|| "coin commit v"), coin2_hash_pt)?
+        let com2 = {
+            let nullifier2_msg : AssignedCell<Fp,Fp> = {
+                let poseidon_message = [
+                    coin_pk.clone(),
+                    coin_value.clone(),
+                    coin_nonce.clone(),
+                ];
+                let poseidon_hasher = PoseidonHash::<_, _, poseidon::P128Pow5T3, poseidon::ConstantLength<3>, 3, 2>::init(
+                    config.poseidon_chip(),
+                    layouter.namespace(|| "Poseidon init"),
+                )?;
+
+                let poseidon_output =
+                    poseidon_hasher.hash(layouter.namespace(|| "Poseidon hash"), poseidon_message)?;
+                let poseidon_output: AssignedCell<Fp, Fp> = poseidon_output;
+                poseidon_output
+        };
+            let coin_commit_v = FixedPointBaseField::from_inner(ecc_chip.clone(), NullifierK);
+            coin_commit_v.mul(layouter.namespace(|| "coin commit v"), nullifier2_msg)?
         };
         // r*G_2
         let (blind, _) = {
-            let coin_commit_r = OrchardFixedBasesFull::ValueCommitR;
-            let coin_commit_r = FixedPoint::from_inner(ecc_chip.clone(), coin_commit_r);
             let coin2_blind = ScalarFixed::new(
                 ecc_chip.clone(),
                 layouter.namespace(|| "coin2 blind scalar"),
                 self.coin2_blind,
             )?;
-            coin_commit_r
-                .mul(layouter.namespace(|| "coin serial number commit R"), coin2_blind)?
+            let coin_commit_r = FixedPoint::from_inner(ecc_chip.clone(), OrchardFixedBasesFull::ValueCommitR);
+            coin_commit_r.mul(layouter.namespace(|| "coin serial number commit R"), coin2_blind)?
         };
-        let coin2_commit = com.add(layouter.namespace(|| "nonce commit"), &blind)?;
+        let coin2_commit = com2.add(layouter.namespace(|| "nonce commit"), &blind)?;
         let coin2_commit_x: AssignedCell<Fp, Fp> = coin2_commit.inner().x();
         let coin2_commit_y: AssignedCell<Fp, Fp> = coin2_commit.inner().y();
 
-        layouter.constrain_instance(
+
+      layouter.constrain_instance(
             coin2_commit_x.cell(),
             config.primary,
             LEAD_COIN_COMMIT2_X_OFFSET,
@@ -509,9 +529,14 @@ impl Circuit<pallas::Base> for LeadContract {
             coin2_commit_y.cell(),
             config.primary,
             LEAD_COIN_COMMIT2_Y_OFFSET,
-        )?;
+    )?;
 
 
+        layouter.constrain_instance(
+        coin2_nonce.clone().cell(),
+        config.primary,
+        LEAD_COIN_NONCE2_OFFSET,
+    )?;
 
         // ===========================
         // path is valid path to cm1
@@ -540,50 +565,55 @@ impl Circuit<pallas::Base> for LeadContract {
         let computed_final_root = merkle_inputs
             .calculate_root(layouter.namespace(|| "calculate root"), coin_commit_prod)?;
 
+        /*
         layouter.constrain_instance(
             computed_final_root.cell(),
             config.primary,
             LEAD_COIN_COMMIT_PATH_OFFSET,
         )?;
-
-
+        */
         //================================
         // y as COMIT(root_sk*nonce, mau_y)
         //================================
-        let y_commit_exp = ar_chip.mul(
-        layouter.namespace(|| ""),
-            &_root_sk.clone(),
-            &coin_nonce,
-        )?;
-
-        let (com, _) = {
-            let y_commit_v = ValueCommitV;
-            let y_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), y_commit_v);
-            let y_commit_exp = ScalarFixedShort::new(
-                ecc_chip.clone(),
-                layouter.namespace(|| "y_commit_exp*1"),
-                (y_commit_exp, one.clone()),
+        let y_commit_msg : AssignedCell<Fp,Fp> = {
+            let poseidon_message = [
+                _root_sk.clone(),
+                coin_nonce.clone(),
+            ];
+            let poseidon_hasher = PoseidonHash::<_, _, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init(
+                config.poseidon_chip(),
+                layouter.namespace(|| "Poseidon init"),
             )?;
-            y_commit_v.mul(layouter.namespace(|| "coin commit v"), y_commit_exp)?
+
+            let poseidon_output =
+                poseidon_hasher.hash(layouter.namespace(|| "Poseidon hash"), poseidon_message)?;
+            let poseidon_output: AssignedCell<Fp, Fp> = poseidon_output;
+            poseidon_output
+        };
+
+        let com = {
+            let y_commit_v = FixedPointBaseField::from_inner(ecc_chip.clone(),  NullifierK);
+            y_commit_v.mul(layouter.namespace(|| "coin commit v"), y_commit_msg)?
         };
 
         // r*G_2
         let (blind, _) = {
-            let y_commit_r = OrchardFixedBasesFull::ValueCommitR;
-            let y_commit_r = FixedPoint::from_inner(ecc_chip.clone(), y_commit_r);
             let mau_y = ScalarFixed::new(
                 ecc_chip.clone(),
                 layouter.namespace(|| "mau_y scalar"),
                 self.mau_y,
             )?;
+            let y_commit_r = FixedPoint::from_inner(ecc_chip.clone(), OrchardFixedBasesFull::ValueCommitR);
             y_commit_r.mul(layouter.namespace(|| "coin serial number commit R"), mau_y)?
         };
         let y_commit = com.add(layouter.namespace(|| "nonce commit"), &blind)?;
         let y_commit_base = y_commit.inner().x();
 
+        //TODO public constraint y
         // ============================
         // constraint rho as COMIT(root_sk*nonce, mau_rho)
         // ============================
+        /*
         let (com, _) = {
             let rho_commit_v = ValueCommitV;
             let rho_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), rho_commit_v);
@@ -594,6 +624,7 @@ impl Circuit<pallas::Base> for LeadContract {
             )?;
             rho_commit_v.mul(layouter.namespace(|| "coin commit v"), rcv)?
         };
+
         // r*G_2
         let (blind, _) = {
             let rho_commit_r = OrchardFixedBasesFull::ValueCommitR;
@@ -603,39 +634,21 @@ impl Circuit<pallas::Base> for LeadContract {
             rho_commit_r.mul(layouter.namespace(|| "coin serial number commit R"), mau_rho)?
         };
         let _rho_commit = com.add(layouter.namespace(|| "nonce commit"), &blind)?;
-
-        //used for fine tuning the leader election frequency
-        let scalar = self.load_private(
-            layouter.namespace(|| "load scalar "),
-            config.advices[0],
-            Value::known(pallas::Base::from(1024)),
-        )?;
-        //leadership coefficient
-
-        let c = self.load_private(
-            layouter.namespace(|| ""),
-            config.advices[0],
-            Value::known(pallas::Base::one()), // note! this parameter to be tuned.
-        )?;
+        */
 
 
         let ord = ar_chip.mul(layouter.namespace(|| ""), &scalar, &c)?;
         let target = ar_chip.mul(layouter.namespace(|| "calculate target"), &ord, &coin_value.clone())?;
 
-
-        let is_lt = layouter.assign_region(|| "y<t",
-                               |mut region| {
-                                   less_than_chip.less_than(
-                                       region,
-                                       //y_commit_base.clone(),
-                                       //target.clone(),
-                                       zero.clone(),
-                                       one.clone(),
-                                       0,
-                                   )
-                               })?;
-
-        layouter.constrain_instance(is_lt.cell(), config.primary, LEAD_THRESHOLD_OFFSET)?;
+        let y : Value<pallas::Base> = y_commit_base.value().cloned();
+        let T : Value<pallas::Base> = target.value().cloned();
+        less_than_chip.witness_less_than(
+            layouter.namespace(|| "y < T"),
+            y,
+            T,
+            0,
+            true
+        )?;
 
         Ok(())
     }

+ 24 - 0
src/zk/gadget/less_than.rs

@@ -130,6 +130,30 @@ impl<const WINDOW_SIZE: usize, const NUM_OF_BITS: usize, const NUM_OF_WINDOWS: u
         Ok(())
     }
 
+    pub fn witness_less_than2(
+        &self,
+        mut layouter: impl Layouter<pallas::Base>,
+        a: Value<pallas::Base>,
+        b: Value<pallas::Base>,
+        offset: usize,
+        strict: bool,
+    ) -> Result<AssignedCell<pallas::Base, pallas::Base>, Error> {
+        let (a, _, a_offset) = layouter.assign_region(
+            || "a less than b",
+            |mut region: Region<'_, pallas::Base>| {
+                let a = region.assign_advice(|| "a", self.config.a, offset, || a)?;
+                let b = region.assign_advice(|| "b", self.config.b, offset, || b)?;
+                let a_offset = self.less_than(region, a.clone(), b.clone(), offset)?;
+                Ok((a, b, a_offset))
+            },
+        )?;
+
+        self.less_than_range_check(layouter, a, a_offset.clone(), strict)?;
+
+        Ok(a_offset)
+    }
+
+
     pub fn copy_less_than(
         &self,
         mut layouter: impl Layouter<pallas::Base>,