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

[zk/lead] set commitment tree for product of point's coordinates

mohab 4 лет назад
Родитель
Сommit
fe5e6f7def
2 измененных файлов с 80 добавлено и 83 удалено
  1. 44 22
      example/lead.rs
  2. 36 61
      src/zk/circuit/lead_contract.rs

+ 44 - 22
example/lead.rs

@@ -27,6 +27,8 @@ use darkfi::{
     zk::circuit::lead_contract::LeadContract,
 };
 
+use incrementalmerkletree::Hashable;
+
 use pasta_curves::{arithmetic::CurveAffine, group::Curve};
 use pasta_curves::group::{ff::PrimeField, GroupEncoding};
 //use halo2_proofs::arithmetic::CurveAffine;
@@ -82,8 +84,8 @@ fn main() {
     //
     let yu64: u64 = rng.gen();
     let rhou64: u64 = rng.gen();
-    let mau_y: pallas::Scalar = pallas::Scalar::from(yu64);
-    let mau_rho: pallas::Scalar = pallas::Scalar::from(rhou64);
+    let mau_y: pallas::Base = pallas::Base::from(yu64);
+    let mau_rho: pallas::Base = pallas::Base::from(rhou64);
 
     //
     let mut coins: Vec<Coin> = vec![];
@@ -126,14 +128,10 @@ fn main() {
         //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_base = pallas::Base::from(1);
+
+        let c_cm_coordinates = c_cm.to_affine().coordinates().unwrap();
+        let c_cm_base : pallas::Base = c_cm_coordinates.x() *
+            c_cm_coordinates.y();
         let c_cm_node = MerkleNode(c_cm_base);
         tree_cm.append(&c_cm_node.clone());
         let leaf_position = tree_cm.witness();
@@ -141,16 +139,16 @@ fn main() {
         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 c_seed2_pt = c_seed2.to_affine().coordinates().unwrap();
         /*
         let lead_coin_msg = [c_pk_pt_y.clone(),
-                             c_pk_pt_x.clone(),
-                             c_v,
-                             *c_seed2_pt.x(),
-                             *c_seed2_pt.y()
-        ];
+        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);
+        poseidon::Hash::<_, P128Pow5T3, ConstantLength<5>, 3, 2>::init().hash(lead_coin_msg);
          */
         let lead_coin_msg = c_pk_pt_y.clone() *
             c_pk_pt_x.clone() *
@@ -159,6 +157,14 @@ fn main() {
             *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_root_sk_bytes : [u8;32] = c_root_sk.inner().to_repr();
+        let mut c_root_sk_base_bytes : [u8;32] = [0;32];
+        for i in 0..23 {
+            c_root_sk_base_bytes[i] = c_root_sk_bytes[i];
+        }
+        let c_root_sk_base = pallas::Base::from_repr(c_root_sk_base_bytes);
+
         let c_path_sk = path_sks[i];
 
         let coin = Coin {
@@ -205,13 +211,12 @@ fn main() {
     let po_pk = coin.pk.unwrap().to_affine().coordinates().unwrap();
     let po_sn = coin.sn.unwrap().to_affine().coordinates().unwrap();
 
-    let po_path = coin.path.unwrap();
 
-    let po_cmp = pallas::Base::from(1);
+    let po_cmp = pallas::Base::from(0);
     let zero = pallas::Base::from(0);
     // ===============
     let path_sk = path_sks[coin_idx];
-
+    let cm_pos = u32::try_from(coin_idx).unwrap();
     let contract = LeadContract {
         path: coin.path,
         coin_pk_x : coin.pk_x,
@@ -223,7 +228,7 @@ fn main() {
         coin_opening_1: Some(mod_r_p(coin.opening1.unwrap())),
         value: coin.value,
         coin_opening_2: Some(mod_r_p(coin.opening2.unwrap())),
-        cm_pos: Some(u32::try_from(coin_idx).unwrap()),
+        cm_pos: Some(cm_pos),
         //sn_c1: Some(coin.sn.unwrap()),
         slot: Some(coin.sl.unwrap()),
         mau_rho: Some(mau_rho.clone()),
@@ -231,6 +236,23 @@ fn main() {
         root_cm: Some(coin.root_cm.unwrap()),
     };
 
+    let cm_root = {
+        let pos : u32 = cm_pos;
+        let c_cm_coordinates = coin.cm.unwrap().to_affine().coordinates().unwrap();
+        let c_cm_base : pallas::Base = c_cm_coordinates.x() *
+            c_cm_coordinates.y();
+        let mut current = MerkleNode(c_cm_base);
+        for (level, sibling) in coin.path.unwrap().iter().enumerate() {
+            let level = level as u8;
+            current = if pos & (1 << level) == 0 {
+                MerkleNode::combine(level.into(), &current, sibling)
+            } else {
+                MerkleNode::combine(level.into(), sibling, &current)
+            };
+        }
+        current
+    };
+
     let mut public_inputs: Vec<pallas::Base> = vec![
         *po_nonce.x(),
         *po_nonce.y(),
@@ -247,7 +269,7 @@ fn main() {
         *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.
+        cm_root.0,
         po_cmp,
 
     ];

+ 36 - 61
src/zk/circuit/lead_contract.rs

@@ -129,8 +129,8 @@ pub struct LeadContract {
     //
     //pub sn_c1 : Option<pallas::Base>,
     pub slot: Option<pallas::Base>,
-    pub mau_rho: Option<pallas::Scalar>,
-    pub mau_y: Option<pallas::Scalar>,
+    pub mau_rho: Option<pallas::Base>,
+    pub mau_y: Option<pallas::Base>,
     pub root_cm: Option<pallas::Scalar>,
     //pub eta : Option<u32>,
     //pub rho : Option<u32>,
@@ -314,15 +314,18 @@ impl Circuit<pallas::Base> for LeadContract {
         let slot =
             self.load_private(layouter.namespace(|| ""), config.advices[0], self.slot)?;
 
+        let root_sk = self.load_private(
+            layouter.namespace(||""),
+            config.advices[0],
+            self.root_sk,
+        )?;
+
         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
-        //
 
         // ===============
         // coin 2 nonce
@@ -331,14 +334,17 @@ impl Circuit<pallas::Base> for LeadContract {
         let (com, _) = {
             let nonce2_commit_v = ValueCommitV;
             let nonce2_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), nonce2_commit_v);
-            nonce2_commit_v
-                .mul(layouter.namespace(|| "coin_pk commit v"), (coin_nonce.clone(), one.clone()))?
+            nonce2_commit_v.mul(layouter.namespace(|| "coin_pk commit v"),
+                     (coin_nonce.clone(), one.clone())
+                )?
         };
         // r*G_2
         let (blind, _) = {
             let nonce2_commit_r = OrchardFixedBasesFull::ValueCommitR;
             let nonce2_commit_r = FixedPoint::from_inner(ecc_chip.clone(), nonce2_commit_r);
-            nonce2_commit_r.mul(layouter.namespace(|| "nonce2 commit R"), Some(mod_r_p(self.root_sk.unwrap())))?
+            nonce2_commit_r.mul(layouter.namespace(|| "nonce2 commit R"),
+                                Some(mod_r_p(self.root_sk.unwrap()))
+            )?
         };
         let coin2_nonce = com.add(layouter.namespace(|| "nonce2 commit"), &blind)?;
 
@@ -575,7 +581,6 @@ impl Circuit<pallas::Base> for LeadContract {
             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()));
@@ -588,70 +593,40 @@ impl Circuit<pallas::Base> for LeadContract {
             path,
         );
 
-        let coin_commit_hash: AssignedCell<Fp, Fp> = {
-            let poseidon_message = [coin_commit_x.clone(), coin_commit_y.clone()];
-
-            let poseidon_hasher = PoseidonHash::<_, _, P128Pow5T3, ConstantLength<2>, 3, 2>::init(
-                config.poseidon_chip(),
-                layouter.namespace(|| "Poseidon init"),
-            )?;
+        let coin_commit_prod: AssignedCell<Fp, Fp> = {
+            let coin_commit_coordinates = coin_commit.inner();
 
-            let poseidon_output =
-                poseidon_hasher.hash(layouter.namespace(|| "Poseidon hash"), poseidon_message)?;
-
-            let poseidon_output: AssignedCell<Fp, Fp> = poseidon_output;
-            poseidon_output
+            let res : AssignedCell<Fp,Fp> =
+                ar_chip.mul(layouter.namespace(||""),
+                            coin_commit_coordinates.x(),
+                            coin_commit_coordinates.y()).unwrap();
+            res
         };
+
         let computed_final_root = merkle_inputs
-            .calculate_root(layouter.namespace(|| "calculate root"), coin_commit_hash)?;
+            .calculate_root(layouter.namespace(|| "calculate root"), coin_commit_prod.clone())?;
 
         //TODO (fix)
-        /*
+
         layouter.constrain_instance(
             computed_final_root.cell(),
             config.primary,
             LEAD_COIN_COMMIT_PATH_OFFSET,
         )?;
-        */
 
-        /*
-        let message  = {
-            let (com, _) = {
-                let commit_v = ValueCommitV;
-                let commit_v = FixedPointShort::from_inner(ecc_chip.clone(), commit_v);
-                commit_v.mul(
-                    layouter.namespace(|| "coin commit v"),
-                    (coin_nonce.clone(), one.clone()),
-                )?
-            };
-            // r*G_2
-            let (blind, _) = {
-                let commit_r = OrchardFixedBasesFull::ValueCommitR;
-                let commit_r = FixedPoint::from_inner(ecc_chip.clone(), commit_r);
-                commit_r.mul(layouter.namespace(|| "coin serial number commit R"), self.root_sk)?
-            };
-            com.add(layouter.namespace(|| "nonce commit"), &blind)?
-        };
-        */
-
-        //TODO (research need root_sk as base
-        let root_sk = self.load_private(
-            layouter.namespace(||""),
-            config.advices[0],
-            self.root_sk,
-        )?;
 
+        //TODO (research) this multiplication panics!
         let y_commit_exp = ar_chip.mul(layouter.namespace(||""),
                                        coin_nonce.clone(),
-                                       //root_sk.clone(),
-                                       one.clone(),
+                                       //root_sk.clone(), //(fix)
+                                       one.clone()
         )?;
 
         let (com, _) = {
             let y_commit_v = ValueCommitV;
             let y_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), y_commit_v);
             y_commit_v.mul(layouter.namespace(|| "coin commit v"),
-                           (y_commit_exp.clone(), one.clone()),
+                           (y_commit_exp, one.clone()),
             )?
         };
 
@@ -660,7 +635,7 @@ impl Circuit<pallas::Base> for LeadContract {
             let y_commit_r = OrchardFixedBasesFull::ValueCommitR;
             let y_commit_r = FixedPoint::from_inner(ecc_chip.clone(), y_commit_r);
             y_commit_r.mul(layouter.namespace(|| "coin serial number commit R"),
-                           self.mau_y
+                           Some(mod_r_p(self.mau_y.unwrap()))
             )?
         };
         let mut y_commit = com.add(layouter.namespace(|| "nonce commit"), &blind)?;
@@ -693,7 +668,9 @@ impl Circuit<pallas::Base> for LeadContract {
         let (blind, _) = {
             let rho_commit_r = OrchardFixedBasesFull::ValueCommitR;
             let rho_commit_r = FixedPoint::from_inner(ecc_chip.clone(), rho_commit_r);
-            rho_commit_r.mul(layouter.namespace(|| "coin serial number commit R"), self.mau_rho)?
+            rho_commit_r.mul(layouter.namespace(|| "coin serial number commit R"),
+                             Some(mod_r_p(self.mau_rho.unwrap())),
+            )?
         };
         let rho_commit = com.add(layouter.namespace(|| "nonce commit"), &blind)?;
         //TODO in case of the v_max lead statement you need to provide a proof
@@ -706,7 +683,7 @@ impl Circuit<pallas::Base> for LeadContract {
         //leadership coefficient
         let c = self.load_private(layouter.namespace(||""),
                                   config.advices[0],
-                                  Some(pallas::Base::one()),
+                                  Some(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)?;
@@ -714,14 +691,11 @@ impl Circuit<pallas::Base> for LeadContract {
         eb_chip.decompose(layouter.namespace(|| "target range check"), target.clone())?;
         eb_chip.decompose(layouter.namespace(|| "y_commit  range check"), y_commit_base.clone())?;
 
-        //TODO (research) maybe pick up the first bit of the y_commit_base
         let (helper, is_gt) = greater_than_chip.greater_than(
             layouter.namespace(|| "t>y"),
             target.into(),
-            //y_commit_base.into(),
-            one.into(),
-
-        )?; //note assuming x,y coordinates are true random each?
+            y_commit_base.into(),
+        )?;
         eb_chip.decompose(layouter.namespace(|| "helper range check"), helper.0)?;
 
         layouter.constrain_instance(
@@ -731,5 +705,6 @@ impl Circuit<pallas::Base> for LeadContract {
         )?;
 
         Ok(())
+
     }
 }