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

zk/vm: Implement zero_cond opcode.

parazyd 3 лет назад
Родитель
Сommit
281aa87faf
6 измененных файлов с 42 добавлено и 6 удалено
  1. 1 0
      contrib/zk.lang
  2. 1 1
      contrib/zk.lua
  3. 1 1
      contrib/zk.vim
  4. 2 1
      src/consensus/fees.rs
  5. 30 3
      src/zk/vm.rs
  6. 7 0
      src/zkas/opcode.rs

+ 1 - 0
contrib/zk.lang

@@ -69,6 +69,7 @@
       <keyword>less_than_loose</keyword>
       <keyword>bool_check</keyword>
       <keyword>cond_select</keyword>
+      <keyword>zero_cond</keyword>
       <keyword>witness_base</keyword>
       <keyword>constrain_equal_base</keyword>
       <keyword>constrain_equal_point</keyword>

+ 1 - 1
contrib/zk.lua

@@ -43,7 +43,7 @@ local instruction = token('instruction', word_match{
   'base_add', 'base_mul', 'base_sub',
   'poseidon_hash', 'merkle_root',
   'range_check', 'less_than_strict', 'less_than_loose', 'bool_check',
-  'cond_select', 'witness_base',
+  'cond_select', 'zero_cond', 'witness_base',
   'constrain_equal_base', 'constrain_equal_point',
   'constrain_instance', 'debug',
 })

+ 1 - 1
contrib/zk.vim

@@ -23,7 +23,7 @@ syn keyword zkasInstruction
     \ base_add base_mul base_sub
     \ poseidon_hash merkle_root
     \ range_check less_than_strict less_than_loose bool_check
-    \ cond_select witness_base
+    \ cond_select zero_cond witness_base
     \ constrain_equal_base constrain_equal_point
     \ constrain_instance debug
 

+ 2 - 1
src/consensus/fees.rs

