Jelajahi Sumber

[crypsinous zk/circuit/lead_contract] fix order of public inputs

mohab metwally 4 tahun lalu
induk
melakukan
7488b9f484
8 mengubah file dengan 168 tambahan dan 214 penghapusan
  1. 0 17
      Cargo.lock
  2. 0 1
      Cargo.toml
  3. 4 4
      example/lead.rs
  4. 0 1
      src/blockchain/epoch.rs
  5. 23 24
      src/crypto/leadcoin.rs
  6. 2 5
      src/stakeholder/stakeholder.rs
  7. 2 14
      src/util/clock.rs
  8. 137 148
      src/zk/circuit/lead_contract.rs

+ 0 - 17
Cargo.lock

@@ -1019,17 +1019,6 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
 
-[[package]]
-name = "crypsinous"
-version = "0.1.0"
-dependencies = [
- "async-std",
- "darkfi",
- "futures",
- "thread",
- "url",
-]
-
 [[package]]
 name = "crypto-common"
 version = "0.1.3"
@@ -4121,12 +4110,6 @@ dependencies = [
  "syn",
 ]
 
-[[package]]
-name = "thread"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afe9c0e959dd1e7b871071b51bc674380d1889cd4fed9f4b3b1f5c1772d9f796"
-
 [[package]]
 name = "time"
 version = "0.1.44"

+ 0 - 1
Cargo.toml

