Răsfoiți Sursa

[zk/lead] replaced failing hash with mul

mohab 4 ani în urmă
părinte
comite
ead5e339e7
2 a modificat fișierele cu 123 adăugiri și 118 ștergeri
  1. 48 15
      example/lead.rs
  2. 75 103
      src/zk/circuit/lead_contract.rs

+ 48 - 15
example/lead.rs

@@ -36,7 +36,6 @@ pub struct Coin {
     value: Option<pallas::Base>, //stake
     cm: Option<pallas::Point>,
     cm2: Option<pallas::Point>,
-    cm_blind: Option<pallas::Base>,
     sl: Option<pallas::Base>, //slot id
     tau: Option<pallas::Base>,
     nonce: Option<pallas::Base>,
@@ -44,6 +43,8 @@ pub struct Coin {
     sn: Option<pallas::Point>, // coin's serial number
     //sk : Option<SecretKey>,
     pk: Option<pallas::Point>,
+    pk_x: Option<pallas::Base>,
+    pk_y: Option<pallas::Base>,
     root_cm: Option<pallas::Scalar>,
     root_sk: Option<pallas::Scalar>,
     path: Option<[MerkleNode; MERKLE_DEPTH_ORCHARD]>,
@@ -107,42 +108,63 @@ fn main() {
         let c_seed = pallas::Base::from(seeds[i]);
         let c_sn = pedersen_commitment_scalar(mod_r_p(c_seed), mod_r_p(c_root_sk.inner()));
         let c_pk_pt = c_pk.to_affine().coordinates().unwrap();
-        let c_cm_message = [*c_pk_pt.x(), *c_pk_pt.y(), c_v.clone(), c_seed.clone()];
-        let c_cm_v =
-            poseidon::Hash::<_, P128Pow5T3, ConstantLength<4>, 3, 2>::init().hash(c_cm_message);
-        let c_cm1_blind = pallas::Base::from(0); //tmp val
-        let c_cm2_blind = pallas::Base::from(0); //tmp val
+        let c_pk_pt_x : pallas::Base = *c_pk_pt.x();
+        let c_pk_pt_y : pallas::Base = *c_pk_pt.y();
+        /*
+        let c_cm_message = [
+            c_pk_pt_x,clone(),
+            c_pk_pt_y.clone(),
+            c_v.clone(),
+            c_seed.clone()
+        ];
+        let c_cm_v poseidon::Hash::<_, P128Pow5T3, ConstantLength<2>, 3, 2>::init().hash(c_cm_message);
+         */
+        let c_cm_v = c_v.clone() * c_seed.clone() * c_pk_pt_x * c_pk_pt_y;
+        let c_cm1_blind = pallas::Base::from(1); //tmp val
+        let c_cm2_blind = pallas::Base::from(1); //tmp val
         let c_cm: pallas::Point = pedersen_commitment_scalar(mod_r_p(c_cm_v), mod_r_p(c_cm1_blind));
         //TODO this return run time error! assertion error, it's out of range most likely
         //let c_cm_base_bytes : [u8; 32] = c_cm.to_bytes();
+
         /*
         let c_cm_base_bytes : [u8; 32] = c_cm.to_affine()
             .coordinates()
             .unwrap()
             .x().to_repr();
         let c_cm_base : pallas::Base = pallas::Base::from_repr(c_cm_base_bytes).unwrap();
-        */
-        let c_cm_node = MerkleNode(pallas::Base::from(1)); // this is temporary, shouldn't pass of course
+         */
+        let c_cm_base = pallas::Base::from(1);
+        let c_cm_node = MerkleNode(c_cm_base);
         tree_cm.append(&c_cm_node.clone());
         let leaf_position = tree_cm.witness();
-        //let (leaf_pos, c_cm_path) = tree_cm.authentication_path(&c_cm_node).unwrap();
-        //let (leaf_pos, c_cm_path) = tree_cm.authentication_path(leaf_position.unwrap()).unwrap();
         let c_cm_path = tree_cm.authentication_path(leaf_position.unwrap()).unwrap();
         let c_root_cm = tree_cm.root();
         // lead coin commitment
         let c_seed2 = pedersen_commitment_scalar(mod_r_p(c_seed), mod_r_p(c_root_sk.inner()));
         let c_seed2_pt = c_seed2.to_affine().coordinates().unwrap();
-        let lead_coin_msg = [*c_pk_pt.x(), *c_pk_pt.y(), c_v, *c_seed2_pt.x(), *c_seed2_pt.y()];
+        /*
+        let lead_coin_msg = [c_pk_pt_y.clone(),
+                             c_pk_pt_x.clone(),
+                             c_v,
+                             *c_seed2_pt.x(),
+                             *c_seed2_pt.y()
+        ];
         let lead_coin_msg_hash =
             poseidon::Hash::<_, P128Pow5T3, ConstantLength<5>, 3, 2>::init().hash(lead_coin_msg);
-        let c_cm2 = pedersen_commitment_scalar(mod_r_p(lead_coin_msg_hash), mod_r_p(c_cm2_blind));
+         */
+        let lead_coin_msg = c_pk_pt_y.clone() *
+            c_pk_pt_x.clone() *
+            c_v *
+            *c_seed2_pt.x() *
+            *c_seed2_pt.y();
+        let c_cm2 = pedersen_commitment_scalar(mod_r_p(lead_coin_msg), mod_r_p(c_cm2_blind));
         let c_root_sk = root_sks[i];
         let c_path_sk = path_sks[i];
+
         let coin = Coin {
             value: Some(c_v),
             cm: Some(c_cm),
             cm2: Some(c_cm2),
-            cm_blind: Some(c_cm1_blind),
             sl: Some(c_sl),
             tau: Some(c_tau),
             nonce: Some(c_seed),
@@ -150,6 +172,8 @@ fn main() {
             sn: Some(c_sn),
             //sk: Some(c_sk),
             pk: Some(c_pk),
+            pk_x: Some(c_pk_pt_x),
+            pk_y: Some(c_pk_pt_y),
             root_cm: Some(mod_r_p(c_root_cm.inner())),
             root_sk: Some(mod_r_p(c_root_sk.inner())),
             path: Some(c_cm_path.as_slice().try_into().unwrap()),
@@ -184,11 +208,14 @@ fn main() {
     let po_path = coin.path.unwrap();
 
     let po_cmp = pallas::Base::from(0);
+    let zero = pallas::Base::from(0);
     // ===============
     let path_sk = path_sks[coin_idx];
 
     let contract = LeadContract {
         path: coin.path,
+        coin_pk_x : coin.pk_x,
+        coin_pk_y : coin.pk_y,
         root_sk: coin.root_sk,
         path_sk: Some(path_sk),
         coin_timestamp: coin.tau, //
@@ -211,16 +238,22 @@ fn main() {
     let mut public_inputs: Vec<pallas::Base> = vec![
         *po_nonce.x(),
         *po_nonce.y(),
+
         *po_pk.x(),
         *po_pk.y(),
+
         *po_sn.x(),
         *po_sn.y(),
+
         *po_cm.x(),
         *po_cm.y(),
+
         *po_cm2.x(),
         *po_cm2.y(),
-        po_path[31].inner(), //TODO (res) how the path is structured assumed root is last node in the path.
-        po_cmp,
+
+        //po_path[31].inner(), //TODO (res) how the path is structured assumed root is last node in the path.
+        //po_cmp,
+
     ];
 
     let prover = MockProver::run(k, &contract, vec![public_inputs]).unwrap();

+ 75 - 103
src/zk/circuit/lead_contract.rs

@@ -111,6 +111,8 @@ const LEAD_THRESHOLD_OFFSET: usize = 11;
 pub struct LeadContract {
     // witness
     pub path: Option<[MerkleNode; MERKLE_DEPTH_ORCHARD]>,
+    pub coin_pk_x: Option<pallas::Base>,
+    pub coin_pk_y: Option<pallas::Base>,
     pub root_sk: Option<pallas::Scalar>, // coins merkle tree secret key of coin1
     pub path_sk: Option<[MerkleNode; MERKLE_DEPTH_ORCHARD]>, // path to the secret key root_sk
     pub coin_timestamp: Option<pallas::Base>,
@@ -266,6 +268,7 @@ 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();
@@ -281,24 +284,14 @@ impl Circuit<pallas::Base> for LeadContract {
 
         // coin_timestamp tau
 
+
         let coin_timestamp = self.load_private(
             layouter.namespace(|| "load coin time stamp"),
             config.advices[0],
             self.coin_timestamp,
         )?;
 
-        // root of coin
-
-        /*
-        let root_sk = self.load_private(
-            layouter.namespace(|| "load root coin"),
-            config.advices[0],
-            self.root_sk,
-        )?;
-        */
-        // coin nonce
-
-        let coin_nonce = self.load_private(
+        let coin_nonce : AssignedCell<Fp,Fp> = self.load_private(
             layouter.namespace(|| "load coin nonce"),
             config.advices[0],
             self.coin_nonce,
@@ -309,104 +302,40 @@ impl Circuit<pallas::Base> for LeadContract {
             config.advices[0],
             self.value,
         )?;
-
-        /*
-        let coin_opening_1 = self.load_private(
-            layouter.namespace(|| "load opening 1"),
+        let coin_pk_x : AssignedCell<Fp,Fp> = self.load_private(
+            layouter.namespace(|| "load coin time stamp"),
             config.advices[0],
-            self.coin_opening_1,
+            self.coin_pk_x,
         )?;
-        let coin_opening_2 = self.load_private(
-            layouter.namespace(|| "load opening 2"),
+
+
+        let coin_pk_y : AssignedCell<Fp,Fp> = self.load_private(
+            layouter.namespace(|| "load coin time stamp"),
             config.advices[0],
-            self.coin_opening_2,
+            self.coin_pk_y,
         )?;
-         */
-
-        //let cm_c1_point : pallas::Point = pallas::Point::from(1);
-        //let cm_c1 : AssignedCell<pallas::Point, pallas::Point> = cm_c1_point;
 
         let cm_c1_x =
             self.load_private(layouter.namespace(|| ""), config.advices[0], self.cm_c1_x)?;
+
         let cm_c1_y =
             self.load_private(layouter.namespace(|| ""), config.advices[0], self.cm_c1_y)?;
 
         let cm_c2_x =
             self.load_private(layouter.namespace(|| ""), config.advices[0], self.cm_c2_x)?;
+
         let cm_c2_y =
             self.load_private(layouter.namespace(|| ""), config.advices[0], self.cm_c2_y)?;
 
-        /*
-        let cm_pos = self.load_private(
-            layouter.namespace(|| ""),
-            config.advices[0],
-            self.cm_pos
-        )?;
-
-        let sn_c1 = self.load_private(
-            layouter.namespace(|| ""),
-            config.advices[0],
-            self.sn_c1,
-        )?;
-        */
-
-        /*
-        let eta = self.load_private(
-            layouter.namespace(|| ""),
-            config.advices[0],
-            self.eta,
-        )?;
-         */
-
-        let slot = self.load_private(layouter.namespace(|| ""), config.advices[0], self.slot)?;
-
-        /*
-        let rho = self.load_private(
-            layouter.namespace(|| ""),
-            config.advices[0],
-            self.rho,
-        )?;
-
-        let h = self.load_private(
-            layouter.namespace(|| ""),
-            config.advices[0],
-            self.h,
-        )?;
-
-        let ptr = self.load_private(
-            layouter.namespace(|| ""),
-            config.advices[0],
-            self.ptr,
-        )?;
-         */
-
-        /*
-        let mau_rho = self.load_private(
-            layouter.namespace(|| ""),
-            config.advices[0],
-            self.mau_rho,
-        )?;
-
-        let mau_y = self.load_private(
-            layouter.namespace(|| ""),
-            config.advices[0],
-            self.mau_y,
-        )?;
-        */
-
-        /*
-        let root = self.load_private(
-            layouter.namespace(|| ""),
-            config.advices[0],
-            self.root,
-        )?;
-         */
+        let slot =
+            self.load_private(layouter.namespace(|| ""), config.advices[0], self.slot)?;
 
         let one = self.load_private(
             layouter.namespace(|| "one"),
             config.advices[0],
             Some(pallas::Base::one()),
         )?;
+
         //TODO read the second coin commitment as constant(public input)
         // in this case
         //
@@ -441,6 +370,7 @@ impl Circuit<pallas::Base> for LeadContract {
             LEAD_COIN_NONCE2_Y_OFFSET,
         )?;
 
+
         // ================
         // coin public key constraints derived from the coin timestamp
         // ================
@@ -459,6 +389,7 @@ impl Circuit<pallas::Base> for LeadContract {
             coin_pk_commit_r.mul(layouter.namespace(|| "coin_pk commit R"), self.root_sk)?
         };
         let coin_pk_commit = com.add(layouter.namespace(|| "coin timestamp commit"), &blind)?;
+
         // constrain coin's pub key x value
 
         layouter.constrain_instance(
@@ -481,6 +412,7 @@ impl Circuit<pallas::Base> for LeadContract {
         // constrain coin c1 serial number
         // =============
         // m*G_1
+
         let (com, _) = {
             let sn_commit_v = ValueCommitV;
             let sn_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), sn_commit_v);
@@ -510,6 +442,7 @@ impl Circuit<pallas::Base> for LeadContract {
             config.primary,
             LEAD_COIN_SERIAL_NUMBER_Y_OFFSET,
         )?;
+
         // ==========================
         // commitment of coins c1,c2
         // ==========================
@@ -526,15 +459,17 @@ impl Circuit<pallas::Base> for LeadContract {
         //TODO does both coins have the same value?!! doesn't make sense
         //but only single value is in witness.
 
-        let coin_hash = {
+        /*
+        let coin_hash  = {
             let poseidon_message = [
-                coin_pk_commit.inner().x(),
-                coin_pk_commit.inner().y(),
-                coin_value.clone(),
-                coin_nonce.clone(),
+                //coin_pk_commit.inner().x(),
+                //coin_pk_commit.inner().y(),
+                //coin_value.clone(),
+                //coin_nonce.clone(),
+                coin_pk_x.clone(),
             ];
 
-            let poseidon_hasher = PoseidonHash::<_, _, P128Pow5T3, ConstantLength<4>, 3, 2>::init(
+            let poseidon_hasher = PoseidonHash::<_, _, P128Pow5T3, ConstantLength<1>, 3, 2>::init(
                 config.poseidon_chip(),
                 layouter.namespace(|| "Poseidon init"),
             )?;
@@ -545,11 +480,34 @@ impl Circuit<pallas::Base> for LeadContract {
             let poseidon_output: AssignedCell<Fp, Fp> = poseidon_output;
             poseidon_output
         };
+         */
+        let coin_val = {
+            //TODO (research) this panic probably due to arith_chip overflowing
+
+            let coin_val_pt = ar_chip.mul(layouter.namespace(|| ""),
+                                       coin_pk_y.clone(),
+                                       coin_pk_x.clone(),
+            )?;
+
+            let coin_val0 = ar_chip.mul(layouter.namespace(|| ""),
+                        coin_nonce.clone(),
+                        coin_value.clone()
+            )?;
+            ar_chip.mul(layouter.namespace(||""),
+                        coin_val_pt.clone(),
+                        coin_val0.clone())?
+        };
+
         let (com, _) = {
+
             let coin_commit_v = ValueCommitV;
             let coin_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), coin_commit_v);
-            coin_commit_v.mul(layouter.namespace(|| "coin commit v"), (coin_hash, one.clone()))?
+            coin_commit_v.mul(layouter.namespace(|| "coin commit v"),
+                              (coin_val.clone(), one.clone())
+            )?
+
         };
+
         // r*G_2
         let (blind, _) = {
             let coin_commit_r = OrchardFixedBasesFull::ValueCommitR;
@@ -557,30 +515,35 @@ impl Circuit<pallas::Base> for LeadContract {
             coin_commit_r
                 .mul(layouter.namespace(|| "coin serial number commit R"), self.coin_opening_1)?
         };
+
         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();
 
+        //TODO subtract cm from given cm to sum to zero
         let cm1_zero_out_x =
             ar_chip.sub(layouter.namespace(|| "sub to zero"), coin_commit_x.clone(), cm_c1_x)?;
         let cm1_zero_out_y =
             ar_chip.sub(layouter.namespace(|| "sub to zero"), coin_commit_y.clone(), cm_c1_y)?;
 
         // constrain coin's pub key x value
+
+
         layouter.constrain_instance(
-            cm1_zero_out_x.cell(),
+            coin_commit_x.cell(),
             config.primary,
             LEAD_COIN_COMMIT_X_OFFSET,
         )?;
         // constrain coin's pub key y value
         layouter.constrain_instance(
-            cm1_zero_out_y.cell(),
+            coin_commit_y.cell(),
             config.primary,
             LEAD_COIN_COMMIT_Y_OFFSET,
         )?;
 
         //
+        /*
         let coin2_hash = {
             let poseidon_message = [
                 coin_pk_commit.inner().x(),
@@ -601,6 +564,12 @@ impl Circuit<pallas::Base> for LeadContract {
             let poseidon_output: AssignedCell<Fp, Fp> = poseidon_output;
             poseidon_output
         };
+         */
+        let coin2_hash0 = ar_chip.mul(layouter.namespace(||""), coin_pk_commit.inner().x(), coin_pk_commit.inner().y())?;
+        let coin2_hash1 = ar_chip.mul(layouter.namespace(||""), coin2_nonce.inner().x(), coin2_nonce.inner().y())?;
+        let coin2_hash2 = ar_chip.mul(layouter.namespace(||""), coin2_hash0.clone(), coin2_hash1.clone())?;
+        let coin2_hash = ar_chip.mul(layouter.namespace(||""), coin_value.clone(), coin2_hash2)?;
+
         let (com, _) = {
             let coin_commit_v = ValueCommitV;
             let coin_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), coin_commit_v);
@@ -616,23 +585,25 @@ impl Circuit<pallas::Base> for LeadContract {
         let coin2_commit = com.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();
+        /*
         let cm2_zero_out_x =
             ar_chip.sub(layouter.namespace(|| "sub to zero"), coin2_commit_x, cm_c2_x)?;
         let cm2_zero_out_y =
             ar_chip.sub(layouter.namespace(|| "sub to zero"), coin2_commit_y, cm_c2_y)?;
-
+        */
         layouter.constrain_instance(
-            cm2_zero_out_x.cell(),
+            coin2_commit_x.cell(),
             config.primary,
             LEAD_COIN_COMMIT2_X_OFFSET,
         )?;
         // constrain coin's pub key y value
         layouter.constrain_instance(
-            cm2_zero_out_y.cell(),
+            coin2_commit_y.cell(),
             config.primary,
-            LEAD_COIN_COMMIT2_X_OFFSET,
+            LEAD_COIN_COMMIT2_Y_OFFSET,
         )?;
 
+
         // ===========================
         let path: Option<[pallas::Base; MERKLE_DEPTH_ORCHARD]> =
             self.path.map(|typed_path| gen_const_array(|i| typed_path[i].inner()));
@@ -661,7 +632,7 @@ impl Circuit<pallas::Base> for LeadContract {
         };
         let computed_final_root = merkle_inputs
             .calculate_root(layouter.namespace(|| "calculate root"), coin_commit_hash)?;
-
+        /*
         layouter.constrain_instance(
             computed_final_root.cell(),
             config.primary,
@@ -754,6 +725,7 @@ impl Circuit<pallas::Base> for LeadContract {
         )?; //note assuming x,y coordinates are true random each?
         eb_chip.decompose(layouter.namespace(|| "helper range check"), helper.0)?;
         layouter.constrain_instance(is_gt.0.cell(), config.primary, LEAD_THRESHOLD_OFFSET)?;
+        */
         Ok(())
     }
 }