ソースを参照

add calculate root function

narodnik 4 年 前
コミット
aa877915aa
3 ファイル変更97 行追加5 行削除
  1. 88 2
      example/halo2/src/vm2.rs
  2. 5 0
      example/halo2/src/vm2_serial.rs
  3. 4 3
      script/zkas/types.py

+ 88 - 2
example/halo2/src/vm2.rs

@@ -16,6 +16,11 @@ use halo2_gadgets::{
         StateWord, Word,
     },
     primitives::poseidon::{ConstantLength, P128Pow5T3},
+    sinsemilla::{
+        chip::{SinsemillaChip, SinsemillaConfig},
+        merkle::chip::{MerkleChip, MerkleConfig},
+        merkle::MerklePath,
+    },
     utilities::{
         lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
     },
@@ -24,7 +29,10 @@ use pasta_curves::pallas;
 
 use crate::{
     arith_chip::{ArithmeticChip, ArithmeticChipConfig},
-    constants::OrchardFixedBases,
+    constants::{
+        sinsemilla::{OrchardCommitDomains, OrchardHashDomains, MERKLE_CRH_PERSONALIZATION},
+        OrchardFixedBases,
+    },
     error::{Error, Result},
 };
 
@@ -49,6 +57,7 @@ pub enum ZkFunctionCall {
     EcAdd(ArgIdx, ArgIdx),
     EcGetX(ArgIdx),
     EcGetY(ArgIdx),
+    CalculateMerkleRoot(ArgIdx, ArgIdx),
 }
 
 pub struct ZkBinary {
@@ -71,6 +80,8 @@ pub struct MintConfig {
     pub q_add: Selector,
     pub advices: [Column<Advice>; 10],
     pub ecc_config: EccConfig,
+    pub merkle_config_1: MerkleConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
+    pub merkle_config_2: MerkleConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
     pub poseidon_config: PoseidonConfig<pallas::Base>,
     pub arith_config: ArithmeticChipConfig,
 }
@@ -87,6 +98,18 @@ impl MintConfig {
     pub fn arithmetic_chip(&self) -> ArithmeticChip {
         ArithmeticChip::construct(self.arith_config.clone())
     }
+
+    fn merkle_chip_1(
+        &self,
+    ) -> MerkleChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
+        MerkleChip::construct(self.merkle_config_1.clone())
+    }
+
+    fn merkle_chip_2(
+        &self,
+    ) -> MerkleChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
+        MerkleChip::construct(self.merkle_config_2.clone())
+    }
 }
 
 #[derive(Clone, Debug)]