@@ -72,7 +72,8 @@ pub fn circuit_gas_use(zkbin: &ZkBinary) -> u64 {
             Opcode::LessThanStrict => 100,
             Opcode::LessThanLoose => 100,
             Opcode::BoolCheck => 20,
-            Opcode::CondSelect => 30,
+            Opcode::CondSelect => 10,
+            Opcode::ZeroCondSelect => 10,
             Opcode::ConstrainEqualBase => 10,
             Opcode::ConstrainEqualPoint => 20,
             Opcode::ConstrainInstance => 10,

+ 30 - 3
src/zk/vm.rs

@@ -58,6 +58,7 @@ use super::{
         less_than::{LessThanChip, LessThanConfig},
         native_range_check::{NativeRangeCheckChip, NativeRangeCheckConfig},
         small_range_check::{SmallRangeCheckChip, SmallRangeCheckConfig},
+        zero_cond::{ZeroCondChip, ZeroCondConfig},
     },
 };
 use crate::zkas::{
@@ -82,6 +83,7 @@ pub struct VmConfig {
     lessthan_config: LessThanConfig<3, 253, 85>,
     boolcheck_config: SmallRangeCheckConfig,
     condselect_config: ConditionalSelectConfig<pallas::Base>,
+    zerocond_config: ZeroCondConfig<pallas::Base>,
 }
 
 impl VmConfig {
@@ -112,6 +114,10 @@ impl VmConfig {
     fn condselect_chip(&self) -> ConditionalSelectChip<pallas::Base> {
         ConditionalSelectChip::construct(self.condselect_config.clone(), ())
     }
+
+    fn zerocond_chip(&self) -> ZeroCondChip<pallas::Base> {
+        ZeroCondChip::construct(self.zerocond_config.clone())
+    }
 }
 
 #[derive(Clone)]
@@ -271,10 +277,13 @@ impl Circuit<pallas::Base> for ZkCircuit {
         // chip with a range of 2, which enforces one bit, i.e. 0 or 1.
         let boolcheck_config = SmallRangeCheckChip::configure(meta, advices[9], 2);
 
-        // Cnfiguration for the conditional selection chip
+        // Configuration for the conditional selection chip
         let condselect_config =
             ConditionalSelectChip::configure(meta, advices[1..5].try_into().unwrap());
 
+        // Configuration for the zero_cond selection chip
+        let zerocond_config = ZeroCondChip::configure(meta, advices[1..5].try_into().unwrap());
+
         VmConfig {
             primary,
             advices,
@@ -290,6 +299,7 @@ impl Circuit<pallas::Base> for ZkCircuit {
             lessthan_config,
             boolcheck_config,
             condselect_config,
+            zerocond_config,
         }
     }
 
@@ -348,9 +358,12 @@ impl Circuit<pallas::Base> for ZkCircuit {
         // Construct the boolean check chip.
         let boolcheck_chip = SmallRangeCheckChip::construct(config.boolcheck_config.clone());
 
-        // Construct the conditional selectiono chip
+        // Construct the conditional selection chip
         let condselect_chip = config.condselect_chip();
 
+        // Construct the zero_cond selection chip
+        let zerocond_chip = config.zerocond_chip();
+
         // ==========================
         // Constants setup
         // ==========================
@@ -850,6 +863,20 @@ impl Circuit<pallas::Base> for ZkCircuit {
                     heap.push(HeapVar::Base(out));
                 }
 
+                Opcode::ZeroCondSelect => {
+                    trace!(target: "zk::vm", "Executing `ZeroCondSelect{:?}` opcode", opcode.1);
+                    let args = &opcode.1;
+
+                    let lhs: AssignedCell<Fp, Fp> = heap[args[0].1].clone().into();
+                    let rhs: AssignedCell<Fp, Fp> = heap[args[1].1].clone().into();
+
+                    let out: AssignedCell<Fp, Fp> =
+                        zerocond_chip.assign(layouter.namespace(|| "zero_cond"), lhs, rhs)?;
+
+                    trace!(target: "zk::vm", "Pushing assignment to heap address {}", heap.len());
+                    heap.push(HeapVar::Base(out));
+                }
+
                 Opcode::ConstrainEqualBase => {
                     trace!(target: "zk::vm", "Executing `ConstrainEqualBase{:?}` opcode", opcode.1);
                     let args = &opcode.1;
@@ -902,7 +929,7 @@ impl Circuit<pallas::Base> for ZkCircuit {
                     println!("[ZKVM DEBUG] {:#?}", heap[args[0].1]);
                 }
 
-                _ => {
+                Opcode::Noop => {
                     error!(target: "zk::vm", "Unsupported opcode");
                     return Err(plonk::Error::Synthesis)
                 }

+ 7 - 0
src/zkas/opcode.rs

@@ -81,6 +81,9 @@ pub enum Opcode {
     /// Conditionally select between two base field elements given a boolean
     CondSelect = 0x60,
 
+    /// Conditionally select between a and b (return a if a is zero, and b if a is nonzero)
+    ZeroCondSelect = 0x61,
+
     /// Constrain equality of two Base field elements inside the circuit
     ConstrainEqualBase = 0xe0,
 
@@ -115,6 +118,7 @@ impl Opcode {
             "less_than_loose" => Some(Self::LessThanLoose),
             "bool_check" => Some(Self::BoolCheck),
             "cond_select" => Some(Self::CondSelect),
+            "zero_cond" => Some(Self::ZeroCondSelect),
             "constrain_equal_base" => Some(Self::ConstrainEqualBase),
             "constrain_equal_point" => Some(Self::ConstrainEqualPoint),
             "constrain_instance" => Some(Self::ConstrainInstance),
@@ -143,6 +147,7 @@ impl Opcode {
             0x52 => Some(Self::LessThanLoose),
             0x53 => Some(Self::BoolCheck),
             0x60 => Some(Self::CondSelect),
+            0x61 => Some(Self::ZeroCondSelect),
             0xe0 => Some(Self::ConstrainEqualBase),
             0xe1 => Some(Self::ConstrainEqualPoint),
             0xf0 => Some(Self::ConstrainInstance),
@@ -203,6 +208,8 @@ impl Opcode {
                 (vec![VarType::Base], vec![VarType::Base, VarType::Base, VarType::Base])
             }
 
+            Opcode::ZeroCondSelect => (vec![VarType::Base], vec![VarType::Base, VarType::Base]),
+
             Opcode::ConstrainEqualBase => (vec![], vec![VarType::Base, VarType::Base]),
 
             Opcode::ConstrainEqualPoint => (vec![], vec![VarType::EcPoint, VarType::EcPoint]),