@@ -31,7 +31,6 @@ members = [
 	"bin/tau/taud",
 	"bin/tau/tau-cli",
 	"bin/vanityaddr",
-        "bin/crypsinous",
 	"src/sdk",
 	"src/util/derive",
 	"src/util/derive-internal",

+ 4 - 4
example/lead.rs

@@ -77,10 +77,10 @@ fn main() {
     let lead_pk = stakeholder.get_provkingkey();
     let lead_vk = stakeholder.get_verifyingkey();
 
-    let proof = lead_proof::create_lead_proof(&lead_pk.clone(), coin.clone()).unwrap();
-    lead_proof::verify_lead_proof(&lead_vk, &proof, &public_inputs);
+    //let proof = lead_proof::create_lead_proof(&lead_pk.clone(), coin.clone()).unwrap();
+    //lead_proof::verify_lead_proof(&lead_vk, &proof, &public_inputs);
 
-    //let prover = MockProver::run(k, &contract, vec![public_inputs.to_vec()]).unwrap();
-    //prover.assert_satisfied();
+    let prover = MockProver::run(k, &contract, vec![public_inputs.to_vec()]).unwrap();
+    prover.assert_satisfied();
     //assert_eq!(prover.verify(), Ok(()));
 }

+ 0 - 1
src/blockchain/epoch.rs

@@ -179,7 +179,6 @@ impl Epoch {
             //pseudo random sampling that is the size of pederson commitment
             // coin slot number
 
-            //TODO this has to be absolute path
             let c_sl = pallas::Base::from(u64::try_from(i).unwrap());
             //
             //let's assume it's sl for simplicity

+ 23 - 24
src/crypto/leadcoin.rs

@@ -19,26 +19,25 @@ pub const LEAD_PUBLIC_INPUT_LEN : usize = 8;
 
 #[derive(Debug, Default, Clone, Copy)]
 pub struct LeadCoin {
-    pub value: Option<pallas::Base>, //stake
-    pub cm: Option<pallas::Point>,
-    pub cm2: Option<pallas::Point>,
-    pub idx: u32,
-    pub sl: Option<pallas::Base>, //slot id
-    pub tau: Option<pallas::Base>,
-    pub nonce: Option<pallas::Base>,
-    pub nonce_cm: Option<pallas::Base>,
+    pub value: Option<pallas::Base>, // coin stake
+    pub cm: Option<pallas::Point>, // coin commitment
+    pub cm2: Option<pallas::Point>, // poured coin commitment
+    pub idx: u32, // coin idex
+    pub sl: Option<pallas::Base>, // coin slot id
+    pub tau: Option<pallas::Base>, // coin time stamp
+    pub nonce: Option<pallas::Base>, // coin nonce
+    pub nonce_cm: Option<pallas::Base>, // coin nonce's commitment
     pub sn: Option<pallas::Base>, // coin's serial number
-    //sk : Option<SecretKey>,
-    pub pk: Option<pallas::Base>,
-    pub root_cm: Option<pallas::Scalar>,
-    pub root_sk: Option<pallas::Base>,
-    pub path: Option<[MerkleNode; MERKLE_DEPTH_ORCHARD]>,
-    pub path_sk: Option<[MerkleNode; MERKLE_DEPTH_ORCHARD]>,
-    pub c1_blind: Option<pallas::Scalar>,
-    pub c2_blind: Option<pallas::Scalar>,
+    pub pk: Option<pallas::Base>, // coin public key
+    pub root_cm: Option<pallas::Scalar>, // root of coin commitment
+    pub root_sk: Option<pallas::Base>, // coin's secret key
+    pub path: Option<[MerkleNode; MERKLE_DEPTH_ORCHARD]>, // path to the coin's commitment
+    pub path_sk: Option<[MerkleNode; MERKLE_DEPTH_ORCHARD]>, // path to the coin's secret key
+    pub c1_blind: Option<pallas::Scalar>, // coin opening
+    pub c2_blind: Option<pallas::Scalar>, // poured coin opening
     // election seeds
-    pub y_mu: Option<pallas::Base>,
-    pub rho_mu: Option<pallas::Base>,
+    pub y_mu: Option<pallas::Base>, // leader election nonce derived from eta at onset of epoch
+    pub rho_mu: Option<pallas::Base>, // leader election nonce derived from eta at onset of epoch
 }
 
 impl LeadCoin {
@@ -57,6 +56,7 @@ impl LeadCoin {
 
         let po_cmp = pallas::Base::from(1);
         let _zero = pallas::Base::from(0);
+
         // ===============
 
         let cm_pos = self.idx;
@@ -76,8 +76,6 @@ impl LeadCoin {
             current
         };
         let public_inputs : [pallas::Base;LEAD_PUBLIC_INPUT_LEN] = [
-            po_pk,
-            po_sn,
 
             *po_cm.x(),
             *po_cm.y(),
@@ -87,6 +85,10 @@ impl LeadCoin {
 
             po_nonce,
             cm_root.0,
+
+            po_pk,
+            po_sn,
+
         ];
         public_inputs
     }
@@ -95,13 +97,10 @@ impl LeadCoin {
         self.public_inputs_as_array().to_vec()
     }
 
-    pub fn create_contract(&self) -> LeadContract
-    {
+    pub fn create_contract(&self) -> LeadContract {
         let contract = LeadContract {
             path: Value::known(self.path.unwrap()),
-            coin_pk: Value::known(self.pk.unwrap()),
             root_sk: Value::known(self.root_sk.unwrap()),
-            sf_root_sk: Value::known(mod_r_p(self.root_sk.unwrap())),
             path_sk: Value::known(self.path_sk.unwrap()),
             coin_timestamp: Value::known(self.tau.unwrap()), //
             coin_nonce: Value::known(self.nonce.unwrap()),

+ 2 - 5
src/stakeholder/stakeholder.rs

@@ -273,6 +273,7 @@ impl Stakeholder
     }
 
     pub async fn background(&mut self) {
+        self.clock.sync().await;
         while self.playing {
             // clock ticks slot begins
             // initialize the epoch if it's the time
@@ -373,11 +374,7 @@ impl Stakeholder
     }
 }
 
-impl fmt::Display
-
-
-
-for Stakeholder {
+impl fmt::Display for Stakeholder {
     fn fmt(&self, formater : &mut fmt::Formatter) ->  fmt::Result {
         formater.write_fmt(format_args!("stakeholder with id: {}", self.id))
     }

+ 2 - 14
src/util/clock.rs

@@ -55,7 +55,7 @@ impl Clock {
     }
 
     async fn time(&self) -> Result<Timestamp> {
-        //TODO (fix) add more than ntp server to time.
+        //TODO (fix) add more than ntp server to time, and take the avg
         /*
         match time::check_clock(self.peers.clone()).await {
             Ok(t) => {
@@ -64,20 +64,8 @@ impl Clock {
             Err(e) => {
                 Err(Error::ClockOutOfSync(e.to_string()))
             }
-        }
-         */
-        //TODO (panics)
-        /*
-        match time::ntp_request().await.unwrap() {
-            t => {
-                Ok(t)
-            },
-            e => {
-                debug!("ntp request failed: {}", e);
-                Err(Error::ClockOutOfSync(e.to_string()))
-            }
     }
-         */
+        */
         Ok(Timestamp::current_time())
     }
 

+ 137 - 148
src/zk/circuit/lead_contract.rs

@@ -88,37 +88,32 @@ impl LeadConfig {
         LessThanChip::construct(self.lessthan_config.clone())
     }
 
-    /*
-    fn evenbits_chip(&self) -> EvenBitsChip<pallas::Base, WORD_BITS> {
-        EvenBitsChip::construct(self.evenbits_config.clone())
-    }
-     */
-
     fn arith_chip(&self) -> ArithChip {
         ArithChip::construct(self.arith_config.clone())
      }
 }
 
 
-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_COIN_COMMIT_X_OFFSET: usize = 0;
+const LEAD_COIN_COMMIT_Y_OFFSET: usize = 1;
+const LEAD_COIN_COMMIT2_X_OFFSET: usize = 2;
+const LEAD_COIN_COMMIT2_Y_OFFSET: usize = 3;
+const LEAD_COIN_NONCE2_OFFSET: usize = 4;
+const LEAD_COIN_COMMIT_PATH_OFFSET: usize = 5;
+const LEAD_COIN_PK_OFFSET: usize = 6;
+const LEAD_COIN_SERIAL_NUMBER_OFFSET: usize = 7;
 
 pub fn concat_u8(lhs: &[u8], rhs: &[u8]) -> Vec<u8> {
     [lhs, rhs].concat()
 }
+
+
 #[derive(Default, Debug)]
 pub struct LeadContract {
     // witness
     pub path: Value<[MerkleNode; MERKLE_DEPTH_ORCHARD]>,
-    pub coin_pk: Value<pallas::Base>,
     pub root_sk: Value<pallas::Base>, // coins merkle tree secret key of coin1
-    pub sf_root_sk: Value<pallas::Scalar>, // root_sk as pallas::Scalar
     pub path_sk: Value<[MerkleNode; MERKLE_DEPTH_ORCHARD]>, // path to the secret key root_sk
     pub coin_timestamp: Value<pallas::Base>,
     pub coin_nonce: Value<pallas::Base>,
@@ -163,8 +158,6 @@ impl Circuit<pallas::Base> for LeadContract {
             meta.advice_column(),
             meta.advice_column(),
             meta.advice_column(),
-            //meta.advice_column(),
-            //meta.advice_column(),
         ];
 
         let table_idx = meta.lookup_table_column();
@@ -255,9 +248,7 @@ impl Circuit<pallas::Base> for LeadContract {
                 k_values_table,
             )
 
-    };
-
-        //let evenbits_config = EvenBitsChip::<pallas::Base, WORD_BITS>::configure(meta);
+        };
 
         let arith_config = ArithChip::configure(meta, advices[7], advices[8], advices[6]);
 
@@ -295,76 +286,77 @@ impl Circuit<pallas::Base> for LeadContract {
         // load witnesses
         // ===============
 
+        /// constant identity value 1
         let one = self.load_private(
             layouter.namespace(|| "one"),
             config.advices[0],
             Value::known(pallas::Base::one()),
         )?;
 
+        /// prefix to the pseudo-random-function that prefix input
+        /// to the nullifier poseidon hash
         let prf_nullifier_prefix_base = self.load_private(
             layouter.namespace(|| "PRF NULLIFIER PREFIX BASE"),
             config.advices[0],
             Value::known(pallas::Base::from(PRF_NULLIFIER_PREFIX)),
         )?;
 
+        /// constant value 0
         let zero = self.load_private(
             layouter.namespace(|| "one"),
             config.advices[0],
             Value::known(pallas::Base::zero()),
         )?;
 
-        // coin_timestamp
+        /// staking coin timestamp
         let coin_timestamp = self.load_private(
             layouter.namespace(|| "load coin time stamp"),
             config.advices[0],
             self.coin_timestamp,
         )?;
 
+        /// staking coin nonce
         let coin_nonce: AssignedCell<Fp, Fp> = self.load_private(
             layouter.namespace(|| "load coin nonce"),
             config.advices[0],
             self.coin_nonce,
         )?;
 
+        /// staking coin value
         let coin_value = self.load_private(
             layouter.namespace(|| "load coin value"),
             config.advices[0],
             self.value,
         )?;
-        let coin_pk: AssignedCell<Fp, Fp> = self.load_private(
-            layouter.namespace(|| "load coin time stamp"),
+
+        /// staking coin secret key
+        let _root_sk = self.load_private(
+            layouter.namespace(|| ""),
             config.advices[0],
-            self.coin_pk,
+            self.root_sk
         )?;
 
-
-        //used for fine tuning the leader election frequency
+        /// scalar 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(10241024)),
+            Value::known(pallas::Base::from(1024)),
         )?;
-        //leadership coefficient
 
+        /// leadership coefficient used for fine-tunning leader election frequency
         let c = self.load_private(
             layouter.namespace(|| ""),
             config.advices[0],
             Value::known(pallas::Base::one()), // note! this parameter to be tuned.
         )?;
 
-
-        let _root_sk =
-            self.load_private(layouter.namespace(|| ""), config.advices[0], self.root_sk)?;
-
-
-
-        // ================
-        // coin public key pk=PRF_{root_sk}(tau)
-        // ================
+        /// coin public key pk=PRF_{root_sk}(tau)
+        /// coin public key is pseudo random hash of concatenation of the following:
+        /// coin timestamp, and root of coin's secret key.
         let coin_pk_commit : AssignedCell<Fp,Fp> = {
             let poseidon_message = [
                 coin_timestamp.clone(),
-                _root_sk.clone()
+                _root_sk.clone(),
             ];
             let poseidon_hasher = PoseidonHash::<_, _, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init(
                 config.poseidon_chip(),
@@ -376,22 +368,11 @@ impl Circuit<pallas::Base> for LeadContract {
             let poseidon_output: AssignedCell<Fp, Fp> = poseidon_output;
             poseidon_output
         };
-        // constrain coin's pub key x value
-
-        layouter.constrain_instance(
-            coin_pk_commit.cell(),
-            config.primary,
-            LEAD_COIN_PK_OFFSET,
-        )?;
 
-        // =================
-        // nonce constraints derived from previous coin's nonce
-        // =================
 
-        // =============
-        // constrain coin c1 serial number sn=PRF_{root_sk}(nonce)
-        // =============
-        // m*G_1
+        /// coin c1 serial number sn=PRF_{root_sk}(nonce)
+        /// coin's serial number is derived from coin nonce (sampled at random)
+        /// and root of the coin's secret key sampled an random.
         let sn_commit : AssignedCell<Fp,Fp> = {
             let poseidon_message = [
                 coin_nonce.clone(),
@@ -407,34 +388,28 @@ impl Circuit<pallas::Base> for LeadContract {
             let poseidon_output: AssignedCell<Fp, Fp> = poseidon_output;
             poseidon_output
         };
-        // constrain coin's pub key x value
-        layouter.constrain_instance(
-            sn_commit.cell(),
-            config.primary,
-            LEAD_COIN_SERIAL_NUMBER_OFFSET,
-        )?;
-
-        let nullifier_msg : AssignedCell<Fp,Fp> = {
-            let poseidon_message =  [
-                prf_nullifier_prefix_base.clone(),
-                coin_pk.clone(),
-                coin_value.clone(),
-                coin_nonce.clone(),
-            ];
-            let poseidon_hasher = PoseidonHash::<_, _, poseidon::P128Pow5T3, poseidon::ConstantLength<4>, 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
-        };
 
+        /// commitment to the staking coin
+        /// coin commiment H=COMMIT(PRF(prefix||pk||V||nonce), r)
         let com = {
-            // ================================================
-            // coin commiment H=COMMIT(pk||V||nonce||r)
-            // ================================================
+            /// coin c1 nullifier is a commitment of the following
+            /// nullifier input
+            let nullifier_msg : AssignedCell<Fp,Fp> = {
+                let poseidon_message =  [
+                    prf_nullifier_prefix_base.clone(),
+                    coin_pk_commit.clone(),
+                    coin_value.clone(),
+                    coin_nonce.clone(),
+                ];
+                let poseidon_hasher = PoseidonHash::<_, _, poseidon::P128Pow5T3, poseidon::ConstantLength<4>, 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"), nullifier_msg)?
         };
@@ -454,29 +429,36 @@ impl Circuit<pallas::Base> for LeadContract {
         let coin_commit_x: AssignedCell<Fp, Fp> = coin_commit.inner().x();
         let coin_commit_y: AssignedCell<Fp, Fp> = coin_commit.inner().y();
 
-        layouter.constrain_instance(
-            coin_commit_x.cell(),
-            config.primary,
-            LEAD_COIN_COMMIT_X_OFFSET,
-        )?;
+        /// nonce2  =  PRF_{root_sk}(coin_nonce)
+        /// poured coin derived nonce as a poseidon of the previous nonce, and
+        /// root of secret key.
+        let coin2_nonce : AssignedCell<Fp,Fp> = {
+            let poseidon_message = [
+                coin_nonce.clone(),
+                _root_sk.clone()
+            ];
+            let poseidon_hasher = PoseidonHash::<_, _, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init(
+                config.poseidon_chip(),
+                layouter.namespace(|| "Poseidon init"),
+            )?;
 
-        // constrain coin's pub key y value
-        layouter.constrain_instance(
-            coin_commit_y.cell(),
-            config.primary,
-            LEAD_COIN_COMMIT_Y_OFFSET,
-        )?;
+            let poseidon_output =
+                poseidon_hasher.hash(layouter.namespace(|| "Poseidon hash"), poseidon_message)?;
+            let poseidon_output: AssignedCell<Fp, Fp> = poseidon_output;
+            poseidon_output
+        };
 
-        // ================================================
-        // coin2 commiment H=COMMIT(pk||V||nonce2||r2)
-        // ================================================
+        /// coin2 commiment H=COMMIT(PRF(pk||V||nonce2), r2)
+        /// poured coin's commitment is a nullifier
         let com2 = {
+            /// coin2's commitment input body as a poseidon of input concatenation of
+            /// public key, stake, and poured coin's nonce.
             let nullifier2_msg : AssignedCell<Fp,Fp> = {
                 let poseidon_message = [
                     prf_nullifier_prefix_base.clone(),
-                    coin_pk.clone(),
+                    coin_pk_commit.clone(),
                     coin_value.clone(),
-                    coin_nonce.clone(),
+                    coin2_nonce.clone(),
                 ];
                 let poseidon_hasher = PoseidonHash::<_, _, poseidon::P128Pow5T3, poseidon::ConstantLength<4>, 3, 2>::init(
                     config.poseidon_chip(),
@@ -506,46 +488,7 @@ impl Circuit<pallas::Base> for LeadContract {
         let coin2_commit_y: AssignedCell<Fp, Fp> = coin2_commit.inner().y();
 
 
-      layouter.constrain_instance(
-            coin2_commit_x.cell(),
-            config.primary,
-            LEAD_COIN_COMMIT2_X_OFFSET,
-        )?;
-        // constrain coin's pub key y value
-        layouter.constrain_instance(
-            coin2_commit_y.cell(),
-            config.primary,
-            LEAD_COIN_COMMIT2_Y_OFFSET,
-    )?;
-
-        // ===============
-        // nonce2  =  PRF_{root_sk}(coin_nonce)
-        // ===============
-        let coin2_nonce : AssignedCell<Fp,Fp> = {
-        let poseidon_message = [
-        coin_nonce.clone(),
-        _root_sk.clone()
-        ];
-        let poseidon_hasher = PoseidonHash::<_, _, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 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
-    };
-        layouter.constrain_instance(
-        coin2_nonce.clone().cell(),
-        config.primary,
-        LEAD_COIN_NONCE2_OFFSET,
-    )?;
-
-        // ===========================
-        // path is valid path to cm1
-        // ===========================
-
+        /// path is valid path to staked coin's commitment
         let path : Value<[pallas::Base;MERKLE_DEPTH_ORCHARD]> = self.path.map(|typed_path| gen_const_array(|i| typed_path[i].inner()));
 
         let merkle_inputs = MerklePath::construct(
@@ -565,20 +508,12 @@ impl Circuit<pallas::Base> for LeadContract {
             )?;
             res
         };
+        let computed_final_root = merkle_inputs .calculate_root(layouter.namespace(|| "calculate root"), coin_commit_prod)?;
 
-        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)
-        //================================
+        /// lhs of the leader election lottery
+        /// *  y as COMIT(root_sk||nonce, mau_y)
+        /// beging the commitment to the coin's secret key, coin's nonce, and
+        /// random value deriven from the epoch sampled random eta.
         let y_commit_msg : AssignedCell<Fp,Fp> = {
             let poseidon_message = [
                 _root_sk.clone(),
@@ -653,6 +588,60 @@ impl Circuit<pallas::Base> for LeadContract {
             true
         )?;
 
+        layouter.constrain_instance(
+            coin_commit_x.cell(),
+            config.primary,
+            LEAD_COIN_COMMIT_X_OFFSET,
+        )?;
+
+        // constrain coin's pub key y value
+        layouter.constrain_instance(
+            coin_commit_y.cell(),
+            config.primary,
+            LEAD_COIN_COMMIT_Y_OFFSET,
+        )?;
+
+
+        layouter.constrain_instance(
+            coin2_commit_x.cell(),
+            config.primary,
+            LEAD_COIN_COMMIT2_X_OFFSET,
+        )?;
+        // constrain coin's pub key y value
+        layouter.constrain_instance(
+            coin2_commit_y.cell(),
+            config.primary,
+            LEAD_COIN_COMMIT2_Y_OFFSET,
+        )?;
+
+
+        layouter.constrain_instance(
+            coin2_nonce.clone().cell(),
+            config.primary,
+            LEAD_COIN_NONCE2_OFFSET,
+        )?;
+
+
+        layouter.constrain_instance(
+            computed_final_root.cell(),
+            config.primary,
+            LEAD_COIN_COMMIT_PATH_OFFSET,
+        )?;
+
+
+        layouter.constrain_instance(
+        coin_pk_commit.cell(),
+        config.primary,
+        LEAD_COIN_PK_OFFSET,
+        )?;
+
+        // constrain coin's pub key x value
+        layouter.constrain_instance(
+            sn_commit.cell(),
+            config.primary,
+            LEAD_COIN_SERIAL_NUMBER_OFFSET,
+        )?;
+
         Ok(())
     }
 }