@@ -232,6 +255,11 @@ impl<'a> Circuit<pallas::Base> for ZkCircuit<'a> {
         let q_add = meta.selector();
 
         let table_idx = meta.lookup_table_column();
+        let lookup = (
+            table_idx,
+            meta.lookup_table_column(),
+            meta.lookup_table_column(),
+        );
 
         let primary = meta.instance_column();
 
@@ -277,11 +305,48 @@ impl<'a> Circuit<pallas::Base> for ZkCircuit<'a> {
 
         let arith_config = ArithmeticChip::configure(meta);
 
+        // Configuration for a Sinsemilla hash instantiation and a
+        // Merkle hash instantiation using this Sinsemilla instance.
+        // Since the Sinsemilla config uses only 5 advice columns,
+        // we can fit two instances side-by-side.
+        let (sinsemilla_config_1, merkle_config_1) = {
+            let sinsemilla_config_1 = SinsemillaChip::configure(
+                meta,
+                advices[..5].try_into().unwrap(),
+                advices[6],
+                lagrange_coeffs[0],
+                lookup,
+                range_check.clone(),
+            );
+            let merkle_config_1 = MerkleChip::configure(meta, sinsemilla_config_1.clone());
+            (sinsemilla_config_1, merkle_config_1)
+        };
+
+        // Configuration for a Sinsemilla hash instantiation and a
+        // Merkle hash instantiation using this Sinsemilla instance.
+        // Since the Sinsemilla config uses only 5 advice columns,
+        // we can fit two instances side-by-side.
+        let (sinsemilla_config_2, merkle_config_2) = {
+            let sinsemilla_config_2 = SinsemillaChip::configure(
+                meta,
+                advices[5..].try_into().unwrap(),
+                advices[7],
+                lagrange_coeffs[1],
+                lookup,
+                range_check,
+            );
+            let merkle_config_2 = MerkleChip::configure(meta, sinsemilla_config_2.clone());
+
+            (sinsemilla_config_2, merkle_config_2)
+        };
+
         MintConfig {
             primary,
             q_add,
             advices,
             ecc_config,
+            merkle_config_1,
+            merkle_config_2,
             poseidon_config,
             arith_config,
         }
@@ -292,9 +357,11 @@ impl<'a> Circuit<pallas::Base> for ZkCircuit<'a> {
         config: Self::Config,
         mut layouter: impl Layouter<pallas::Base>,
     ) -> std::result::Result<(), plonk::Error> {
-        let ecc_chip = config.ecc_chip();
         let arith_chip = config.arithmetic_chip();
 
+        // Construct the ECC chip.
+        let ecc_chip = config.ecc_chip();
+
         let mut stack_base = Vec::new();
         let mut stack_scalar = Vec::new();
         let mut stack_ec_point = Vec::new();
@@ -474,6 +541,25 @@ impl<'a> Circuit<pallas::Base> for ZkCircuit<'a> {
                     let y = arg.inner().y();
                     stack_base.push(y);
                 }
+                ZkFunctionCall::CalculateMerkleRoot(path_idx, leaf_idx) => {
+                    assert!(*path_idx < stack_merkle_path.len());
+                    assert!(*leaf_idx < stack_base.len());
+
+                    let (leaf_pos, path) = &stack_merkle_path[*path_idx];
+                    let leaf = &stack_base[*leaf_idx];
+
+                    let path = MerklePath {
+                        chip_1: config.merkle_chip_1(),
+                        chip_2: config.merkle_chip_2(),
+                        domain: OrchardHashDomains::MerkleCrh,
+                        leaf_pos: leaf_pos.clone(),
+                        path: path.clone(),
+                    };
+
+                    let root =
+                        path.calculate_root(layouter.namespace(|| "calculate root"), leaf.clone())?;
+                    stack_base.push(root);
+                }
             }
         }
 

+ 5 - 0
example/halo2/src/vm2_serial.rs

@@ -24,6 +24,7 @@ impl Decodable for ZkType {
             1 => Ok(Self::Scalar),
             2 => Ok(Self::EcPoint),
             3 => Ok(Self::EcFixedPoint),
+            4 => Ok(Self::MerklePath),
             _i => Err(Error::BadOperationType),
         }
     }
@@ -63,6 +64,10 @@ impl Decodable for ZkFunctionCall {
             )),
             6 => Ok(Self::EcGetX(ReadExt::read_u32(&mut d)? as usize)),
             7 => Ok(Self::EcGetY(ReadExt::read_u32(&mut d)? as usize)),
+            8 => Ok(Self::CalculateMerkleRoot(
+                ReadExt::read_u32(&mut d)? as usize,
+                ReadExt::read_u32(&mut d)? as usize,
+            )),
             _i => Err(Error::BadOperationType),
         }
     }

+ 4 - 3
script/zkas/types.py

@@ -23,7 +23,7 @@ FUNC_ID_EC_MUL                  = 4
 FUNC_ID_EC_ADD                  = 5
 FUNC_ID_EC_GET_X                = 6
 FUNC_ID_EC_GET_Y                = 7
-FUNC_ID_CALCULATE_ROOT          = 8
+FUNC_ID_CALCULATE_MERKLE_ROOT   = 8
 
 class FuncFormat:
 
@@ -66,8 +66,9 @@ function_formats = {
     "ec_get_y": FuncFormat(
         FUNC_ID_EC_GET_Y,       [TYPE_ID_BASE],     [TYPE_ID_EC_POINT]
     ),
-    "calculate_root": FuncFormat(
-        FUNC_ID_CALCULATE_ROOT, [TYPE_ID_BASE],     [TYPE_ID_MERKLE_PATH,
+    "calculate_merkle_root": FuncFormat(
+        FUNC_ID_CALCULATE_MERKLE_ROOT, 
+                                [TYPE_ID_BASE],     [TYPE_ID_MERKLE_PATH,
                                                      TYPE_ID_BASE]
     ),
 }